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