2010-06-07 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                                         if (base_tparam.InterfacesDefined != null)
984                                                 tp.Type.Interfaces = new List<TypeSpec> (base_tparam.InterfacesDefined);
985
986                                         tp.Type.BaseType = base_tparam.BaseType;
987                                 } else if (MethodData.implementing != null) {
988                                         var base_tp = MethodData.implementing.Constraints[i];
989                                         if (!tp.Type.HasSameConstraintsImplementation (base_tp)) {
990                                                 Report.SymbolRelatedToPreviousError (MethodData.implementing);
991                                                 Report.Error (425, Location,
992                                                         "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",
993                                                         tp.GetSignatureForError (), GetSignatureForError (), base_tp.GetSignatureForError (), MethodData.implementing.GetSignatureForError ());
994                                         }
995                                 }
996                         }
997                 }
998
999                 //
1000                 // Creates the type
1001                 //
1002                 public override bool Define ()
1003                 {
1004                         if (type_expr.Type == TypeManager.void_type && parameters.IsEmpty && MemberName.Arity == 0 && MemberName.Name == Destructor.MetadataName) {
1005                                 Report.Warning (465, 1, Location, "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
1006                         }
1007
1008                         if (!base.Define ())
1009                                 return false;
1010
1011                         if (partialMethodImplementation != null && IsPartialDefinition)
1012                                 MethodBuilder = partialMethodImplementation.MethodBuilder;
1013
1014                         if (RootContext.StdLib && TypeManager.IsSpecialType (ReturnType)) {
1015                                 Error1599 (Location, ReturnType, Report);
1016                                 return false;
1017                         }
1018
1019                         if (CurrentTypeParameters == null) {
1020                                 if (base_method != null) {
1021                                         if (parameters.Count == 1 && ParameterTypes[0] == TypeManager.object_type && Name == "Equals")
1022                                                 Parent.PartialContainer.Mark_HasEquals ();
1023                                         else if (parameters.IsEmpty && Name == "GetHashCode")
1024                                                 Parent.PartialContainer.Mark_HasGetHashCode ();
1025                                 }
1026                                         
1027                         } else {
1028                                 DefineTypeParameters ();
1029                         }
1030
1031                         if (block != null && block.IsIterator && !(Parent is IteratorStorey)) {
1032                                 //
1033                                 // Current method is turned into automatically generated
1034                                 // wrapper which creates an instance of iterator
1035                                 //
1036                                 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
1037                                 ModFlags |= Modifiers.DEBUGGER_HIDDEN;
1038                         }
1039
1040                         if ((ModFlags & Modifiers.STATIC) == 0)
1041                                 return true;
1042
1043                         if (parameters.HasExtensionMethodType) {
1044                                 if (Parent.PartialContainer.IsStatic && !Parent.IsGeneric) {
1045                                         if (!Parent.IsTopLevel)
1046                                                 Report.Error (1109, Location, "`{0}': Extension methods cannot be defined in a nested class",
1047                                                         GetSignatureForError ());
1048
1049                                         PredefinedAttribute pa = PredefinedAttributes.Get.Extension;
1050                                         if (!pa.IsDefined) {
1051                                                 Report.Error (1110, Location,
1052                                                         "`{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",
1053                                                         GetSignatureForError ());
1054                                         }
1055
1056                                         ModFlags |= Modifiers.METHOD_EXTENSION;
1057                                         Parent.PartialContainer.ModFlags |= Modifiers.METHOD_EXTENSION;
1058                                         Spec.DeclaringType.SetExtensionMethodContainer ();
1059                                         CodeGen.Assembly.HasExtensionMethods = true;
1060                                 } else {
1061                                         Report.Error (1106, Location, "`{0}': Extension methods must be defined in a non-generic static class",
1062                                                 GetSignatureForError ());
1063                                 }
1064                         }
1065
1066                         //
1067                         // This is used to track the Entry Point,
1068                         //
1069                         if (RootContext.NeedsEntryPoint &&
1070                                 Name == "Main" &&
1071                                 (RootContext.MainClass == null ||
1072                                 RootContext.MainClass == Parent.TypeBuilder.FullName)){
1073                                 if (IsEntryPoint ()) {
1074
1075                                         if (RootContext.EntryPoint == null) {
1076                                                 if (Parent.IsGeneric || MemberName.IsGeneric) {
1077                                                         Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type",
1078                                                                 GetSignatureForError ());
1079                                                 } else {
1080                                                         SetIsUsed ();
1081                                                         RootContext.EntryPoint = this;
1082                                                 }
1083                                         } else {
1084                                                 Error_DuplicateEntryPoint (RootContext.EntryPoint);
1085                                                 Error_DuplicateEntryPoint (this);
1086                                         }
1087                                 } else {
1088                                         Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point",
1089                                                 GetSignatureForError ());
1090                                 }
1091                         }
1092
1093                         return true;
1094                 }
1095
1096                 //
1097                 // Emits the code
1098                 // 
1099                 public override void Emit ()
1100                 {
1101                         try {
1102                                 Report.Debug (64, "METHOD EMIT", this, MethodBuilder, Location, Block, MethodData);
1103                                 if (IsPartialDefinition) {
1104                                         //
1105                                         // Use partial method implementation builder for partial method declaration attributes
1106                                         //
1107                                         if (partialMethodImplementation != null) {
1108                                                 MethodBuilder = partialMethodImplementation.MethodBuilder;
1109                                                 return;
1110                                         }
1111                                 } else if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.PartialDefinitionExists) == 0) {
1112                                         Report.Error (759, Location, "A partial method `{0}' implementation is missing a partial method declaration",
1113                                                 GetSignatureForError ());
1114                                 }
1115
1116                                 if (CurrentTypeParameters != null) {
1117                                         var ge = type_expr as GenericTypeExpr;
1118                                         if (ge != null)
1119                                                 ge.CheckConstraints (this);
1120
1121                                         foreach (Parameter p in parameters.FixedParameters) {
1122                                                 ge = p.TypeExpression as GenericTypeExpr;
1123                                                 if (ge != null)
1124                                                         ge.CheckConstraints (this);
1125                                         }
1126
1127                                         for (int i = 0; i < CurrentTypeParameters.Length; ++i) {
1128                                                 var tp = CurrentTypeParameters [i];
1129                                                 tp.CheckGenericConstraints ();
1130                                                 tp.Emit ();
1131                                         }
1132                                 }
1133
1134                                 base.Emit ();
1135                                 
1136                                 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
1137                                         PredefinedAttributes.Get.Extension.EmitAttribute (MethodBuilder);
1138                         } catch {
1139                                 Console.WriteLine ("Internal compiler error at {0}: exception caught while emitting {1}",
1140                                                    Location, MethodBuilder);
1141                                 throw;
1142                         }
1143                 }
1144
1145                 public override bool EnableOverloadChecks (MemberCore overload)
1146                 {
1147                         // TODO: It can be deleted when members will be defined in correct order
1148                         if (overload is Operator)
1149                                 return overload.EnableOverloadChecks (this);
1150
1151                         if (overload is Indexer)
1152                                 return false;
1153
1154                         return base.EnableOverloadChecks (overload);
1155                 }
1156
1157                 public static void Error1599 (Location loc, TypeSpec t, Report Report)
1158                 {
1159                         Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t));
1160                 }
1161
1162                 protected override bool ResolveMemberType ()
1163                 {
1164                         if (GenericMethod != null) {
1165                                 MethodBuilder = Parent.TypeBuilder.DefineMethod (GetFullName (MemberName), flags);
1166                                 if (!GenericMethod.Define (this))
1167                                         return false;
1168                         }
1169
1170                         return base.ResolveMemberType ();
1171                 }
1172
1173                 public void SetPartialDefinition (Method methodDefinition)
1174                 {
1175                         caching_flags |= Flags.PartialDefinitionExists;
1176                         methodDefinition.partialMethodImplementation = this;
1177
1178                         // Ensure we are always using method declaration parameters
1179                         for (int i = 0; i < methodDefinition.parameters.Count; ++i ) {
1180                                 parameters [i].Name = methodDefinition.parameters [i].Name;
1181                                 parameters [i].DefaultValue = methodDefinition.parameters [i].DefaultValue;
1182                         }
1183
1184                         if (methodDefinition.attributes == null)
1185                                 return;
1186
1187                         if (attributes == null) {
1188                                 attributes = methodDefinition.attributes;
1189                         } else {
1190                                 attributes.Attrs.AddRange (methodDefinition.attributes.Attrs);
1191                         }
1192                 }
1193         }
1194
1195         public abstract class ConstructorInitializer : ExpressionStatement
1196         {
1197                 Arguments argument_list;
1198                 MethodGroupExpr base_constructor_group;
1199
1200                 public ConstructorInitializer (Arguments argument_list, Location loc)
1201                 {
1202                         this.argument_list = argument_list;
1203                         this.loc = loc;
1204                 }
1205
1206                 public Arguments Arguments {
1207                         get {
1208                                 return argument_list;
1209                         }
1210                 }
1211
1212                 public override Expression CreateExpressionTree (ResolveContext ec)
1213                 {
1214                         throw new NotSupportedException ("ET");
1215                 }
1216
1217                 protected override Expression DoResolve (ResolveContext ec)
1218                 {
1219                         eclass = ExprClass.Value;
1220
1221                         // FIXME: Hack
1222                         var caller_builder = (Constructor) ec.MemberContext;
1223
1224                         if (argument_list != null) {
1225                                 bool dynamic;
1226
1227                                 //
1228                                 // Spec mandates that constructor initializer will not have `this' access
1229                                 //
1230                                 using (ec.Set (ResolveContext.Options.BaseInitializer)) {
1231                                         argument_list.Resolve (ec, out dynamic);
1232                                 }
1233
1234                                 if (dynamic) {
1235                                         ec.Report.Error (1975, loc,
1236                                                 "The constructor call cannot be dynamically dispatched within constructor initializer");
1237
1238                                         return null;
1239                                 }
1240                         }
1241
1242                         type = ec.CurrentType;
1243                         if (this is ConstructorBaseInitializer) {
1244                                 if (ec.CurrentType.BaseType == null)
1245                                         return this;
1246
1247                                 type = ec.CurrentType.BaseType;
1248                                 if (ec.CurrentType.IsStruct) {
1249                                         ec.Report.Error (522, loc,
1250                                                 "`{0}': Struct constructors cannot call base constructors", caller_builder.GetSignatureForError ());
1251                                         return this;
1252                                 }
1253                         } else {
1254                                 //
1255                                 // It is legal to have "this" initializers that take no arguments
1256                                 // in structs, they are just no-ops.
1257                                 //
1258                                 // struct D { public D (int a) : this () {}
1259                                 //
1260                                 if (TypeManager.IsStruct (ec.CurrentType) && argument_list == null)
1261                                         return this;                    
1262                         }
1263
1264                         base_constructor_group = MemberLookupFinal (
1265                                 ec, null, type, ConstructorBuilder.ConstructorName, 0, MemberKind.Constructor,
1266                                 BindingRestriction.AccessibleOnly | BindingRestriction.DeclaredOnly,
1267                                 loc) as MethodGroupExpr;
1268                         
1269                         if (base_constructor_group == null)
1270                                 return this;
1271                         
1272                         base_constructor_group = base_constructor_group.OverloadResolve (
1273                                 ec, ref argument_list, false, loc);
1274                         
1275                         if (base_constructor_group == null)
1276                                 return this;
1277
1278                         if (!ec.IsStatic)
1279                                 base_constructor_group.InstanceExpression = ec.GetThis (loc);
1280                         
1281                         var base_ctor = base_constructor_group.BestCandidate;
1282
1283                         // TODO MemberCache: Does it work for inflated types ?
1284                         if (base_ctor == caller_builder.Spec){
1285                                 ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself",
1286                                         caller_builder.GetSignatureForError ());
1287                         }
1288                                                 
1289                         return this;
1290                 }
1291
1292                 public override void Emit (EmitContext ec)
1293                 {
1294                         // It can be null for static initializers
1295                         if (base_constructor_group == null)
1296                                 return;
1297                         
1298                         ec.Mark (loc);
1299
1300                         base_constructor_group.EmitCall (ec, argument_list);
1301                 }
1302
1303                 public override void EmitStatement (EmitContext ec)
1304                 {
1305                         Emit (ec);
1306                 }
1307         }
1308
1309         public class ConstructorBaseInitializer : ConstructorInitializer {
1310                 public ConstructorBaseInitializer (Arguments argument_list, Location l) :
1311                         base (argument_list, l)
1312                 {
1313                 }
1314         }
1315
1316         class GeneratedBaseInitializer: ConstructorBaseInitializer {
1317                 public GeneratedBaseInitializer (Location loc):
1318                         base (null, loc)
1319                 {
1320                 }
1321         }
1322
1323         public class ConstructorThisInitializer : ConstructorInitializer {
1324                 public ConstructorThisInitializer (Arguments argument_list, Location l) :
1325                         base (argument_list, l)
1326                 {
1327                 }
1328         }
1329         
1330         public class Constructor : MethodCore, IMethodData {
1331                 public ConstructorBuilder ConstructorBuilder;
1332                 public ConstructorInitializer Initializer;
1333                 Dictionary<SecurityAction, PermissionSet> declarative_security;
1334                 bool has_compliant_args;
1335
1336                 // <summary>
1337                 //   Modifiers allowed for a constructor.
1338                 // </summary>
1339                 public const Modifiers AllowedModifiers =
1340                         Modifiers.PUBLIC |
1341                         Modifiers.PROTECTED |
1342                         Modifiers.INTERNAL |
1343                         Modifiers.STATIC |
1344                         Modifiers.UNSAFE |
1345                         Modifiers.EXTERN |              
1346                         Modifiers.PRIVATE;
1347
1348                 static readonly string[] attribute_targets = new string [] { "method" };
1349
1350                 //
1351                 // The spec claims that static is not permitted, but
1352                 // my very own code has static constructors.
1353                 //
1354                 public Constructor (DeclSpace parent, string name, Modifiers mod, Attributes attrs, ParametersCompiled args,
1355                                     ConstructorInitializer init, Location loc)
1356                         : base (parent, null, null, mod, AllowedModifiers,
1357                                 new MemberName (name, loc), attrs, args)
1358                 {
1359                         Initializer = init;
1360                 }
1361
1362                 public bool HasCompliantArgs {
1363                         get { return has_compliant_args; }
1364                 }
1365
1366                 public override AttributeTargets AttributeTargets {
1367                         get { return AttributeTargets.Constructor; }
1368                 }
1369
1370                 //
1371                 // Returns true if this is a default constructor
1372                 //
1373                 public bool IsDefault ()
1374                 {
1375                         if ((ModFlags & Modifiers.STATIC) != 0)
1376                                 return parameters.IsEmpty;
1377
1378                         return parameters.IsEmpty &&
1379                                         (Initializer is ConstructorBaseInitializer) &&
1380                                         (Initializer.Arguments == null);
1381                 }
1382
1383                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1384                 {
1385                         if (a.IsValidSecurityAttribute ()) {
1386                                 if (declarative_security == null) {
1387                                         declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
1388                                 }
1389                                 a.ExtractSecurityPermissionSet (declarative_security);
1390                                 return;
1391                         }
1392
1393                         if (a.IsInternalMethodImplAttribute) {
1394                                 is_external_implementation = true;
1395                         }
1396
1397                         ConstructorBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
1398                 }
1399
1400                 protected override bool CheckBase ()
1401                 {
1402                         if ((ModFlags & Modifiers.STATIC) != 0) {
1403                                 if (!parameters.IsEmpty) {
1404                                         Report.Error (132, Location, "`{0}': The static constructor must be parameterless",
1405                                                 GetSignatureForError ());
1406                                         return false;
1407                                 }
1408
1409                                 // the rest can be ignored
1410                                 return true;
1411                         }
1412
1413                         // Check whether arguments were correct.
1414                         if (!DefineParameters (parameters))
1415                                 return false;
1416
1417                         if ((caching_flags & Flags.MethodOverloadsExist) != 0)
1418                                 Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1419
1420                         if (Parent.PartialContainer.Kind == MemberKind.Struct && parameters.IsEmpty) {
1421                                 Report.Error (568, Location, 
1422                                         "Structs cannot contain explicit parameterless constructors");
1423                                 return false;
1424                         }
1425
1426                         CheckProtectedModifier ();
1427                         
1428                         return true;
1429                 }
1430                 
1431                 //
1432                 // Creates the ConstructorBuilder
1433                 //
1434                 public override bool Define ()
1435                 {
1436                         if (ConstructorBuilder != null)
1437                                 return true;
1438
1439                         var ca = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName;
1440                         
1441                         if ((ModFlags & Modifiers.STATIC) != 0) {
1442                                 ca |= MethodAttributes.Static | MethodAttributes.Private;
1443                         } else {
1444                                 ca |= ModifiersExtensions.MethodAttr (ModFlags);
1445                         }
1446
1447                         if (!CheckAbstractAndExtern (block != null))
1448                                 return false;
1449                         
1450                         // Check if arguments were correct.
1451                         if (!CheckBase ())
1452                                 return false;
1453
1454                         ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
1455                                 ca, CallingConventions,
1456                                 parameters.GetMetaInfo ());
1457
1458                         spec = new MethodSpec (MemberKind.Constructor, Parent.Definition, this, TypeManager.void_type, ConstructorBuilder, parameters, ModFlags);
1459                         
1460                         Parent.MemberCache.AddMember (spec);
1461                         
1462                         // It's here only to report an error
1463                         if (block != null && block.IsIterator) {
1464                                 member_type = TypeManager.void_type;
1465                                 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
1466                         }
1467
1468                         return true;
1469                 }
1470
1471                 //
1472                 // Emits the code
1473                 //
1474                 public override void Emit ()
1475                 {
1476                         if (Parent.PartialContainer.IsComImport) {
1477                                 if (!IsDefault ()) {
1478                                         Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
1479                                                 Parent.GetSignatureForError ());
1480                                 }
1481                                 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
1482                         }
1483
1484                         if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1485                                 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (ConstructorBuilder);
1486
1487                         if (OptAttributes != null)
1488                                 OptAttributes.Emit ();
1489
1490                         base.Emit ();
1491
1492                         //
1493                         // If we use a "this (...)" constructor initializer, then
1494                         // do not emit field initializers, they are initialized in the other constructor
1495                         //
1496                         bool emit_field_initializers = ((ModFlags & Modifiers.STATIC) != 0) ||
1497                                 !(Initializer is ConstructorThisInitializer);
1498
1499                         BlockContext bc = new BlockContext (this, block, TypeManager.void_type);
1500                         bc.Set (ResolveContext.Options.ConstructorScope);
1501
1502                         if (emit_field_initializers)
1503                                 Parent.PartialContainer.ResolveFieldInitializers (bc);
1504
1505                         if (block != null) {
1506                                 // If this is a non-static `struct' constructor and doesn't have any
1507                                 // initializer, it must initialize all of the struct's fields.
1508                                 if ((Parent.PartialContainer.Kind == MemberKind.Struct) &&
1509                                         ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
1510                                         block.AddThisVariable (Parent, Location);
1511
1512                                 if (block != null && (ModFlags & Modifiers.STATIC) == 0){
1513                                         if (Parent.PartialContainer.Kind == MemberKind.Class && Initializer == null)
1514                                                 Initializer = new GeneratedBaseInitializer (Location);
1515
1516                                         if (Initializer != null) {
1517                                                 block.AddScopeStatement (new StatementExpression (Initializer));
1518                                         }
1519                                 }
1520                         }
1521
1522                         parameters.ApplyAttributes (ConstructorBuilder);
1523
1524                         SourceMethod source = SourceMethod.Create (Parent, ConstructorBuilder, block);
1525
1526                         if (block != null) {
1527                                 if (block.Resolve (null, bc, parameters, this)) {
1528                                         EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType);
1529                                         ec.With (EmitContext.Options.ConstructorScope, true);
1530
1531                                         if (!ec.HasReturnLabel && bc.HasReturnLabel) {
1532                                                 ec.ReturnLabel = bc.ReturnLabel;
1533                                                 ec.HasReturnLabel = true;
1534                                         }
1535
1536                                         block.Emit (ec);
1537                                 }
1538                         }
1539
1540                         if (source != null)
1541                                 source.CloseMethod ();
1542
1543                         if (declarative_security != null) {
1544                                 foreach (var de in declarative_security) {
1545                                         ConstructorBuilder.AddDeclarativeSecurity (de.Key, de.Value);
1546                                 }
1547                         }
1548
1549                         block = null;
1550                 }
1551
1552                 protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate)
1553                 {
1554                         // Is never override
1555                         bestCandidate = null;
1556                         return null;
1557                 }
1558
1559                 public override string GetSignatureForError()
1560                 {
1561                         return base.GetSignatureForError () + parameters.GetSignatureForError ();
1562                 }
1563
1564                 public override string[] ValidAttributeTargets {
1565                         get {
1566                                 return attribute_targets;
1567                         }
1568                 }
1569
1570                 protected override bool VerifyClsCompliance ()
1571                 {
1572                         if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
1573                                 return false;
1574                         }
1575
1576                         if (!parameters.IsEmpty && Parent.Definition.IsAttribute) {
1577                                 foreach (TypeSpec param in parameters.Types) {
1578                                         if (param.IsArray) {
1579                                                 return true;
1580                                         }
1581                                 }
1582                         }
1583
1584                         has_compliant_args = true;
1585                         return true;
1586                 }
1587
1588                 #region IMethodData Members
1589
1590                 public MemberName MethodName {
1591                         get {
1592                                 return MemberName;
1593                         }
1594                 }
1595
1596                 public TypeSpec ReturnType {
1597                         get {
1598                                 return MemberType;
1599                         }
1600                 }
1601
1602                 public EmitContext CreateEmitContext (ILGenerator ig)
1603                 {
1604                         throw new NotImplementedException ();
1605                 }
1606
1607                 public bool IsExcluded()
1608                 {
1609                         return false;
1610                 }
1611
1612                 GenericMethod IMethodData.GenericMethod {
1613                         get {
1614                                 return null;
1615                         }
1616                 }
1617
1618                 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
1619                 { }
1620
1621                 #endregion
1622         }
1623
1624         /// <summary>
1625         /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
1626         /// </summary>
1627         public interface IMethodData
1628         {
1629                 CallingConventions CallingConventions { get; }
1630                 Location Location { get; }
1631                 MemberName MethodName { get; }
1632                 TypeSpec ReturnType { get; }
1633                 GenericMethod GenericMethod { get; }
1634                 ParametersCompiled ParameterInfo { get; }
1635                 MethodSpec Spec { get; }
1636
1637                 Attributes OptAttributes { get; }
1638                 ToplevelBlock Block { get; set; }
1639
1640                 EmitContext CreateEmitContext (ILGenerator ig);
1641                 string GetSignatureForError ();
1642                 void EmitExtraSymbolInfo (SourceMethod source);
1643         }
1644
1645         //
1646         // Encapsulates most of the Method's state
1647         //
1648         public class MethodData {
1649                 static FieldInfo methodbuilder_attrs_field;
1650                 public readonly IMethodData method;
1651
1652                 public readonly GenericMethod GenericMethod;
1653
1654                 //
1655                 // Are we implementing an interface ?
1656                 //
1657                 public MethodSpec implementing;
1658
1659                 //
1660                 // Protected data.
1661                 //
1662                 protected InterfaceMemberBase member;
1663                 protected Modifiers modifiers;
1664                 protected MethodAttributes flags;
1665                 protected TypeSpec declaring_type;
1666                 protected MethodSpec parent_method;
1667
1668                 MethodBuilder builder;
1669                 public MethodBuilder MethodBuilder {
1670                         get {
1671                                 return builder;
1672                         }
1673                 }
1674
1675                 public TypeSpec DeclaringType {
1676                         get {
1677                                 return declaring_type;
1678                         }
1679                 }
1680
1681                 public MethodData (InterfaceMemberBase member,
1682                                    Modifiers modifiers, MethodAttributes flags, IMethodData method)
1683                 {
1684                         this.member = member;
1685                         this.modifiers = modifiers;
1686                         this.flags = flags;
1687
1688                         this.method = method;
1689                 }
1690
1691                 public MethodData (InterfaceMemberBase member,
1692                                    Modifiers modifiers, MethodAttributes flags, 
1693                                    IMethodData method, MethodBuilder builder,
1694                                    GenericMethod generic, MethodSpec parent_method)
1695                         : this (member, modifiers, flags, method)
1696                 {
1697                         this.builder = builder;
1698                         this.GenericMethod = generic;
1699                         this.parent_method = parent_method;
1700                 }
1701
1702                 public bool Define (DeclSpace parent, string method_full_name, Report Report)
1703                 {
1704                         TypeContainer container = parent.PartialContainer;
1705
1706                         PendingImplementation pending = container.PendingImplementations;
1707                         if (pending != null){
1708                                 implementing = pending.IsInterfaceMethod (method.MethodName, member.InterfaceType, this);
1709
1710                                 if (member.InterfaceType != null){
1711                                         if (implementing == null){
1712                                                 if (member is PropertyBase) {
1713                                                         Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'",
1714                                                                       method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType),
1715                                                                       member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
1716
1717                                                 } else {
1718                                                         Report.Error (539, method.Location,
1719                                                                       "`{0}.{1}' in explicit interface declaration is not a member of interface",
1720                                                                       TypeManager.CSharpName (member.InterfaceType), member.ShortName);
1721                                                 }
1722                                                 return false;
1723                                         }
1724                                         if (implementing.IsAccessor && !(method is AbstractPropertyEventMethod)) {
1725                                                 Report.SymbolRelatedToPreviousError (implementing);
1726                                                 Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
1727                                                         member.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
1728                                                 return false;
1729                                         }
1730                                 } else {
1731                                         if (implementing != null) {
1732                                                 AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod;
1733                                                 if (prop_method == null) {
1734                                                         if (implementing.IsAccessor) {
1735                                                                 Report.SymbolRelatedToPreviousError (implementing);
1736                                                                 Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}'",
1737                                                                         method.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
1738                                                         }
1739                                                 } else if (implementing.DeclaringType.IsInterface) {
1740                                                         if (!implementing.IsAccessor) {
1741                                                                 Report.SymbolRelatedToPreviousError (implementing);
1742                                                                 Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
1743                                                                         method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
1744                                                                 return false;
1745                                                         }
1746                                                         PropertyBase.PropertyMethod pm = prop_method as PropertyBase.PropertyMethod;
1747                                                         if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
1748                                                                 Report.SymbolRelatedToPreviousError (implementing);
1749                                                                 Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'",
1750                                                                         method.GetSignatureForError (), implementing.GetSignatureForError ());
1751                                                                 return false;
1752                                                         }
1753                                                 }
1754                                         }
1755                                 }
1756                         }
1757
1758                         //
1759                         // For implicit implementations, make sure we are public, for
1760                         // explicit implementations, make sure we are private.
1761                         //
1762                         if (implementing != null){
1763                                 //
1764                                 // Setting null inside this block will trigger a more
1765                                 // verbose error reporting for missing interface implementations
1766                                 //
1767                                 // The "candidate" function has been flagged already
1768                                 // but it wont get cleared
1769                                 //
1770                                 if (member.IsExplicitImpl){
1771                                         if (method.ParameterInfo.HasParams && !implementing.Parameters.HasParams) {
1772                                                 Report.SymbolRelatedToPreviousError (implementing);
1773                                                 Report.Error (466, method.Location, "`{0}': the explicit interface implementation cannot introduce the params modifier",
1774                                                         method.GetSignatureForError ());
1775                                                 return false;
1776                                         }
1777                                 } else {
1778                                         if (implementing.DeclaringType.IsInterface) {
1779                                                 //
1780                                                 // If this is an interface method implementation,
1781                                                 // check for public accessibility
1782                                                 //
1783                                                 if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
1784                                                 {
1785                                                         implementing = null;
1786                                                 }
1787                                         } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
1788                                                 // We may never be private.
1789                                                 implementing = null;
1790
1791                                         } else if ((modifiers & Modifiers.OVERRIDE) == 0){
1792                                                 //
1793                                                 // We may be protected if we're overriding something.
1794                                                 //
1795                                                 implementing = null;
1796                                         }
1797                                 }
1798                                         
1799                                 //
1800                                 // Static is not allowed
1801                                 //
1802                                 if ((modifiers & Modifiers.STATIC) != 0){
1803                                         implementing = null;
1804                                 }
1805                         }
1806                         
1807                         //
1808                         // If implementing is still valid, set flags
1809                         //
1810                         if (implementing != null){
1811                                 //
1812                                 // When implementing interface methods, set NewSlot
1813                                 // unless, we are overwriting a method.
1814                                 //
1815                                 if (implementing.DeclaringType.IsInterface){
1816                                         if ((modifiers & Modifiers.OVERRIDE) == 0)
1817                                                 flags |= MethodAttributes.NewSlot;
1818                                 }
1819
1820                                 flags |= MethodAttributes.Virtual | MethodAttributes.HideBySig;
1821
1822                                 // Set Final unless we're virtual, abstract or already overriding a method.
1823                                 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
1824                                         flags |= MethodAttributes.Final;
1825
1826                                 //
1827                                 // clear the pending implementation flag (requires explicit methods to be defined first)
1828                                 //
1829                                 parent.PartialContainer.PendingImplementations.ImplementMethod (method.MethodName,
1830                                         member.InterfaceType, this, member.IsExplicitImpl);
1831
1832                                 //
1833                                 // Update indexer accessor name to match implementing abstract accessor
1834                                 //
1835                                 if (!implementing.DeclaringType.IsInterface && !member.IsExplicitImpl && implementing.IsAccessor)
1836                                         method_full_name = implementing.MemberDefinition.Name;
1837                         }
1838
1839                         DefineMethodBuilder (container, method_full_name, method.ParameterInfo);
1840
1841                         if (builder == null)
1842                                 return false;
1843
1844 //                      if (container.CurrentType != null)
1845 //                              declaring_type = container.CurrentType;
1846 //                      else
1847                                 declaring_type = container.Definition;
1848
1849                         if (implementing != null && member.IsExplicitImpl) {
1850                                 container.TypeBuilder.DefineMethodOverride (builder, (MethodInfo) implementing.GetMetaInfo ());
1851                         }
1852
1853                         return true;
1854                 }
1855
1856
1857                 /// <summary>
1858                 /// Create the MethodBuilder for the method 
1859                 /// </summary>
1860                 void DefineMethodBuilder (TypeContainer container, string method_name, ParametersCompiled param)
1861                 {
1862                         var return_type = method.ReturnType.GetMetaInfo ();
1863                         var p_types = param.GetMetaInfo ();
1864
1865                         if (builder == null) {
1866                                 builder = container.TypeBuilder.DefineMethod (
1867                                         method_name, flags, method.CallingConventions,
1868                                         return_type, p_types);
1869                                 return;
1870                         }
1871
1872                         //
1873                         // Generic method has been already defined to resolve method parameters
1874                         // correctly when they use type parameters
1875                         //
1876                         builder.SetParameters (p_types);
1877                         builder.SetReturnType (return_type);
1878                         if (builder.Attributes != flags) {
1879                                 try {
1880                                         if (methodbuilder_attrs_field == null)
1881                                                 methodbuilder_attrs_field = typeof (MethodBuilder).GetField ("attrs", BindingFlags.NonPublic | BindingFlags.Instance);
1882                                         methodbuilder_attrs_field.SetValue (builder, flags);
1883                                 } catch {
1884                                         container.Compiler.Report.RuntimeMissingSupport (method.Location, "Generic method MethodAttributes");
1885                                 }
1886                         }
1887                 }
1888
1889                 //
1890                 // Emits the code
1891                 // 
1892                 public void Emit (DeclSpace parent)
1893                 {
1894                         if (GenericMethod != null)
1895                                 GenericMethod.EmitAttributes ();
1896
1897                         method.ParameterInfo.ApplyAttributes (MethodBuilder);
1898
1899                         SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
1900
1901                         ToplevelBlock block = method.Block;
1902                         if (block != null) {
1903                                 BlockContext bc = new BlockContext ((IMemberContext) method, block, method.ReturnType);
1904                                 if (block.Resolve (null, bc, method.ParameterInfo, method)) {
1905                                         EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator ());
1906                                         if (!ec.HasReturnLabel && bc.HasReturnLabel) {
1907                                                 ec.ReturnLabel = bc.ReturnLabel;
1908                                                 ec.HasReturnLabel = true;
1909                                         }
1910
1911                                         block.Emit (ec);
1912                                 }
1913                         }
1914
1915                         if (source != null) {
1916                                 method.EmitExtraSymbolInfo (source);
1917                                 source.CloseMethod ();
1918                         }
1919                 }
1920         }
1921
1922         public class Destructor : MethodOrOperator
1923         {
1924                 const Modifiers AllowedModifiers =
1925                         Modifiers.UNSAFE |
1926                         Modifiers.EXTERN;
1927
1928                 static readonly string[] attribute_targets = new string [] { "method" };
1929
1930                 public static readonly string MetadataName = "Finalize";
1931
1932                 public Destructor (DeclSpace parent, Modifiers mod, ParametersCompiled parameters, Attributes attrs, Location l)
1933                         : base (parent, null, null, mod, AllowedModifiers,
1934                                 new MemberName (MetadataName, l), attrs, parameters)
1935                 {
1936                         ModFlags &= ~Modifiers.PRIVATE;
1937                         ModFlags |= Modifiers.PROTECTED | Modifiers.OVERRIDE;
1938                 }
1939
1940                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1941                 {
1942                         if (a.Type == pa.Conditional) {
1943                                 Error_ConditionalAttributeIsNotValid ();
1944                                 return;
1945                         }
1946
1947                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1948                 }
1949
1950                 protected override bool CheckBase ()
1951                 {
1952                         // Don't check base, destructors have special syntax
1953                         return true;
1954                 }
1955
1956                 public override void  Emit()
1957                 {
1958                         var base_type = Parent.PartialContainer.BaseType;
1959                         if (base_type != null && Block != null) {
1960                                 MethodGroupExpr method_expr = Expression.MethodLookup (Parent.Module.Compiler, Parent.Definition, base_type, MemberKind.Destructor, MetadataName, 0, Location);
1961                                 if (method_expr == null)
1962                                         throw new NotImplementedException ();
1963
1964                                 method_expr.QueriedBaseType = base_type;
1965                                 method_expr.InstanceExpression = new CompilerGeneratedThis (Parent.Definition, Location);
1966
1967                                 ToplevelBlock new_block = new ToplevelBlock (Compiler, Block.StartLocation);
1968                                 new_block.EndLocation = Block.EndLocation;
1969
1970                                 Block finaly_block = new ExplicitBlock (new_block, Location, Location);
1971                                 Block try_block = new Block (new_block, block);
1972
1973                                 //
1974                                 // 0-size arguments to avoid CS0250 error
1975                                 // TODO: Should use AddScopeStatement or something else which emits correct
1976                                 // debugger scope
1977                                 //
1978                                 finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0))));
1979                                 new_block.AddStatement (new TryFinally (try_block, finaly_block, Location));
1980
1981                                 block = new_block;
1982                         }
1983
1984                         base.Emit ();
1985                 }
1986
1987                 public override string GetSignatureForError ()
1988                 {
1989                         return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
1990                 }
1991
1992                 protected override bool ResolveMemberType ()
1993                 {
1994                         member_type = TypeManager.void_type;
1995                         return true;
1996                 }
1997
1998                 public override string[] ValidAttributeTargets {
1999                         get {
2000                                 return attribute_targets;
2001                         }
2002                 }
2003         }
2004
2005         // Ooouh Martin, templates are missing here.
2006         // When it will be possible move here a lot of child code and template method type.
2007         public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData {
2008                 protected MethodData method_data;
2009                 protected ToplevelBlock block;
2010                 protected Dictionary<SecurityAction, PermissionSet> declarative_security;
2011
2012                 // The accessor are created even if they are not wanted.
2013                 // But we need them because their names are reserved.
2014                 // Field says whether accessor will be emited or not
2015                 public readonly bool IsDummy;
2016
2017                 protected readonly string prefix;
2018
2019                 ReturnParameter return_attributes;
2020
2021                 public AbstractPropertyEventMethod (PropertyBasedMember member, string prefix)
2022                         : base (member.Parent, SetupName (prefix, member, member.Location), null)
2023                 {
2024                         this.prefix = prefix;
2025                         IsDummy = true;
2026                 }
2027
2028                 public AbstractPropertyEventMethod (InterfaceMemberBase member, Accessor accessor,
2029                                                     string prefix)
2030                         : base (member.Parent, SetupName (prefix, member, accessor.Location),
2031                                 accessor.Attributes)
2032                 {
2033                         this.prefix = prefix;
2034                         this.block = accessor.Block;
2035                 }
2036
2037                 static MemberName SetupName (string prefix, InterfaceMemberBase member, Location loc)
2038                 {
2039                         return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc);
2040                 }
2041
2042                 public void UpdateName (InterfaceMemberBase member)
2043                 {
2044                         SetMemberName (SetupName (prefix, member, Location));
2045                 }
2046
2047                 #region IMethodData Members
2048
2049                 public ToplevelBlock Block {
2050                         get {
2051                                 return block;
2052                         }
2053
2054                         set {
2055                                 block = value;
2056                         }
2057                 }
2058
2059                 public CallingConventions CallingConventions {
2060                         get {
2061                                 return CallingConventions.Standard;
2062                         }
2063                 }
2064
2065                 public EmitContext CreateEmitContext (ILGenerator ig)
2066                 {
2067                         return new EmitContext (this, ig, ReturnType);
2068                 }
2069
2070                 public bool IsExcluded ()
2071                 {
2072                         return false;
2073                 }
2074
2075                 GenericMethod IMethodData.GenericMethod {
2076                         get {
2077                                 return null;
2078                         }
2079                 }
2080
2081                 public MemberName MethodName {
2082                         get {
2083                                 return MemberName;
2084                         }
2085                 }
2086
2087                 public TypeSpec[] ParameterTypes { 
2088                         get {
2089                                 return ParameterInfo.Types;
2090                         }
2091                 }
2092
2093                 public abstract ParametersCompiled ParameterInfo { get ; }
2094                 public abstract TypeSpec ReturnType { get; }
2095
2096                 #endregion
2097
2098                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2099                 {
2100                         if (a.Type == pa.CLSCompliant || a.Type == pa.Obsolete || a.Type == pa.Conditional) {
2101                                 Report.Error (1667, a.Location,
2102                                         "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
2103                                         TypeManager.CSharpName (a.Type), a.GetValidTargets ());
2104                                 return;
2105                         }
2106
2107                         if (a.IsValidSecurityAttribute ()) {
2108                                 if (declarative_security == null)
2109                                         declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
2110                                 a.ExtractSecurityPermissionSet (declarative_security);
2111                                 return;
2112                         }
2113
2114                         if (a.Target == AttributeTargets.Method) {
2115                                 method_data.MethodBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
2116                                 return;
2117                         }
2118
2119                         if (a.Target == AttributeTargets.ReturnValue) {
2120                                 if (return_attributes == null)
2121                                         return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
2122
2123                                 return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
2124                                 return;
2125                         }
2126
2127                         ApplyToExtraTarget (a, ctor, cdata, pa);
2128                 }
2129
2130                 protected virtual void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2131                 {
2132                         throw new NotSupportedException ("You forgot to define special attribute target handling");
2133                 }
2134
2135                 // It is not supported for the accessors
2136                 public sealed override bool Define()
2137                 {
2138                         throw new NotSupportedException ();
2139                 }
2140
2141                 public virtual void Emit (DeclSpace parent)
2142                 {
2143                         method_data.Emit (parent);
2144
2145                         if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2146                                 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (method_data.MethodBuilder);
2147                         if (((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0))
2148                                 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (method_data.MethodBuilder);
2149
2150                         if (ReturnType == InternalType.Dynamic) {
2151                                 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
2152                                 PredefinedAttributes.Get.Dynamic.EmitAttribute (return_attributes.Builder);
2153                         } else {
2154                                 var trans_flags = TypeManager.HasDynamicTypeUsed (ReturnType);
2155                                 if (trans_flags != null) {
2156                                         var pa = PredefinedAttributes.Get.DynamicTransform;
2157                                         if (pa.Constructor != null || pa.ResolveConstructor (Location, ArrayContainer.MakeType (TypeManager.bool_type))) {
2158                                                 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
2159                                                 return_attributes.Builder.SetCustomAttribute (
2160                                                         new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
2161                                         }
2162                                 }
2163                         }
2164
2165                         if (OptAttributes != null)
2166                                 OptAttributes.Emit ();
2167
2168                         if (declarative_security != null) {
2169                                 foreach (var de in declarative_security) {
2170                                         method_data.MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2171                                 }
2172                         }
2173
2174                         block = null;
2175                 }
2176
2177                 public override bool EnableOverloadChecks (MemberCore overload)
2178                 {
2179                         // This can only happen with indexers and it will
2180                         // be catched as indexer difference
2181                         if (overload is AbstractPropertyEventMethod)
2182                                 return true;
2183
2184                         if (overload is MethodCore) {
2185                                 caching_flags |= Flags.MethodOverloadsExist;
2186                                 return true;
2187                         }
2188                         return false;
2189                 }
2190
2191                 public override bool IsClsComplianceRequired()
2192                 {
2193                         return false;
2194                 }
2195
2196                 public bool IsDuplicateImplementation (MethodCore method)
2197                 {
2198                         if (!MemberName.Equals (method.MemberName))
2199                                 return false;
2200
2201                         TypeSpec[] param_types = method.ParameterTypes;
2202
2203                         if (param_types == null || param_types.Length != ParameterTypes.Length)
2204                                 return false;
2205
2206                         for (int i = 0; i < param_types.Length; i++)
2207                                 if (param_types [i] != ParameterTypes [i])
2208                                         return false;
2209
2210                         Report.SymbolRelatedToPreviousError (method);
2211                         Report.Error (82, Location, "A member `{0}' is already reserved",
2212                                 method.GetSignatureForError ());
2213                         return true;
2214                 }
2215
2216                 public override bool IsUsed {
2217                         get {
2218                                 if (IsDummy)
2219                                         return false;
2220
2221                                 return base.IsUsed;
2222                         }
2223                 }
2224
2225                 public MethodSpec Spec { get; protected set; }
2226
2227                 //
2228                 //   Represents header string for documentation comment.
2229                 //
2230                 public override string DocCommentHeader {
2231                         get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
2232                 }
2233
2234                 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
2235                 { }
2236         }
2237
2238         public class Operator : MethodOrOperator {
2239
2240                 const Modifiers AllowedModifiers =
2241                         Modifiers.PUBLIC |
2242                         Modifiers.UNSAFE |
2243                         Modifiers.EXTERN |
2244                         Modifiers.STATIC;
2245
2246                 public enum OpType : byte {
2247
2248                         // Unary operators
2249                         LogicalNot,
2250                         OnesComplement,
2251                         Increment,
2252                         Decrement,
2253                         True,
2254                         False,
2255
2256                         // Unary and Binary operators
2257                         Addition,
2258                         Subtraction,
2259
2260                         UnaryPlus,
2261                         UnaryNegation,
2262                         
2263                         // Binary operators
2264                         Multiply,
2265                         Division,
2266                         Modulus,
2267                         BitwiseAnd,
2268                         BitwiseOr,
2269                         ExclusiveOr,
2270                         LeftShift,
2271                         RightShift,
2272                         Equality,
2273                         Inequality,
2274                         GreaterThan,
2275                         LessThan,
2276                         GreaterThanOrEqual,
2277                         LessThanOrEqual,
2278
2279                         // Implicit and Explicit
2280                         Implicit,
2281                         Explicit,
2282
2283                         // Just because of enum
2284                         TOP
2285                 };
2286
2287                 public readonly OpType OperatorType;
2288
2289                 static readonly string [] [] names;
2290
2291                 static Operator ()
2292                 {
2293                         names = new string[(int)OpType.TOP][];
2294                         names [(int) OpType.LogicalNot] = new string [] { "!", "op_LogicalNot" };
2295                         names [(int) OpType.OnesComplement] = new string [] { "~", "op_OnesComplement" };
2296                         names [(int) OpType.Increment] = new string [] { "++", "op_Increment" };
2297                         names [(int) OpType.Decrement] = new string [] { "--", "op_Decrement" };
2298                         names [(int) OpType.True] = new string [] { "true", "op_True" };
2299                         names [(int) OpType.False] = new string [] { "false", "op_False" };
2300                         names [(int) OpType.Addition] = new string [] { "+", "op_Addition" };
2301                         names [(int) OpType.Subtraction] = new string [] { "-", "op_Subtraction" };
2302                         names [(int) OpType.UnaryPlus] = new string [] { "+", "op_UnaryPlus" };
2303                         names [(int) OpType.UnaryNegation] = new string [] { "-", "op_UnaryNegation" };
2304                         names [(int) OpType.Multiply] = new string [] { "*", "op_Multiply" };
2305                         names [(int) OpType.Division] = new string [] { "/", "op_Division" };
2306                         names [(int) OpType.Modulus] = new string [] { "%", "op_Modulus" };
2307                         names [(int) OpType.BitwiseAnd] = new string [] { "&", "op_BitwiseAnd" };
2308                         names [(int) OpType.BitwiseOr] = new string [] { "|", "op_BitwiseOr" };
2309                         names [(int) OpType.ExclusiveOr] = new string [] { "^", "op_ExclusiveOr" };
2310                         names [(int) OpType.LeftShift] = new string [] { "<<", "op_LeftShift" };
2311                         names [(int) OpType.RightShift] = new string [] { ">>", "op_RightShift" };
2312                         names [(int) OpType.Equality] = new string [] { "==", "op_Equality" };
2313                         names [(int) OpType.Inequality] = new string [] { "!=", "op_Inequality" };
2314                         names [(int) OpType.GreaterThan] = new string [] { ">", "op_GreaterThan" };
2315                         names [(int) OpType.LessThan] = new string [] { "<", "op_LessThan" };
2316                         names [(int) OpType.GreaterThanOrEqual] = new string [] { ">=", "op_GreaterThanOrEqual" };
2317                         names [(int) OpType.LessThanOrEqual] = new string [] { "<=", "op_LessThanOrEqual" };
2318                         names [(int) OpType.Implicit] = new string [] { "implicit", "op_Implicit" };
2319                         names [(int) OpType.Explicit] = new string [] { "explicit", "op_Explicit" };
2320                 }
2321                 
2322                 public Operator (DeclSpace parent, OpType type, FullNamedExpression ret_type,
2323                                  Modifiers mod_flags, ParametersCompiled parameters,
2324                                  ToplevelBlock block, Attributes attrs, Location loc)
2325                         : base (parent, null, ret_type, mod_flags, AllowedModifiers,
2326                                 new MemberName (GetMetadataName (type), loc), attrs, parameters)
2327                 {
2328                         OperatorType = type;
2329                         Block = block;
2330                 }
2331
2332                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2333                 {
2334                         if (a.Type == pa.Conditional) {
2335                                 Error_ConditionalAttributeIsNotValid ();
2336                                 return;
2337                         }
2338
2339                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2340                 }
2341                 
2342                 public override bool Define ()
2343                 {
2344                         const Modifiers RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
2345                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
2346                                 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
2347                         }
2348
2349                         if (!base.Define ())
2350                                 return false;
2351
2352                         if (block != null && block.IsIterator && !(Parent is IteratorStorey)) {
2353                                 //
2354                                 // Current method is turned into automatically generated
2355                                 // wrapper which creates an instance of iterator
2356                                 //
2357                                 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
2358                                 ModFlags |= Modifiers.DEBUGGER_HIDDEN;
2359                         }
2360
2361                         // imlicit and explicit operator of same types are not allowed
2362                         if (OperatorType == OpType.Explicit)
2363                                 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Implicit), parameters);
2364                         else if (OperatorType == OpType.Implicit)
2365                                 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Explicit), parameters);
2366
2367                         TypeSpec declaring_type = Parent.CurrentType;
2368                         TypeSpec return_type = MemberType;
2369                         TypeSpec first_arg_type = ParameterTypes [0];
2370                         
2371                         TypeSpec first_arg_type_unwrap = first_arg_type;
2372                         if (TypeManager.IsNullableType (first_arg_type))
2373                                 first_arg_type_unwrap = TypeManager.GetTypeArguments (first_arg_type) [0];
2374                         
2375                         TypeSpec return_type_unwrap = return_type;
2376                         if (TypeManager.IsNullableType (return_type))
2377                                 return_type_unwrap = TypeManager.GetTypeArguments (return_type) [0];
2378
2379                         if (return_type == InternalType.Dynamic || first_arg_type == InternalType.Dynamic) {
2380                                 Report.Error (1964, Location,
2381                                         "User-defined operator `{0}' cannot convert to or from the dynamic type",
2382                                         GetSignatureForError ());
2383
2384                                 return false;
2385                         }
2386
2387                         //
2388                         // Rules for conversion operators
2389                         //
2390                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2391                                 if (first_arg_type_unwrap == return_type_unwrap && first_arg_type_unwrap == declaring_type){
2392                                         Report.Error (555, Location,
2393                                                 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
2394                                         return false;
2395                                 }
2396                                 
2397                                 TypeSpec conv_type;
2398                                 if (TypeManager.IsEqual (declaring_type, return_type) || declaring_type == return_type_unwrap) {
2399                                         conv_type = first_arg_type;
2400                                 } else if (TypeManager.IsEqual (declaring_type, first_arg_type) || declaring_type == first_arg_type_unwrap) {
2401                                         conv_type = return_type;
2402                                 } else {
2403                                         Report.Error (556, Location, 
2404                                                 "User-defined conversion must convert to or from the enclosing type");
2405                                         return false;
2406                                 }
2407
2408                                 //
2409                                 // Because IsInterface and IsClass are not supported
2410                                 //
2411                                 if (!TypeManager.IsGenericParameter (conv_type)) {
2412                                         if (conv_type.IsInterface) {
2413                                                 Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
2414                                                         GetSignatureForError ());
2415                                                 return false;
2416                                         }
2417
2418                                         if (conv_type.IsClass) {
2419                                                 if (TypeManager.IsSubclassOf (declaring_type, conv_type)) {
2420                                                         Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from a base class",
2421                                                                 GetSignatureForError ());
2422                                                         return false;
2423                                                 }
2424
2425                                                 if (TypeManager.IsSubclassOf (conv_type, declaring_type)) {
2426                                                         Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from a derived class",
2427                                                                 GetSignatureForError ());
2428                                                         return false;
2429                                                 }
2430                                         }
2431                                 }
2432                         } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
2433                                 if (first_arg_type != declaring_type || parameters.Types[1] != TypeManager.int32_type) {
2434                                         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");
2435                                         return false;
2436                                 }
2437                         } else if (parameters.Count == 1) {
2438                                 // Checks for Unary operators
2439
2440                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
2441                                         if (return_type != declaring_type && !TypeManager.IsSubclassOf (return_type, declaring_type)) {
2442                                                 Report.Error (448, Location,
2443                                                         "The return type for ++ or -- operator must be the containing type or derived from the containing type");
2444                                                 return false;
2445                                         }
2446                                         if (first_arg_type != declaring_type) {
2447                                                 Report.Error (
2448                                                         559, Location, "The parameter type for ++ or -- operator must be the containing type");
2449                                                 return false;
2450                                         }
2451                                 }
2452                                 
2453                                 if (!TypeManager.IsEqual (first_arg_type_unwrap, declaring_type)){
2454                                         Report.Error (562, Location,
2455                                                 "The parameter type of a unary operator must be the containing type");
2456                                         return false;
2457                                 }
2458                                 
2459                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
2460                                         if (return_type != TypeManager.bool_type){
2461                                                 Report.Error (
2462                                                         215, Location,
2463                                                         "The return type of operator True or False " +
2464                                                         "must be bool");
2465                                                 return false;
2466                                         }
2467                                 }
2468                                 
2469                         } else if (!TypeManager.IsEqual (first_arg_type_unwrap, declaring_type)) {
2470                                 // Checks for Binary operators
2471
2472                                 var second_arg_type = ParameterTypes [1];
2473                                 if (TypeManager.IsNullableType (second_arg_type))
2474                                         second_arg_type = TypeManager.GetTypeArguments (second_arg_type) [0];
2475
2476                                 if (!TypeManager.IsEqual (second_arg_type, declaring_type)) {
2477                                         Report.Error (563, Location,
2478                                                 "One of the parameters of a binary operator must be the containing type");
2479                                         return false;
2480                                 }
2481                         }
2482
2483                         return true;
2484                 }
2485
2486                 protected override bool ResolveMemberType ()
2487                 {
2488                         if (!base.ResolveMemberType ())
2489                                 return false;
2490
2491                         flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2492                         return true;
2493                 }
2494
2495                 protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate)
2496                 {
2497                         // Operator cannot be override
2498                         bestCandidate = null;
2499                         return null;
2500                 }
2501
2502                 public static string GetName (OpType ot)
2503                 {
2504                         return names [(int) ot] [0];
2505                 }
2506
2507                 public static string GetName (string metadata_name)
2508                 {
2509                         for (int i = 0; i < names.Length; ++i) {
2510                                 if (names [i] [1] == metadata_name)
2511                                         return names [i] [0];
2512                         }
2513                         return null;
2514                 }
2515
2516                 public static string GetMetadataName (OpType ot)
2517                 {
2518                         return names [(int) ot] [1];
2519                 }
2520
2521                 public static string GetMetadataName (string name)
2522                 {
2523                         for (int i = 0; i < names.Length; ++i) {
2524                                 if (names [i] [0] == name)
2525                                         return names [i] [1];
2526                         }
2527                         return null;
2528                 }
2529
2530                 public static OpType? GetType (string metadata_name)
2531                 {
2532                         for (int i = 0; i < names.Length; ++i) {
2533                                 if (names[i][1] == metadata_name)
2534                                         return (OpType) i;
2535                         }
2536
2537                         return null;
2538                 }
2539
2540                 public OpType GetMatchingOperator ()
2541                 {
2542                         switch (OperatorType) {
2543                         case OpType.Equality:
2544                                 return OpType.Inequality;
2545                         case OpType.Inequality:
2546                                 return OpType.Equality;
2547                         case OpType.True:
2548                                 return OpType.False;
2549                         case OpType.False:
2550                                 return OpType.True;
2551                         case OpType.GreaterThan:
2552                                 return OpType.LessThan;
2553                         case OpType.LessThan:
2554                                 return OpType.GreaterThan;
2555                         case OpType.GreaterThanOrEqual:
2556                                 return OpType.LessThanOrEqual;
2557                         case OpType.LessThanOrEqual:
2558                                 return OpType.GreaterThanOrEqual;
2559                         default:
2560                                 return OpType.TOP;
2561                         }
2562                 }
2563
2564                 public override string GetSignatureForError ()
2565                 {
2566                         StringBuilder sb = new StringBuilder ();
2567                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2568                                 sb.AppendFormat ("{0}.{1} operator {2}",
2569                                         Parent.GetSignatureForError (), GetName (OperatorType), type_expr.GetSignatureForError ());
2570                         }
2571                         else {
2572                                 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
2573                         }
2574
2575                         sb.Append (parameters.GetSignatureForError ());
2576                         return sb.ToString ();
2577                 }
2578         }
2579 }
2580