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