a6109dc5f72aa483e0c577ceb265811df9d8d4f0
[mono.git] / mcs / mcs / property.cs
1 //
2 // property.cs: Property based handlers
3 //
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 //          Martin Baulig (martin@ximian.com)
6 //          Marek Safar (marek.safar@seznam.cz)
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         // It is used as a base class for all property based members
35         // This includes properties, indexers, and events
36         public abstract class PropertyBasedMember : InterfaceMemberBase
37         {
38                 public PropertyBasedMember (DeclSpace parent, GenericMethod generic,
39                         FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
40                         MemberName name, Attributes attrs)
41                         : base (parent, generic, type, mod, allowed_mod, name, attrs)
42                 {
43                 }
44
45                 protected override bool VerifyClsCompliance ()
46                 {
47                         if (!base.VerifyClsCompliance ())
48                                 return false;
49
50                         if (!AttributeTester.IsClsCompliant (MemberType)) {
51                                 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
52                                         GetSignatureForError ());
53                         }
54                         return true;
55                 }
56
57         }
58
59         //
60         // `set' and `get' accessors are represented with an Accessor.
61         // 
62         public class Accessor {
63                 //
64                 // Null if the accessor is empty, or a Block if not
65                 //
66                 public const Modifiers AllowedModifiers = 
67                         Modifiers.PUBLIC |
68                         Modifiers.PROTECTED |
69                         Modifiers.INTERNAL |
70                         Modifiers.PRIVATE;
71                 
72                 public ToplevelBlock Block;
73                 public Attributes Attributes;
74                 public Location Location;
75                 public Modifiers ModFlags;
76                 public ParametersCompiled Parameters;
77                 
78                 public Accessor (ToplevelBlock b, Modifiers mod, Attributes attrs, ParametersCompiled p, Location loc)
79                 {
80                         Block = b;
81                         Attributes = attrs;
82                         Location = loc;
83                         Parameters = p;
84                         ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, 0, loc, RootContext.ToplevelTypes.Compiler.Report);
85                 }
86         }
87
88         public class PropertySpec : MemberSpec
89         {
90                 PropertyInfo info;
91
92                 public PropertySpec (MemberKind kind, IMemberDefinition definition, PropertyInfo info, Modifiers modifiers)
93                         : base (kind, definition, info.Name, modifiers)
94                 {
95                         this.info = info;
96                 }
97
98                 public override Type DeclaringType {
99                         get { return info.DeclaringType; }
100                 }
101
102                 public PropertyInfo MetaInfo {
103                         get { return info; }
104                 }
105
106                 public Type PropertyType {
107                         get { return info.PropertyType; }
108                 }
109         }
110
111         //
112         // Properties and Indexers both generate PropertyBuilders, we use this to share 
113         // their common bits.
114         //
115         abstract public class PropertyBase : PropertyBasedMember {
116
117                 public class GetMethod : PropertyMethod
118                 {
119                         static string[] attribute_targets = new string [] { "method", "return" };
120
121                         public GetMethod (PropertyBase method):
122                                 base (method, "get_")
123                         {
124                         }
125
126                         public GetMethod (PropertyBase method, Accessor accessor):
127                                 base (method, accessor, "get_")
128                         {
129                         }
130
131                         public override MethodBuilder Define (DeclSpace parent)
132                         {
133                                 base.Define (parent);
134
135                                 if (IsDummy)
136                                         return null;
137                                 
138                                 method_data = new MethodData (method, ModFlags, flags, this);
139
140                                 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
141                                         return null;
142
143                                 Spec = new MethodSpec (MemberKind.Method, this, method_data.MethodBuilder, ParameterInfo, ModFlags);
144
145                                 return method_data.MethodBuilder;
146                         }
147
148                         public override Type ReturnType {
149                                 get {
150                                         return method.MemberType;
151                                 }
152                         }
153
154                         public override ParametersCompiled ParameterInfo {
155                                 get {
156                                         return ParametersCompiled.EmptyReadOnlyParameters;
157                                 }
158                         }
159
160                         public override string[] ValidAttributeTargets {
161                                 get {
162                                         return attribute_targets;
163                                 }
164                         }
165                 }
166
167                 public class SetMethod : PropertyMethod {
168
169                         static string[] attribute_targets = new string [] { "method", "param", "return" };
170                         ImplicitParameter param_attr;
171                         protected ParametersCompiled parameters;
172
173                         public SetMethod (PropertyBase method) :
174                                 base (method, "set_")
175                         {
176                                 parameters = new ParametersCompiled (Compiler,
177                                         new Parameter (method.type_name, "value", Parameter.Modifier.NONE, null, Location));
178                         }
179
180                         public SetMethod (PropertyBase method, Accessor accessor):
181                                 base (method, accessor, "set_")
182                         {
183                                 this.parameters = accessor.Parameters;
184                         }
185
186                         protected override void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
187                         {
188                                 if (a.Target == AttributeTargets.Parameter) {
189                                         if (param_attr == null)
190                                                 param_attr = new ImplicitParameter (method_data.MethodBuilder);
191
192                                         param_attr.ApplyAttributeBuilder (a, cb, pa);
193                                         return;
194                                 }
195
196                                 base.ApplyAttributeBuilder (a, cb, pa);
197                         }
198
199                         public override ParametersCompiled ParameterInfo {
200                             get {
201                                 return parameters;
202                             }
203                         }
204
205                         public override MethodBuilder Define (DeclSpace parent)
206                         {
207                                 parameters.Resolve (this);
208                                 
209                                 base.Define (parent);
210
211                                 if (IsDummy)
212                                         return null;
213
214                                 method_data = new MethodData (method, ModFlags, flags, this);
215
216                                 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
217                                         return null;
218
219                                 Spec = new MethodSpec (MemberKind.Method, this, method_data.MethodBuilder, ParameterInfo, ModFlags);
220
221                                 return method_data.MethodBuilder;
222                         }
223
224                         public override Type ReturnType {
225                                 get {
226                                         return TypeManager.void_type;
227                                 }
228                         }
229
230                         public override string[] ValidAttributeTargets {
231                                 get {
232                                         return attribute_targets;
233                                 }
234                         }
235                 }
236
237                 static string[] attribute_targets = new string [] { "property" };
238
239                 public abstract class PropertyMethod : AbstractPropertyEventMethod
240                 {
241                         protected readonly PropertyBase method;
242                         protected MethodAttributes flags;
243
244                         public PropertyMethod (PropertyBase method, string prefix)
245                                 : base (method, prefix)
246                         {
247                                 this.method = method;
248                                 this.ModFlags = method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE);                                
249                         }
250
251                         public PropertyMethod (PropertyBase method, Accessor accessor,
252                                                string prefix)
253                                 : base (method, accessor, prefix)
254                         {
255                                 this.method = method;
256                                 this.ModFlags = accessor.ModFlags | (method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE));
257
258                                 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
259                                         Report.FeatureIsNotAvailable (Location, "access modifiers on properties");
260                                 }
261                         }
262
263                         public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
264                         {
265                                 if (a.IsInternalMethodImplAttribute) {
266                                         method.is_external_implementation = true;
267                                 }
268
269                                 base.ApplyAttributeBuilder (a, cb, pa);
270                         }
271
272                         public override AttributeTargets AttributeTargets {
273                                 get {
274                                         return AttributeTargets.Method;
275                                 }
276                         }
277
278                         public override bool IsClsComplianceRequired ()
279                         {
280                                 return method.IsClsComplianceRequired ();
281                         }
282
283                         public virtual MethodBuilder Define (DeclSpace parent)
284                         {
285                                 CheckForDuplications ();
286
287                                 if (IsDummy) {
288                                         if (method.InterfaceType != null && parent.PartialContainer.PendingImplementations != null) {
289                                                 MethodInfo mi = parent.PartialContainer.PendingImplementations.IsInterfaceMethod (
290                                                         MethodName.Name, method.InterfaceType, new MethodData (method, ModFlags, flags, this));
291                                                 if (mi != null) {
292                                                         Report.SymbolRelatedToPreviousError (mi);
293                                                         Report.Error (551, Location, "Explicit interface implementation `{0}' is missing accessor `{1}'",
294                                                                 method.GetSignatureForError (), TypeManager.CSharpSignature (mi, true));
295                                                 }
296                                         }
297                                         return null;
298                                 }
299
300                                 TypeContainer container = parent.PartialContainer;
301
302                                 //
303                                 // Check for custom access modifier
304                                 //
305                                 if ((ModFlags & Modifiers.AccessibilityMask) == 0) {
306                                         ModFlags |= method.ModFlags;
307                                         flags = method.flags;
308                                 } else {
309                                         if (container.Kind == MemberKind.Interface)
310                                                 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
311                                                         GetSignatureForError ());
312
313                                         if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
314                                                 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
315                                         }
316
317                                         CheckModifiers (ModFlags);
318                                         ModFlags |= (method.ModFlags & (~Modifiers.AccessibilityMask));
319                                         ModFlags |= Modifiers.PROPERTY_CUSTOM;
320                                         flags = ModifiersExtensions.MethodAttr (ModFlags);
321                                         flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
322                                 }
323
324                                 CheckAbstractAndExtern (block != null);
325                                 CheckProtectedModifier ();
326
327                                 if (block != null && block.IsIterator)
328                                         Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
329
330                                 return null;
331                         }
332
333                         public bool HasCustomAccessModifier {
334                                 get {
335                                         return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
336                                 }
337                         }
338
339                         public PropertyBase Property {
340                                 get {
341                                         return method;
342                                 }
343                         }
344
345                         public override ObsoleteAttribute GetObsoleteAttribute ()
346                         {
347                                 return method.GetObsoleteAttribute ();
348                         }
349
350                         public override string GetSignatureForError()
351                         {
352                                 return method.GetSignatureForError () + '.' + prefix.Substring (0, 3);
353                         }
354
355                         void CheckModifiers (Modifiers modflags)
356                         {
357                                 modflags &= Modifiers.AccessibilityMask;
358                                 Modifiers flags = 0;
359                                 Modifiers mflags = method.ModFlags & Modifiers.AccessibilityMask;
360
361                                 if ((mflags & Modifiers.PUBLIC) != 0) {
362                                         flags |= Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
363                                 }
364                                 else if ((mflags & Modifiers.PROTECTED) != 0) {
365                                         if ((mflags & Modifiers.INTERNAL) != 0)
366                                                 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL;
367
368                                         flags |= Modifiers.PRIVATE;
369                                 } else if ((mflags & Modifiers.INTERNAL) != 0)
370                                         flags |= Modifiers.PRIVATE;
371
372                                 if ((mflags == modflags) || (modflags & (~flags)) != 0) {
373                                         Report.Error (273, Location,
374                                                 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
375                                                 GetSignatureForError (), method.GetSignatureForError ());
376                                 }
377                         }
378
379                         protected bool CheckForDuplications ()
380                         {
381                                 if ((caching_flags & Flags.MethodOverloadsExist) == 0)
382                                         return true;
383
384                                 return Parent.MemberCache.CheckExistingMembersOverloads (this, Name, ParameterInfo, Report);
385                         }
386                 }
387
388                 public PropertyMethod Get, Set;
389                 public PropertyBuilder PropertyBuilder;
390                 public MethodBuilder GetBuilder, SetBuilder;
391
392                 protected bool define_set_first = false;
393
394                 public PropertyBase (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags,
395                                      Modifiers allowed_mod, MemberName name,
396                                      Attributes attrs, bool define_set_first)
397                         : base (parent, null, type, mod_flags, allowed_mod, name, attrs)
398                 {
399                          this.define_set_first = define_set_first;
400                 }
401
402                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
403                 {
404                         if (a.HasSecurityAttribute) {
405                                 a.Error_InvalidSecurityParent ();
406                                 return;
407                         }
408
409                         if (a.Type == pa.Dynamic) {
410                                 a.Error_MisusedDynamicAttribute ();
411                                 return;
412                         }
413
414                         PropertyBuilder.SetCustomAttribute (cb);
415                 }
416
417                 public override AttributeTargets AttributeTargets {
418                         get {
419                                 return AttributeTargets.Property;
420                         }
421                 }
422
423                 protected override void DoMemberTypeDependentChecks ()
424                 {
425                         base.DoMemberTypeDependentChecks ();
426
427                         IsTypePermitted ();
428 #if MS_COMPATIBLE
429                         if (MemberType.IsGenericParameter)
430                                 return;
431 #endif
432
433                         if ((MemberType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
434                                 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
435                         }
436                 }
437
438                 protected override void DoMemberTypeIndependentChecks ()
439                 {
440                         base.DoMemberTypeIndependentChecks ();
441
442                         //
443                         // Accessors modifiers check
444                         //
445                         if ((Get.ModFlags & Modifiers.AccessibilityMask) != 0 &&
446                                 (Set.ModFlags & Modifiers.AccessibilityMask) != 0) {
447                                 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
448                                                 GetSignatureForError ());
449                         }
450
451                         if ((ModFlags & Modifiers.OVERRIDE) == 0 && 
452                                 (Get.IsDummy && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) ||
453                                 (Set.IsDummy && (Get.ModFlags & Modifiers.AccessibilityMask) != 0)) {
454                                 Report.Error (276, Location, 
455                                               "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
456                                               GetSignatureForError ());
457                         }
458                 }
459
460                 bool DefineGet ()
461                 {
462                         GetBuilder = Get.Define (Parent);
463                         return (Get.IsDummy) ? true : GetBuilder != null;
464                 }
465
466                 bool DefineSet (bool define)
467                 {
468                         if (!define)
469                                 return true;
470
471                         SetBuilder = Set.Define (Parent);
472                         return (Set.IsDummy) ? true : SetBuilder != null;
473                 }
474
475                 protected bool DefineAccessors ()
476                 {
477                         return DefineSet (define_set_first) &&
478                                 DefineGet () &&
479                                 DefineSet (!define_set_first);
480                 }
481
482                 protected void DefineBuilders (MemberKind kind, Type[] parameterTypes)
483                 {
484                         // FIXME - PropertyAttributes.HasDefault ?
485
486                         PropertyBuilder = Parent.TypeBuilder.DefineProperty (
487                                 GetFullName (MemberName), PropertyAttributes.None, MemberType, parameterTypes);
488
489                         if (!Get.IsDummy) {
490                                 PropertyBuilder.SetGetMethod (GetBuilder);
491                                 Parent.MemberCache.AddMember (GetBuilder, Get.Spec);
492                         }
493
494                         if (!Set.IsDummy) {
495                                 PropertyBuilder.SetSetMethod (SetBuilder);
496                                 Parent.MemberCache.AddMember (SetBuilder, Set.Spec);
497                         }
498
499                         var spec = new PropertySpec (kind, this, PropertyBuilder, ModFlags);
500                         Parent.MemberCache.AddMember (PropertyBuilder, spec);
501                 }
502
503                 protected abstract PropertyInfo ResolveBaseProperty ();
504
505                 // TODO: rename to Resolve......
506                 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
507                 {
508                         PropertyInfo base_property = ResolveBaseProperty ();
509                         if (base_property == null)
510                                 return null;
511
512                         base_ret_type = base_property.PropertyType;
513                         MethodInfo get_accessor = base_property.GetGetMethod (true);
514                         MethodInfo set_accessor = base_property.GetSetMethod (true);
515                         MethodAttributes get_accessor_access = 0, set_accessor_access = 0;
516
517                         //
518                         // Check base property accessors conflict
519                         //
520                         if ((ModFlags & (Modifiers.OVERRIDE | Modifiers.NEW)) == Modifiers.OVERRIDE) {
521                                 if (get_accessor == null) {
522                                         if (Get != null && !Get.IsDummy) {
523                                                 Report.SymbolRelatedToPreviousError (base_property);
524                                                 Report.Error (545, Location,
525                                                         "`{0}.get': cannot override because `{1}' does not have an overridable get accessor",
526                                                         GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
527                                         }
528                                 } else {
529                                         get_accessor_access = get_accessor.Attributes & MethodAttributes.MemberAccessMask;
530
531                                         if (!Get.IsDummy && !CheckAccessModifiers (
532                                                 ModifiersExtensions.MethodAttr (Get.ModFlags) & MethodAttributes.MemberAccessMask, get_accessor_access, get_accessor))
533                                                 Error_CannotChangeAccessModifiers (Get.Location, get_accessor, get_accessor_access, ".get");
534                                 }
535
536                                 if (set_accessor == null) {
537                                         if (Set != null && !Set.IsDummy) {
538                                                 Report.SymbolRelatedToPreviousError (base_property);
539                                                 Report.Error (546, Location,
540                                                         "`{0}.set': cannot override because `{1}' does not have an overridable set accessor",
541                                                         GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
542                                         }
543                                 } else {
544                                         set_accessor_access = set_accessor.Attributes & MethodAttributes.MemberAccessMask;
545
546                                         if (!Set.IsDummy && !CheckAccessModifiers (
547                                                 ModifiersExtensions.MethodAttr (Set.ModFlags) & MethodAttributes.MemberAccessMask, set_accessor_access, set_accessor))
548                                                 Error_CannotChangeAccessModifiers (Set.Location, set_accessor, set_accessor_access, ".set");
549                                 }
550                         }
551
552                         // When one accessor does not exist and property hides base one
553                         // we need to propagate this upwards
554                         if (set_accessor == null)
555                                 set_accessor = get_accessor;
556
557                         //
558                         // Get the less restrictive access
559                         //
560                         return get_accessor_access > set_accessor_access ? get_accessor : set_accessor;
561                 }
562
563                 public override void Emit ()
564                 {
565                         //
566                         // The PropertyBuilder can be null for explicit implementations, in that
567                         // case, we do not actually emit the ".property", so there is nowhere to
568                         // put the attribute
569                         //
570                         if (PropertyBuilder != null) {
571                                 if (OptAttributes != null)
572                                         OptAttributes.Emit ();
573
574                                 if (TypeManager.IsDynamicType (member_type)) {
575                                         PredefinedAttributes.Get.Dynamic.EmitAttribute (PropertyBuilder);
576                                 } else {
577                                         var trans_flags = TypeManager.HasDynamicTypeUsed (member_type);
578                                         if (trans_flags != null) {
579                                                 var pa = PredefinedAttributes.Get.DynamicTransform;
580                                                 if (pa.Constructor != null || pa.ResolveConstructor (Location, TypeManager.bool_type.MakeArrayType ())) {
581                                                         PropertyBuilder.SetCustomAttribute (
582                                                                 new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
583                                                 }
584                                         }
585                                 }
586                         }
587
588                         if (!Get.IsDummy)
589                                 Get.Emit (Parent);
590
591                         if (!Set.IsDummy)
592                                 Set.Emit (Parent);
593
594                         base.Emit ();
595                 }
596
597                 /// <summary>
598                 /// Tests whether accessors are not in collision with some method (CS0111)
599                 /// </summary>
600                 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
601                 {
602                         return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
603                 }
604
605                 public override bool IsUsed
606                 {
607                         get {
608                                 if (IsExplicitImpl)
609                                         return true;
610
611                                 return Get.IsUsed | Set.IsUsed;
612                         }
613                 }
614
615                 protected override void SetMemberName (MemberName new_name)
616                 {
617                         base.SetMemberName (new_name);
618
619                         Get.UpdateName (this);
620                         Set.UpdateName (this);
621                 }
622
623                 public override string[] ValidAttributeTargets {
624                         get {
625                                 return attribute_targets;
626                         }
627                 }
628
629                 //
630                 //   Represents header string for documentation comment.
631                 //
632                 public override string DocCommentHeader {
633                         get { return "P:"; }
634                 }
635         }
636                         
637         public class Property : PropertyBase
638         {
639                 public sealed class BackingField : Field
640                 {
641                         readonly Property property;
642
643                         public BackingField (Property p)
644                                 : base (p.Parent, p.type_name,
645                                 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
646                                 new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
647                         {
648                                 this.property = p;
649                         }
650
651                         public override string GetSignatureForError ()
652                         {
653                                 return property.GetSignatureForError ();
654                         }
655                 }
656
657                 const Modifiers AllowedModifiers =
658                         Modifiers.NEW |
659                         Modifiers.PUBLIC |
660                         Modifiers.PROTECTED |
661                         Modifiers.INTERNAL |
662                         Modifiers.PRIVATE |
663                         Modifiers.STATIC |
664                         Modifiers.SEALED |
665                         Modifiers.OVERRIDE |
666                         Modifiers.ABSTRACT |
667                         Modifiers.UNSAFE |
668                         Modifiers.EXTERN |
669                         Modifiers.VIRTUAL;
670
671                 const Modifiers AllowedInterfaceModifiers =
672                         Modifiers.NEW;
673
674                 public Property (DeclSpace parent, FullNamedExpression type, Modifiers mod,
675                                  MemberName name, Attributes attrs, Accessor get_block,
676                                  Accessor set_block, bool define_set_first)
677                         : this (parent, type, mod, name, attrs, get_block, set_block,
678                                 define_set_first, null)
679                 {
680                 }
681                 
682                 public Property (DeclSpace parent, FullNamedExpression type, Modifiers mod,
683                                  MemberName name, Attributes attrs, Accessor get_block,
684                                  Accessor set_block, bool define_set_first, Block current_block)
685                         : base (parent, type, mod,
686                                 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
687                                 name, attrs, define_set_first)
688                 {
689                         if (get_block == null)
690                                 Get = new GetMethod (this);
691                         else
692                                 Get = new GetMethod (this, get_block);
693
694                         if (set_block == null)
695                                 Set = new SetMethod (this);
696                         else
697                                 Set = new SetMethod (this, set_block);
698
699                         if (!IsInterface && (mod & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
700                                 get_block != null && get_block.Block == null &&
701                                 set_block != null && set_block.Block == null) {
702                                 if (RootContext.Version <= LanguageVersion.ISO_2)
703                                         Report.FeatureIsNotAvailable (Location, "automatically implemented properties");
704
705                                 Get.ModFlags |= Modifiers.COMPILER_GENERATED;
706                                 Set.ModFlags |= Modifiers.COMPILER_GENERATED;
707                         }
708                 }
709
710                 void CreateAutomaticProperty ()
711                 {
712                         // Create backing field
713                         Field field = new BackingField (this);
714                         if (!field.Define ())
715                                 return;
716
717                         Parent.PartialContainer.AddField (field);
718
719                         FieldExpr fe = new FieldExpr (field, Location);
720                         if ((field.ModFlags & Modifiers.STATIC) == 0)
721                                 fe.InstanceExpression = new CompilerGeneratedThis (fe.Type, Location);
722
723                         // Create get block
724                         Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
725                         Return r = new Return (fe, Location);
726                         Get.Block.AddStatement (r);
727
728                         // Create set block
729                         Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location);
730                         Assign a = new SimpleAssign (fe, new SimpleName ("value", Location));
731                         Set.Block.AddStatement (new StatementExpression (a));
732                 }
733
734                 public override bool Define ()
735                 {
736                         if (!base.Define ())
737                                 return false;
738
739                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
740
741                         if ((Get.ModFlags & Modifiers.COMPILER_GENERATED) != 0)
742                                 CreateAutomaticProperty ();
743
744                         if (!DefineAccessors ())
745                                 return false;
746
747                         if (!CheckBase ())
748                                 return false;
749
750                         DefineBuilders (MemberKind.Property, null);
751                         TypeManager.RegisterProperty (PropertyBuilder, this);
752                         return true;
753                 }
754
755                 public override void Emit ()
756                 {
757                         if (((Set.ModFlags | Get.ModFlags) & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) {
758                                 Report.Error (842, Location,
759                                         "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
760                                         GetSignatureForError ());
761                         }
762
763                         base.Emit ();
764                 }
765
766                 protected override PropertyInfo ResolveBaseProperty ()
767                 {
768                         return Parent.PartialContainer.BaseCache.FindMemberToOverride (
769                                 Parent.TypeBuilder, Name, ParametersCompiled.EmptyReadOnlyParameters, null, true) as PropertyInfo;
770                 }
771         }
772
773         /// </summary>
774         ///  Gigantic workaround  for lameness in SRE follows :
775         ///  This class derives from EventInfo and attempts to basically
776         ///  wrap around the EventBuilder so that FindMembers can quickly
777         ///  return this in it search for members
778         /// </summary>
779         public class MyEventBuilder : EventInfo {
780                 
781                 //
782                 // We use this to "point" to our Builder which is
783                 // not really a MemberInfo
784                 //
785                 EventBuilder MyBuilder;
786                 
787                 //
788                 // We "catch" and wrap these methods
789                 //
790                 MethodInfo raise, remove, add;
791
792                 EventAttributes attributes;
793                 Type declaring_type, reflected_type, event_type;
794                 string name;
795
796                 Event my_event;
797
798                 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
799                 {
800                         MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
801
802                         // And now store the values in our own fields.
803                         
804                         declaring_type = type_builder;
805
806                         reflected_type = type_builder;
807                         
808                         attributes = event_attr;
809                         this.name = name;
810                         my_event = ev;
811                         this.event_type = event_type;
812                 }
813                 
814                 //
815                 // Methods that you have to override.  Note that you only need 
816                 // to "implement" the variants that take the argument (those are
817                 // the "abstract" methods, the others (GetAddMethod()) are 
818                 // regular.
819                 //
820                 public override MethodInfo GetAddMethod (bool nonPublic)
821                 {
822                         return add;
823                 }
824                 
825                 public override MethodInfo GetRemoveMethod (bool nonPublic)
826                 {
827                         return remove;
828                 }
829                 
830                 public override MethodInfo GetRaiseMethod (bool nonPublic)
831                 {
832                         return raise;
833                 }
834                 
835                 //
836                 // These methods make "MyEventInfo" look like a Builder
837                 //
838                 public void SetRaiseMethod (MethodBuilder raiseMethod)
839                 {
840                         raise = raiseMethod;
841                         MyBuilder.SetRaiseMethod (raiseMethod);
842                 }
843
844                 public void SetRemoveOnMethod (MethodBuilder removeMethod)
845                 {
846                         remove = removeMethod;
847                         MyBuilder.SetRemoveOnMethod (removeMethod);
848                 }
849
850                 public void SetAddOnMethod (MethodBuilder addMethod)
851                 {
852                         add = addMethod;
853                         MyBuilder.SetAddOnMethod (addMethod);
854                 }
855
856                 public void SetCustomAttribute (CustomAttributeBuilder cb)
857                 {
858                         MyBuilder.SetCustomAttribute (cb);
859                 }
860                 
861                 public override object [] GetCustomAttributes (bool inherit)
862                 {
863                         // FIXME : There's nothing which can be seemingly done here because
864                         // we have no way of getting at the custom attribute objects of the
865                         // EventBuilder !
866                         return null;
867                 }
868
869                 public override object [] GetCustomAttributes (Type t, bool inherit)
870                 {
871                         // FIXME : Same here !
872                         return null;
873                 }
874
875                 public override bool IsDefined (Type t, bool b)
876                 {
877                         return true;
878                 }
879
880                 public override EventAttributes Attributes {
881                         get {
882                                 return attributes;
883                         }
884                 }
885
886                 public override string Name {
887                         get {
888                                 return name;
889                         }
890                 }
891
892                 public override Type DeclaringType {
893                         get {
894                                 return declaring_type;
895                         }
896                 }
897
898                 public override Type ReflectedType {
899                         get {
900                                 return reflected_type;
901                         }
902                 }
903
904                 public Type EventType {
905                         get {
906                                 return event_type;
907                         }
908                 }
909                 
910                 public void SetUsed ()
911                 {
912                         if (my_event != null) {
913 //                              my_event.SetAssigned ();
914                                 my_event.SetIsUsed ();
915                         }
916                 }
917         }
918         
919         /// <summary>
920         /// For case when event is declared like property (with add and remove accessors).
921         /// </summary>
922         public class EventProperty: Event {
923                 abstract class AEventPropertyAccessor : AEventAccessor
924                 {
925                         protected AEventPropertyAccessor (EventProperty method, Accessor accessor, string prefix)
926                                 : base (method, accessor, prefix)
927                         {
928                         }
929
930                         public override MethodBuilder Define (DeclSpace ds)
931                         {
932                                 CheckAbstractAndExtern (block != null);
933                                 return base.Define (ds);
934                         }
935                         
936                         public override string GetSignatureForError ()
937                         {
938                                 return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1);
939                         }
940                 }
941
942                 sealed class AddDelegateMethod: AEventPropertyAccessor
943                 {
944                         public AddDelegateMethod (EventProperty method, Accessor accessor):
945                                 base (method, accessor, AddPrefix)
946                         {
947                         }
948                 }
949
950                 sealed class RemoveDelegateMethod: AEventPropertyAccessor
951                 {
952                         public RemoveDelegateMethod (EventProperty method, Accessor accessor):
953                                 base (method, accessor, RemovePrefix)
954                         {
955                         }
956                 }
957
958
959                 static readonly string[] attribute_targets = new string [] { "event" }; // "property" target was disabled for 2.0 version
960
961                 public EventProperty (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags,
962                                       MemberName name,
963                                       Attributes attrs, Accessor add, Accessor remove)
964                         : base (parent, type, mod_flags, name, attrs)
965                 {
966                         Add = new AddDelegateMethod (this, add);
967                         Remove = new RemoveDelegateMethod (this, remove);
968                 }
969
970                 public override bool Define()
971                 {
972                         if (!base.Define ())
973                                 return false;
974
975                         SetIsUsed ();
976                         return true;
977                 }
978
979                 public override string[] ValidAttributeTargets {
980                         get {
981                                 return attribute_targets;
982                         }
983                 }
984         }
985
986         /// <summary>
987         /// Event is declared like field.
988         /// </summary>
989         public class EventField : Event {
990                 abstract class EventFieldAccessor : AEventAccessor
991                 {
992                         protected EventFieldAccessor (EventField method, string prefix)
993                                 : base (method, prefix)
994                         {
995                         }
996
997                         public override void Emit (DeclSpace parent)
998                         {
999                                 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
1000                                         if (parent is Class) {
1001                                                 MethodBuilder mb = method_data.MethodBuilder;
1002                                                 mb.SetImplementationFlags (mb.GetMethodImplementationFlags () | MethodImplAttributes.Synchronized);
1003                                         }
1004
1005                                         var field_info = ((EventField) method).BackingField;
1006                                         FieldExpr f_expr = new FieldExpr (field_info, Location);
1007                                         if ((method.ModFlags & Modifiers.STATIC) == 0)
1008                                                 f_expr.InstanceExpression = new CompilerGeneratedThis (field_info.Spec.FieldType, Location);
1009
1010                                         block = new ToplevelBlock (Compiler, ParameterInfo, Location);
1011                                         block.AddStatement (new StatementExpression (
1012                                                 new CompoundAssign (Operation,
1013                                                         f_expr,
1014                                                         block.GetParameterReference (ParameterInfo[0].Name, Location))));
1015                                 }
1016
1017                                 base.Emit (parent);
1018                         }
1019
1020                         protected abstract Binary.Operator Operation { get; }
1021                 }
1022
1023                 sealed class AddDelegateMethod: EventFieldAccessor
1024                 {
1025                         public AddDelegateMethod (EventField method):
1026                                 base (method, AddPrefix)
1027                         {
1028                         }
1029
1030                         protected override Binary.Operator Operation {
1031                                 get { return Binary.Operator.Addition; }
1032                         }
1033                 }
1034
1035                 sealed class RemoveDelegateMethod: EventFieldAccessor
1036                 {
1037                         public RemoveDelegateMethod (EventField method):
1038                                 base (method, RemovePrefix)
1039                         {
1040                         }
1041
1042                         protected override Binary.Operator Operation {
1043                                 get { return Binary.Operator.Subtraction; }
1044                         }
1045                 }
1046
1047
1048                 static readonly string[] attribute_targets = new string [] { "event", "field", "method" };
1049                 static readonly string[] attribute_targets_interface = new string[] { "event", "method" };
1050
1051                 public Field BackingField;
1052                 public Expression Initializer;
1053
1054                 public EventField (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
1055                         : base (parent, type, mod_flags, name, attrs)
1056                 {
1057                         Add = new AddDelegateMethod (this);
1058                         Remove = new RemoveDelegateMethod (this);
1059                 }
1060
1061                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
1062                 {
1063                         if (a.Target == AttributeTargets.Field) {
1064                                 BackingField.ApplyAttributeBuilder (a, cb, pa);
1065                                 return;
1066                         }
1067
1068                         if (a.Target == AttributeTargets.Method) {
1069                                 int errors = Report.Errors;
1070                                 Add.ApplyAttributeBuilder (a, cb, pa);
1071                                 if (errors == Report.Errors)
1072                                         Remove.ApplyAttributeBuilder (a, cb, pa);
1073                                 return;
1074                         }
1075
1076                         base.ApplyAttributeBuilder (a, cb, pa);
1077                 }
1078
1079                 public override bool Define()
1080                 {
1081                         if (!base.Define ())
1082                                 return false;
1083
1084                         if (Initializer != null && (ModFlags & Modifiers.ABSTRACT) != 0) {
1085                                 Report.Error (74, Location, "`{0}': abstract event cannot have an initializer",
1086                                         GetSignatureForError ());
1087                         }
1088
1089                         if (!HasBackingField) {
1090                                 SetIsUsed ();
1091                                 return true;
1092                         }
1093
1094                         // FIXME: We are unable to detect whether generic event is used because
1095                         // we are using FieldExpr instead of EventExpr for event access in that
1096                         // case.  When this issue will be fixed this hack can be removed.
1097                         if (TypeManager.IsGenericType (MemberType) || Parent.IsGeneric)
1098                                 SetIsUsed ();
1099
1100                         if (Add.IsInterfaceImplementation)
1101                                 SetIsUsed ();
1102
1103                         BackingField = new Field (Parent,
1104                                 new TypeExpression (MemberType, Location),
1105                                 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
1106                                 MemberName, null);
1107
1108                         Parent.PartialContainer.AddField (BackingField);
1109                         BackingField.Initializer = Initializer;
1110                         BackingField.ModFlags &= ~Modifiers.COMPILER_GENERATED;
1111
1112                         // Call define because we passed fields definition
1113                         return BackingField.Define ();
1114                 }
1115
1116                 public bool HasBackingField {
1117                         get {
1118                                 return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0;
1119                         }
1120                 }
1121
1122                 public override string[] ValidAttributeTargets {
1123                         get {
1124                                 return HasBackingField ? attribute_targets : attribute_targets_interface;
1125                         }
1126                 }
1127         }
1128
1129         public abstract class Event : PropertyBasedMember {
1130                 public abstract class AEventAccessor : AbstractPropertyEventMethod
1131                 {
1132                         protected readonly Event method;
1133                         ImplicitParameter param_attr;
1134
1135                         static readonly string[] attribute_targets = new string [] { "method", "param", "return" };
1136
1137                         public const string AddPrefix = "add_";
1138                         public const string RemovePrefix = "remove_";
1139
1140                         protected AEventAccessor (Event method, string prefix)
1141                                 : base (method, prefix)
1142                         {
1143                                 this.method = method;
1144                                 this.ModFlags = method.ModFlags;
1145                         }
1146
1147                         protected AEventAccessor (Event method, Accessor accessor, string prefix)
1148                                 : base (method, accessor, prefix)
1149                         {
1150                                 this.method = method;
1151                                 this.ModFlags = method.ModFlags;
1152                         }
1153
1154                         public bool IsInterfaceImplementation {
1155                                 get { return method_data.implementing != null; }
1156                         }
1157
1158                         public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
1159                         {
1160                                 if (a.IsInternalMethodImplAttribute) {
1161                                         method.is_external_implementation = true;
1162                                 }
1163
1164                                 base.ApplyAttributeBuilder (a, cb, pa);
1165                         }
1166
1167                         protected override void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
1168                         {
1169                                 if (a.Target == AttributeTargets.Parameter) {
1170                                         if (param_attr == null)
1171                                                 param_attr = new ImplicitParameter (method_data.MethodBuilder);
1172
1173                                         param_attr.ApplyAttributeBuilder (a, cb, pa);
1174                                         return;
1175                                 }
1176
1177                                 base.ApplyAttributeBuilder (a, cb, pa);
1178                         }
1179
1180                         public override AttributeTargets AttributeTargets {
1181                                 get {
1182                                         return AttributeTargets.Method;
1183                                 }
1184                         }
1185
1186                         public override bool IsClsComplianceRequired ()
1187                         {
1188                                 return method.IsClsComplianceRequired ();
1189                         }
1190
1191                         public virtual MethodBuilder Define (DeclSpace parent)
1192                         {
1193                                 method_data = new MethodData (method, method.ModFlags,
1194                                         method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
1195
1196                                 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
1197                                         return null;
1198
1199                                 MethodBuilder mb = method_data.MethodBuilder;
1200                                 ParameterInfo.ApplyAttributes (mb);
1201                                 Spec = new MethodSpec (MemberKind.Method, this, mb, ParameterInfo, method.ModFlags);
1202
1203                                 return mb;
1204                         }
1205
1206                         public override Type ReturnType {
1207                                 get {
1208                                         return TypeManager.void_type;
1209                                 }
1210                         }
1211
1212                         public override ObsoleteAttribute GetObsoleteAttribute ()
1213                         {
1214                                 return method.GetObsoleteAttribute ();
1215                         }
1216
1217                         public override string[] ValidAttributeTargets {
1218                                 get {
1219                                         return attribute_targets;
1220                                 }
1221                         }
1222
1223                         public override ParametersCompiled ParameterInfo {
1224                                 get {
1225                                         return method.parameters;
1226                                 }
1227                         }
1228                 }
1229
1230
1231                 const Modifiers AllowedModifiers =
1232                         Modifiers.NEW |
1233                         Modifiers.PUBLIC |
1234                         Modifiers.PROTECTED |
1235                         Modifiers.INTERNAL |
1236                         Modifiers.PRIVATE |
1237                         Modifiers.STATIC |
1238                         Modifiers.VIRTUAL |
1239                         Modifiers.SEALED |
1240                         Modifiers.OVERRIDE |
1241                         Modifiers.UNSAFE |
1242                         Modifiers.ABSTRACT |
1243                         Modifiers.EXTERN;
1244
1245                 const Modifiers AllowedInterfaceModifiers =
1246                         Modifiers.NEW;
1247
1248                 public AEventAccessor Add, Remove;
1249                 public MyEventBuilder     EventBuilder;
1250                 public MethodBuilder AddBuilder, RemoveBuilder;
1251
1252                 ParametersCompiled parameters;
1253
1254                 protected Event (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
1255                         : base (parent, null, type, mod_flags,
1256                                 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
1257                                 name, attrs)
1258                 {
1259                 }
1260
1261                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
1262                 {
1263                         if ((a.HasSecurityAttribute)) {
1264                                 a.Error_InvalidSecurityParent ();
1265                                 return;
1266                         }
1267                         
1268                         EventBuilder.SetCustomAttribute (cb);
1269                 }
1270
1271                 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
1272                 {
1273                         return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
1274                 }
1275
1276                 public override AttributeTargets AttributeTargets {
1277                         get {
1278                                 return AttributeTargets.Event;
1279                         }
1280                 }
1281
1282                 public override bool Define ()
1283                 {
1284                         if (!base.Define ())
1285                                 return false;
1286
1287                         if (!TypeManager.IsDelegateType (MemberType)) {
1288                                 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
1289                         }
1290
1291                         parameters = ParametersCompiled.CreateFullyResolved (
1292                                 new Parameter (null, "value", Parameter.Modifier.NONE, null, Location), MemberType);
1293
1294                         if (!CheckBase ())
1295                                 return false;
1296
1297                         if (TypeManager.delegate_combine_delegate_delegate == null) {
1298                                 TypeManager.delegate_combine_delegate_delegate = TypeManager.GetPredefinedMethod (
1299                                         TypeManager.delegate_type, "Combine", Location,
1300                                         TypeManager.delegate_type, TypeManager.delegate_type);
1301                         }
1302                         if (TypeManager.delegate_remove_delegate_delegate == null) {
1303                                 TypeManager.delegate_remove_delegate_delegate = TypeManager.GetPredefinedMethod (
1304                                         TypeManager.delegate_type, "Remove", Location,
1305                                         TypeManager.delegate_type, TypeManager.delegate_type);
1306                         }
1307
1308                         //
1309                         // Now define the accessors
1310                         //
1311
1312                         AddBuilder = Add.Define (Parent);
1313                         if (AddBuilder == null)
1314                                 return false;
1315
1316                         RemoveBuilder = Remove.Define (Parent);
1317                         if (RemoveBuilder == null)
1318                                 return false;
1319
1320                         EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, EventAttributes.None, MemberType);                                           
1321                         EventBuilder.SetAddOnMethod (AddBuilder);
1322                         EventBuilder.SetRemoveOnMethod (RemoveBuilder);
1323
1324                         var spec = new EventSpec (this, EventBuilder, ModFlags, Add.Spec, Remove.Spec) {
1325                                 EventType = MemberType
1326                         };
1327
1328                         TypeManager.RegisterEventField (EventBuilder, spec);
1329
1330                         Parent.MemberCache.AddMember (EventBuilder, spec);
1331                         Parent.MemberCache.AddMember (AddBuilder, Add.Spec);
1332                         Parent.MemberCache.AddMember (RemoveBuilder, Remove.Spec);
1333                         
1334                         return true;
1335                 }
1336
1337                 public override void Emit ()
1338                 {
1339                         if (OptAttributes != null) {
1340                                 OptAttributes.Emit ();
1341                         }
1342
1343                         Add.Emit (Parent);
1344                         Remove.Emit (Parent);
1345
1346                         base.Emit ();
1347                 }
1348
1349                 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
1350                 {
1351                         MethodInfo mi = (MethodInfo) Parent.PartialContainer.BaseCache.FindBaseEvent (
1352                                 Parent.TypeBuilder, Name);
1353
1354                         if (mi == null)
1355                                 return null;
1356
1357                         AParametersCollection pd = TypeManager.GetParameterData (mi);
1358                         base_ret_type = pd.Types [0];
1359                         return mi;
1360                 }
1361
1362                 //
1363                 //   Represents header string for documentation comment.
1364                 //
1365                 public override string DocCommentHeader {
1366                         get { return "E:"; }
1367                 }
1368         }
1369
1370         public class EventSpec : MemberSpec
1371         {
1372                 EventInfo info;
1373
1374                 public EventSpec (IMemberDefinition definition, EventInfo info, Modifiers modifiers, MethodSpec add, MethodSpec remove)
1375                         : base (MemberKind.Event, definition, info.Name, modifiers)
1376                 {
1377                         this.info = info;
1378                         this.AccessorAdd = add;
1379                         this.AccessorRemove = remove;
1380
1381                         // TODO MemberCache: Remove
1382                         if (TypeManager.IsBeingCompiled (info))
1383                                 state &= ~MemberSpec.StateFlags.Obsolete_Undetected;
1384                 }
1385
1386                 public MethodSpec AccessorAdd { get; private set; }
1387                 public MethodSpec AccessorRemove { get; private set; }
1388
1389                 public override Type DeclaringType {
1390                         get { return info.DeclaringType; }
1391                 }
1392
1393                 public Type EventType { get; set; }
1394
1395                 public bool IsAbstract {
1396                         get { return (Modifiers & Modifiers.ABSTRACT) != 0; }
1397                 }
1398
1399                 public EventInfo MetaInfo {
1400                         get { return info; }
1401                 }
1402         }
1403  
1404         public class Indexer : PropertyBase
1405         {
1406                 public class GetIndexerMethod : GetMethod
1407                 {
1408                         ParametersCompiled parameters;
1409
1410                         public GetIndexerMethod (Indexer method):
1411                                 base (method)
1412                         {
1413                                 this.parameters = method.parameters;
1414                         }
1415
1416                         public GetIndexerMethod (PropertyBase method, Accessor accessor):
1417                                 base (method, accessor)
1418                         {
1419                                 parameters = accessor.Parameters;
1420                         }
1421
1422                         public override MethodBuilder Define (DeclSpace parent)
1423                         {
1424                                 parameters.Resolve (this);
1425                                 return base.Define (parent);
1426                         }
1427                         
1428                         public override bool EnableOverloadChecks (MemberCore overload)
1429                         {
1430                                 if (base.EnableOverloadChecks (overload)) {
1431                                         overload.caching_flags |= Flags.MethodOverloadsExist;
1432                                         return true;
1433                                 }
1434
1435                                 return false;
1436                         }                       
1437
1438                         public override ParametersCompiled ParameterInfo {
1439                                 get {
1440                                         return parameters;
1441                                 }
1442                         }
1443                 }
1444
1445                 public class SetIndexerMethod: SetMethod
1446                 {
1447                         public SetIndexerMethod (Indexer method):
1448                                 base (method)
1449                         {
1450                                 parameters = ParametersCompiled.MergeGenerated (Compiler, method.parameters, false, parameters [0], null);
1451                         }
1452
1453                         public SetIndexerMethod (PropertyBase method, Accessor accessor):
1454                                 base (method, accessor)
1455                         {
1456                                 parameters = method.Get.IsDummy ? accessor.Parameters : accessor.Parameters.Clone ();                   
1457                         }
1458
1459                         public override bool EnableOverloadChecks (MemberCore overload)
1460                         {
1461                                 if (base.EnableOverloadChecks (overload)) {
1462                                         overload.caching_flags |= Flags.MethodOverloadsExist;
1463                                         return true;
1464                                 }
1465
1466                                 return false;
1467                         }
1468                 }
1469
1470                 const Modifiers AllowedModifiers =
1471                         Modifiers.NEW |
1472                         Modifiers.PUBLIC |
1473                         Modifiers.PROTECTED |
1474                         Modifiers.INTERNAL |
1475                         Modifiers.PRIVATE |
1476                         Modifiers.VIRTUAL |
1477                         Modifiers.SEALED |
1478                         Modifiers.OVERRIDE |
1479                         Modifiers.UNSAFE |
1480                         Modifiers.EXTERN |
1481                         Modifiers.ABSTRACT;
1482
1483                 const Modifiers AllowedInterfaceModifiers =
1484                         Modifiers.NEW;
1485
1486                 public readonly ParametersCompiled parameters;
1487
1488                 public Indexer (DeclSpace parent, FullNamedExpression type, MemberName name, Modifiers mod,
1489                                 ParametersCompiled parameters, Attributes attrs,
1490                                 Accessor get_block, Accessor set_block, bool define_set_first)
1491                         : base (parent, type, mod,
1492                                 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
1493                                 name, attrs, define_set_first)
1494                 {
1495                         this.parameters = parameters;
1496
1497                         if (get_block == null)
1498                                 Get = new GetIndexerMethod (this);
1499                         else
1500                                 Get = new GetIndexerMethod (this, get_block);
1501
1502                         if (set_block == null)
1503                                 Set = new SetIndexerMethod (this);
1504                         else
1505                                 Set = new SetIndexerMethod (this, set_block);
1506                 }
1507
1508                 protected override bool CheckForDuplications ()
1509                 {
1510                         return Parent.MemberCache.CheckExistingMembersOverloads (this, GetFullName (MemberName), parameters, Report);
1511                 }
1512                 
1513                 public override bool Define ()
1514                 {
1515                         if (!base.Define ())
1516                                 return false;
1517
1518                         if (!DefineParameters (parameters))
1519                                 return false;
1520
1521                         if (OptAttributes != null) {
1522                                 Attribute indexer_attr = OptAttributes.Search (PredefinedAttributes.Get.IndexerName);
1523                                 if (indexer_attr != null) {
1524                                         // Remove the attribute from the list because it is not emitted
1525                                         OptAttributes.Attrs.Remove (indexer_attr);
1526
1527                                         string name = indexer_attr.GetIndexerAttributeValue ();
1528                                         if (name == null)
1529                                                 return false;
1530
1531                                         ShortName = name;
1532
1533                                         if (IsExplicitImpl) {
1534                                                 Report.Error (415, indexer_attr.Location,
1535                                                               "The `IndexerName' attribute is valid only on an " +
1536                                                               "indexer that is not an explicit interface member declaration");
1537                                                 return false;
1538                                         }
1539
1540                                         if ((ModFlags & Modifiers.OVERRIDE) != 0) {
1541                                                 Report.Error (609, indexer_attr.Location,
1542                                                               "Cannot set the `IndexerName' attribute on an indexer marked override");
1543                                                 return false;
1544                                         }
1545                                 }
1546                         }
1547
1548                         if (InterfaceType != null) {
1549                                 string base_IndexerName = TypeManager.IndexerPropertyName (InterfaceType);
1550                                 if (base_IndexerName != Name)
1551                                         ShortName = base_IndexerName;
1552                         }
1553
1554                         if (!Parent.PartialContainer.AddMember (this) ||
1555                                 !Parent.PartialContainer.AddMember (Get) || !Parent.PartialContainer.AddMember (Set))
1556                                 return false;
1557
1558                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
1559                         
1560                         if (!DefineAccessors ())
1561                                 return false;
1562
1563                         if (!CheckBase ())
1564                                 return false;
1565
1566                         DefineBuilders (MemberKind.Indexer, parameters.GetEmitTypes ());
1567                         TypeManager.RegisterIndexer (PropertyBuilder, parameters);
1568                         return true;
1569                 }
1570
1571                 public override bool EnableOverloadChecks (MemberCore overload)
1572                 {
1573                         if (overload is Indexer) {
1574                                 caching_flags |= Flags.MethodOverloadsExist;
1575                                 return true;
1576                         }
1577
1578                         return base.EnableOverloadChecks (overload);
1579                 }
1580
1581                 public override string GetDocCommentName (DeclSpace ds)
1582                 {
1583                         return DocUtil.GetMethodDocCommentName (this, parameters, ds);
1584                 }
1585
1586                 public override string GetSignatureForError ()
1587                 {
1588                         StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
1589                         if (MemberName.Left != null) {
1590                                 sb.Append ('.');
1591                                 sb.Append (MemberName.Left.GetSignatureForError ());
1592                         }
1593
1594                         sb.Append (".this");
1595                         sb.Append (parameters.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
1596                         return sb.ToString ();
1597                 }
1598
1599                 protected override PropertyInfo ResolveBaseProperty ()
1600                 {
1601                         return Parent.PartialContainer.BaseCache.FindMemberToOverride (
1602                                 Parent.TypeBuilder, Name, parameters, null, true) as PropertyInfo;
1603                 }
1604
1605                 protected override bool VerifyClsCompliance ()
1606                 {
1607                         if (!base.VerifyClsCompliance ())
1608                                 return false;
1609
1610                         parameters.VerifyClsCompliance (this);
1611                         return true;
1612                 }
1613         }
1614 }