2009-07-20 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / class.cs
blob3928ee5adc7f0a2fa374a9823f32361435675bda
1 //
2 // class.cs: Class and Struct 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
14 using System;
15 using System.Collections;
16 using System.Collections.Specialized;
17 using System.Reflection;
18 using System.Reflection.Emit;
19 using System.Runtime.CompilerServices;
20 using System.Runtime.InteropServices;
21 using System.Security;
22 using System.Security.Permissions;
23 using System.Text;
25 #if BOOTSTRAP_WITH_OLDLIB || NET_2_1
26 using XmlElement = System.Object;
27 #else
28 using System.Xml;
29 #endif
31 using Mono.CompilerServices.SymbolWriter;
33 namespace Mono.CSharp {
35 public enum Kind {
36 Root,
37 Struct,
38 Class,
39 Interface,
40 Enum,
41 Delegate
44 /// <summary>
45 /// This is the base class for structs and classes.
46 /// </summary>
47 public abstract class TypeContainer : DeclSpace, IMemberContainer {
49 public class MemberCoreArrayList: ArrayList
51 /// <summary>
52 /// Defines the MemberCore objects that are in this array
53 /// </summary>
54 public virtual void DefineContainerMembers ()
56 foreach (MemberCore mc in this) {
57 try {
58 mc.Define ();
59 } catch (Exception e) {
60 throw new InternalErrorException (mc, e);
65 public virtual void Emit ()
67 foreach (MemberCore mc in this)
68 mc.Emit ();
72 public class OperatorArrayList: MemberCoreArrayList
74 TypeContainer container;
76 public OperatorArrayList (TypeContainer container)
78 this.container = container;
82 // Checks that some operators come in pairs:
83 // == and !=
84 // > and <
85 // >= and <=
86 // true and false
88 // They are matched based on the return type and the argument types
90 void CheckPairedOperators ()
92 bool has_equality_or_inequality = false;
93 Operator[] operators = (Operator[]) ToArray (typeof (Operator));
94 bool [] has_pair = new bool [operators.Length];
96 for (int i = 0; i < Count; ++i) {
97 if (operators [i] == null)
98 continue;
100 Operator o_a = operators [i];
101 Operator.OpType o_type = o_a.OperatorType;
102 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
103 has_equality_or_inequality = true;
105 Operator.OpType matching_type = o_a.GetMatchingOperator ();
106 if (matching_type == Operator.OpType.TOP) {
107 operators [i] = null;
108 continue;
111 for (int ii = 0; ii < Count; ++ii) {
112 Operator o_b = operators [ii];
113 if (o_b == null || o_b.OperatorType != matching_type)
114 continue;
116 if (!TypeManager.IsEqual (o_a.ReturnType, o_b.ReturnType))
117 continue;
119 if (!TypeManager.IsEqual (o_a.ParameterTypes, o_b.ParameterTypes))
120 continue;
122 operators [i] = null;
125 // Used to ignore duplicate user conversions
127 has_pair [ii] = true;
131 for (int i = 0; i < Count; ++i) {
132 if (operators [i] == null || has_pair [i])
133 continue;
135 Operator o = operators [i];
136 Report.Error (216, o.Location,
137 "The operator `{0}' requires a matching operator `{1}' to also be defined",
138 o.GetSignatureForError (), Operator.GetName (o.GetMatchingOperator ()));
141 if (has_equality_or_inequality && Report.WarningLevel > 2) {
142 if (container.Methods == null || !container.HasEquals)
143 Report.Warning (660, 2, container.Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)", container.GetSignatureForError ());
145 if (container.Methods == null || !container.HasGetHashCode)
146 Report.Warning (661, 2, container.Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()", container.GetSignatureForError ());
150 public override void DefineContainerMembers ()
152 base.DefineContainerMembers ();
153 CheckPairedOperators ();
157 [Flags]
158 enum CachedMethods
160 Equals = 1,
161 GetHashCode = 1 << 1,
162 HasStaticFieldInitializer = 1 << 2
166 // Whether this is a struct, class or interface
167 public readonly Kind Kind;
169 // Holds a list of classes and structures
170 protected ArrayList types;
172 MemberCoreArrayList ordered_explicit_member_list;
173 MemberCoreArrayList ordered_member_list;
175 // Holds the list of properties
176 MemberCoreArrayList properties;
178 // Holds the list of delegates
179 MemberCoreArrayList delegates;
181 // Holds the list of constructors
182 protected MemberCoreArrayList instance_constructors;
184 // Holds the list of fields
185 protected MemberCoreArrayList fields;
187 // Holds a list of fields that have initializers
188 protected ArrayList initialized_fields;
190 // Holds a list of static fields that have initializers
191 protected ArrayList initialized_static_fields;
193 // Holds the list of constants
194 protected MemberCoreArrayList constants;
196 // Holds the methods.
197 MemberCoreArrayList methods;
199 // Holds the events
200 protected MemberCoreArrayList events;
202 // Holds the indexers
203 ArrayList indexers;
205 // Holds the operators
206 MemberCoreArrayList operators;
208 // Holds the compiler generated classes
209 ArrayList compiler_generated;
212 // Pointers to the default constructor and the default static constructor
214 protected Constructor default_constructor;
215 protected Constructor default_static_constructor;
218 // Points to the first non-static field added to the container.
220 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
221 // and the first one's as good as any.
223 FieldBase first_nonstatic_field = null;
226 // This one is computed after we can distinguish interfaces
227 // from classes from the arraylist `type_bases'
229 TypeExpr base_type;
230 TypeExpr[] iface_exprs;
231 Type GenericType;
232 GenericTypeParameterBuilder[] nested_gen_params;
234 protected ArrayList type_bases;
236 protected bool members_defined;
237 bool members_defined_ok;
239 // The interfaces we implement.
240 protected Type[] ifaces;
242 // The base member cache and our member cache
243 MemberCache base_cache;
244 protected MemberCache member_cache;
246 public const string DefaultIndexerName = "Item";
248 private bool seen_normal_indexers = false;
249 private string indexer_name = DefaultIndexerName;
250 protected bool requires_delayed_unmanagedtype_check;
252 private CachedMethods cached_method;
254 ArrayList partial_parts;
256 /// <remarks>
257 /// The pending methods that need to be implemented
258 // (interfaces or abstract methods)
259 /// </remarks>
260 PendingImplementation pending;
262 public TypeContainer (NamespaceEntry ns, DeclSpace parent, MemberName name,
263 Attributes attrs, Kind kind)
264 : base (ns, parent, name, attrs)
266 if (parent != null && parent.NamespaceEntry != ns)
267 throw new InternalErrorException ("A nested type should be in the same NamespaceEntry as its enclosing class");
269 this.Kind = kind;
270 this.PartialContainer = this;
273 public bool AddMember (MemberCore symbol)
275 return AddToContainer (symbol, symbol.MemberName.Basename);
278 protected virtual bool AddMemberType (DeclSpace ds)
280 return AddToContainer (ds, ds.Basename);
283 protected virtual void RemoveMemberType (DeclSpace ds)
285 RemoveFromContainer (ds.Basename);
288 public void AddConstant (Const constant)
290 if (!AddMember (constant))
291 return;
293 if (constants == null)
294 constants = new MemberCoreArrayList ();
296 constants.Add (constant);
299 public TypeContainer AddTypeContainer (TypeContainer tc)
301 if (!AddMemberType (tc))
302 return tc;
304 if (types == null)
305 types = new MemberCoreArrayList ();
306 types.Add (tc);
308 return tc;
311 public virtual TypeContainer AddPartial (TypeContainer next_part)
313 return AddPartial (next_part, next_part.Basename);
316 protected TypeContainer AddPartial (TypeContainer next_part, string name)
318 next_part.ModFlags |= Modifiers.PARTIAL;
319 TypeContainer tc = defined_names [name] as TypeContainer;
321 if (tc == null)
322 return AddTypeContainer (next_part);
324 if ((tc.ModFlags & Modifiers.PARTIAL) == 0) {
325 Report.SymbolRelatedToPreviousError (next_part);
326 Error_MissingPartialModifier (tc);
329 if (tc.Kind != next_part.Kind) {
330 Report.SymbolRelatedToPreviousError (tc);
331 Report.Error (261, next_part.Location,
332 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
333 next_part.GetSignatureForError ());
336 if ((tc.ModFlags & Modifiers.Accessibility) != (next_part.ModFlags & Modifiers.Accessibility) &&
337 ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 &&
338 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
339 Report.SymbolRelatedToPreviousError (tc);
340 Report.Error (262, next_part.Location,
341 "Partial declarations of `{0}' have conflicting accessibility modifiers",
342 next_part.GetSignatureForError ());
345 if (tc.partial_parts == null)
346 tc.partial_parts = new ArrayList (1);
348 if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
349 tc.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.Accessibility);
350 } else if ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
351 tc.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.Accessibility);
352 tc.ModFlags |= next_part.ModFlags;
353 } else {
354 tc.ModFlags |= next_part.ModFlags;
357 if (next_part.attributes != null) {
358 if (tc.attributes == null)
359 tc.attributes = next_part.attributes;
360 else
361 tc.attributes.AddAttributes (next_part.attributes.Attrs);
364 next_part.PartialContainer = tc;
365 tc.partial_parts.Add (next_part);
366 return tc;
369 public virtual void RemoveTypeContainer (TypeContainer next_part)
371 if (types != null)
372 types.Remove (next_part);
373 RemoveMemberType (next_part);
376 public void AddDelegate (Delegate d)
378 if (!AddMemberType (d))
379 return;
381 if (delegates == null)
382 delegates = new MemberCoreArrayList ();
384 delegates.Add (d);
387 private void AddMemberToList (MemberCore mc, ArrayList alist, bool isexplicit)
389 if (ordered_explicit_member_list == null) {
390 ordered_explicit_member_list = new MemberCoreArrayList ();
391 ordered_member_list = new MemberCoreArrayList ();
394 if (isexplicit) {
395 if (Kind == Kind.Interface) {
396 Report.Error (541, mc.Location,
397 "`{0}': explicit interface declaration can only be declared in a class or struct",
398 mc.GetSignatureForError ());
401 ordered_explicit_member_list.Add (mc);
402 alist.Insert (0, mc);
403 } else {
404 ordered_member_list.Add (mc);
405 alist.Add (mc);
410 public void AddMethod (MethodOrOperator method)
412 if (!AddToContainer (method, method.MemberName.Basename))
413 return;
415 if (methods == null)
416 methods = new MemberCoreArrayList ();
418 if (method.MemberName.Left != null)
419 AddMemberToList (method, methods, true);
420 else
421 AddMemberToList (method, methods, false);
424 public void AddConstructor (Constructor c)
426 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
427 if (!AddToContainer (c, is_static ?
428 ConstructorBuilder.ConstructorName : ConstructorBuilder.TypeConstructorName))
429 return;
431 if (is_static && c.Parameters.IsEmpty){
432 if (default_static_constructor != null) {
433 Report.SymbolRelatedToPreviousError (default_static_constructor);
434 Report.Error (111, c.Location,
435 "A member `{0}' is already defined. Rename this member or use different parameter types",
436 c.GetSignatureForError ());
437 return;
440 default_static_constructor = c;
441 } else {
442 if (c.Parameters.IsEmpty)
443 default_constructor = c;
445 if (instance_constructors == null)
446 instance_constructors = new MemberCoreArrayList ();
448 instance_constructors.Add (c);
452 public bool AddField (FieldBase field)
454 if (!AddMember (field))
455 return false;
457 if (fields == null)
458 fields = new MemberCoreArrayList ();
460 fields.Add (field);
462 if ((field.ModFlags & Modifiers.STATIC) != 0)
463 return true;
465 if (first_nonstatic_field == null) {
466 first_nonstatic_field = field;
467 return true;
470 if (Kind == Kind.Struct && first_nonstatic_field.Parent != field.Parent) {
471 Report.SymbolRelatedToPreviousError (first_nonstatic_field.Parent);
472 Report.Warning (282, 3, field.Location,
473 "struct instance field `{0}' found in different declaration from instance field `{1}'",
474 field.GetSignatureForError (), first_nonstatic_field.GetSignatureForError ());
476 return true;
479 public void AddProperty (Property prop)
481 if (!AddMember (prop) ||
482 !AddMember (prop.Get) || !AddMember (prop.Set))
483 return;
485 if (properties == null)
486 properties = new MemberCoreArrayList ();
488 if (prop.MemberName.Left != null)
489 AddMemberToList (prop, properties, true);
490 else
491 AddMemberToList (prop, properties, false);
494 public void AddEvent (Event e)
496 if (!AddMember (e))
497 return;
499 if (e is EventProperty) {
500 if (!AddMember (e.Add))
501 return;
503 if (!AddMember (e.Remove))
504 return;
507 if (events == null)
508 events = new MemberCoreArrayList ();
510 events.Add (e);
513 /// <summary>
514 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
515 /// </summary>
516 public void AddIndexer (Indexer i)
518 if (indexers == null)
519 indexers = new ArrayList ();
521 if (i.IsExplicitImpl)
522 AddMemberToList (i, indexers, true);
523 else
524 AddMemberToList (i, indexers, false);
527 public void AddOperator (Operator op)
529 if (!AddMember (op))
530 return;
532 if (operators == null)
533 operators = new OperatorArrayList (this);
535 operators.Add (op);
538 public void AddCompilerGeneratedClass (CompilerGeneratedClass c)
540 Report.Debug (64, "ADD COMPILER GENERATED CLASS", this, c);
542 if (compiler_generated == null)
543 compiler_generated = new ArrayList ();
545 compiler_generated.Add (c);
548 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
550 if (a.Type == pa.DefaultMember) {
551 if (Indexers != null) {
552 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
553 return;
557 base.ApplyAttributeBuilder (a, cb, pa);
560 public override AttributeTargets AttributeTargets {
561 get {
562 throw new NotSupportedException ();
566 public ArrayList Types {
567 get {
568 return types;
572 public MemberCoreArrayList Methods {
573 get {
574 return methods;
578 public ArrayList Constants {
579 get {
580 return constants;
584 protected Type BaseType {
585 get {
586 return TypeBuilder.BaseType;
590 public ArrayList Fields {
591 get {
592 return fields;
596 public ArrayList InstanceConstructors {
597 get {
598 return instance_constructors;
602 public ArrayList Properties {
603 get {
604 return properties;
608 public ArrayList Events {
609 get {
610 return events;
614 public ArrayList Indexers {
615 get {
616 return indexers;
620 public ArrayList Operators {
621 get {
622 return operators;
626 public ArrayList Delegates {
627 get {
628 return delegates;
632 protected override TypeAttributes TypeAttr {
633 get {
634 return Modifiers.TypeAttr (ModFlags, IsTopLevel) | base.TypeAttr;
638 public string IndexerName {
639 get {
640 return indexers == null ? DefaultIndexerName : indexer_name;
644 public bool IsComImport {
645 get {
646 if (OptAttributes == null)
647 return false;
649 return OptAttributes.Contains (PredefinedAttributes.Get.ComImport);
653 public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
655 if ((field.ModFlags & Modifiers.STATIC) != 0){
656 if (initialized_static_fields == null) {
657 PartialContainer.HasStaticFieldInitializer = true;
658 initialized_static_fields = new ArrayList (4);
661 initialized_static_fields.Add (expression);
662 } else {
663 if (initialized_fields == null)
664 initialized_fields = new ArrayList (4);
666 initialized_fields.Add (expression);
670 public void ResolveFieldInitializers (EmitContext ec)
672 if (partial_parts != null) {
673 foreach (TypeContainer part in partial_parts) {
674 part.DoResolveFieldInitializers (ec);
677 DoResolveFieldInitializers (ec);
680 void DoResolveFieldInitializers (EmitContext ec)
682 if (ec.IsStatic) {
683 if (initialized_static_fields == null)
684 return;
686 bool has_complex_initializer = !RootContext.Optimize;
687 int i;
688 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
689 for (i = 0; i < initialized_static_fields.Count; ++i) {
690 FieldInitializer fi = (FieldInitializer) initialized_static_fields [i];
691 ExpressionStatement s = fi.ResolveStatement (ec);
692 if (s == null) {
693 s = EmptyExpressionStatement.Instance;
694 } else if (fi.IsComplexInitializer) {
695 has_complex_initializer |= true;
698 init [i] = s;
701 for (i = 0; i < initialized_static_fields.Count; ++i) {
702 FieldInitializer fi = (FieldInitializer) initialized_static_fields [i];
704 // Need special check to not optimize code like this
705 // static int a = b = 5;
706 // static int b = 0;
708 if (!has_complex_initializer && fi.IsDefaultInitializer)
709 continue;
711 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
714 return;
717 if (initialized_fields == null)
718 return;
720 for (int i = 0; i < initialized_fields.Count; ++i) {
721 FieldInitializer fi = (FieldInitializer) initialized_fields [i];
722 ExpressionStatement s = fi.ResolveStatement (ec);
723 if (s == null)
724 continue;
727 // Field is re-initialized to its default value => removed
729 if (fi.IsDefaultInitializer && RootContext.Optimize)
730 continue;
732 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
737 // Emits the instance field initializers
739 public bool EmitFieldInitializers (EmitContext ec)
741 if (partial_parts != null) {
742 foreach (TypeContainer part in partial_parts)
743 part.EmitFieldInitializers (ec);
746 ArrayList fields;
748 if (ec.IsStatic){
749 fields = initialized_static_fields;
750 } else {
751 fields = initialized_fields;
754 if (fields == null)
755 return true;
757 foreach (FieldInitializer f in fields) {
758 f.EmitStatement (ec);
760 return true;
763 public override string DocComment {
764 get {
765 return comment;
767 set {
768 if (value == null)
769 return;
771 comment += value;
775 public PendingImplementation PendingImplementations {
776 get { return pending; }
779 public override bool GetClsCompliantAttributeValue ()
781 if (PartialContainer != this)
782 return PartialContainer.GetClsCompliantAttributeValue ();
784 return base.GetClsCompliantAttributeValue ();
787 public virtual void AddBasesForPart (DeclSpace part, ArrayList bases)
789 // FIXME: get rid of partial_parts and store lists of bases of each part here
790 // assumed, not verified: 'part' is in 'partial_parts'
791 ((TypeContainer) part).type_bases = bases;
794 /// <summary>
795 /// This function computes the Base class and also the
796 /// list of interfaces that the class or struct @c implements.
797 ///
798 /// The return value is an array (might be null) of
799 /// interfaces implemented (as Types).
800 ///
801 /// The @base_class argument is set to the base object or null
802 /// if this is `System.Object'.
803 /// </summary>
804 protected virtual TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
806 base_class = null;
807 if (type_bases == null)
808 return null;
810 int count = type_bases.Count;
811 TypeExpr [] ifaces = null;
812 for (int i = 0, j = 0; i < count; i++){
813 FullNamedExpression fne = (FullNamedExpression) type_bases [i];
816 // Standard ResolveAsTypeTerminal cannot be used in this case because
817 // it does ObsoleteAttribute and constraint checks which require
818 // base type to be set
820 TypeExpr fne_resolved = fne.ResolveAsBaseTerminal (this, false);
821 if (fne_resolved == null)
822 continue;
824 if (i == 0 && Kind == Kind.Class && !fne_resolved.Type.IsInterface) {
825 base_class = fne_resolved;
826 continue;
829 if (ifaces == null)
830 ifaces = new TypeExpr [count - i];
832 if (fne_resolved.Type.IsInterface) {
833 for (int ii = 0; ii < j; ++ii) {
834 if (TypeManager.IsEqual (fne_resolved.Type, ifaces [ii].Type)) {
835 Report.Error (528, Location, "`{0}' is already listed in interface list",
836 fne_resolved.GetSignatureForError ());
837 break;
841 if (Kind == Kind.Interface && !IsAccessibleAs (fne_resolved.Type)) {
842 Report.Error (61, fne.Location,
843 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
844 fne_resolved.GetSignatureForError (), GetSignatureForError ());
846 } else {
847 Report.SymbolRelatedToPreviousError (fne_resolved.Type);
848 if (Kind != Kind.Class) {
849 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
850 } else if (base_class != null)
851 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
852 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
853 else {
854 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
855 GetSignatureForError (), fne_resolved.GetSignatureForError ());
859 ifaces [j++] = fne_resolved;
862 return ifaces;
865 TypeExpr[] GetNormalPartialBases (ref TypeExpr base_class)
867 ArrayList ifaces = new ArrayList (0);
868 if (iface_exprs != null)
869 ifaces.AddRange (iface_exprs);
871 foreach (TypeContainer part in partial_parts) {
872 TypeExpr new_base_class;
873 TypeExpr[] new_ifaces = part.ResolveBaseTypes (out new_base_class);
874 if (new_base_class != TypeManager.system_object_expr) {
875 if (base_class == TypeManager.system_object_expr)
876 base_class = new_base_class;
877 else {
878 if (new_base_class != null && !new_base_class.Equals (base_class)) {
879 Report.SymbolRelatedToPreviousError (base_class.Location, "");
880 Report.Error (263, part.Location,
881 "Partial declarations of `{0}' must not specify different base classes",
882 part.GetSignatureForError ());
884 return null;
889 if (new_ifaces == null)
890 continue;
892 foreach (TypeExpr iface in new_ifaces) {
893 if (ifaces.Contains (iface))
894 continue;
896 ifaces.Add (iface);
900 if (ifaces.Count == 0)
901 return null;
903 return (TypeExpr[])ifaces.ToArray (typeof (TypeExpr));
906 bool CheckGenericInterfaces (Type[] ifaces)
908 #if GMCS_SOURCE
909 ArrayList already_checked = new ArrayList ();
911 for (int i = 0; i < ifaces.Length; i++) {
912 Type iface = ifaces [i];
913 foreach (Type t in already_checked) {
914 if (iface == t)
915 continue;
917 Type[] inferred = new Type [CountTypeParameters];
918 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t, inferred, null))
919 continue;
921 Report.Error (695, Location,
922 "`{0}' cannot implement both `{1}' and `{2}' " +
923 "because they may unify for some type parameter substitutions",
924 TypeManager.CSharpName (TypeBuilder), TypeManager.CSharpName (iface),
925 TypeManager.CSharpName (t));
926 return false;
929 already_checked.Add (iface);
931 #endif
933 return true;
936 bool error = false;
938 bool CreateTypeBuilder ()
940 try {
941 Type default_parent = null;
942 if (Kind == Kind.Struct)
943 default_parent = TypeManager.value_type;
944 else if (Kind == Kind.Enum)
945 default_parent = TypeManager.enum_type;
948 // Sets .size to 1 for structs with no instance fields
950 int type_size = Kind == Kind.Struct && first_nonstatic_field == null ? 1 : 0;
952 if (IsTopLevel){
953 if (TypeManager.NamespaceClash (Name, Location)) {
954 return false;
957 ModuleBuilder builder = Module.Builder;
958 TypeBuilder = builder.DefineType (
959 Name, TypeAttr, default_parent, type_size);
960 } else {
961 TypeBuilder builder = Parent.TypeBuilder;
963 TypeBuilder = builder.DefineNestedType (
964 Basename, TypeAttr, default_parent, type_size);
966 } catch (ArgumentException) {
967 Report.RuntimeMissingSupport (Location, "static classes");
968 return false;
971 TypeManager.AddUserType (this);
973 if (IsGeneric) {
974 string[] param_names = new string [TypeParameters.Length];
975 for (int i = 0; i < TypeParameters.Length; i++)
976 param_names [i] = TypeParameters [i].Name;
978 #if GMCS_SOURCE
979 GenericTypeParameterBuilder[] gen_params = TypeBuilder.DefineGenericParameters (param_names);
981 int offset = CountTypeParameters - CurrentTypeParameters.Length;
982 if (offset > 0) {
983 nested_gen_params = new GenericTypeParameterBuilder [offset];
984 Array.Copy (gen_params, nested_gen_params, offset);
987 for (int i = offset; i < gen_params.Length; i++)
988 CurrentTypeParameters [i - offset].Define (gen_params [i]);
989 #else
990 nested_gen_params = null;
991 throw new NotSupportedException ();
992 #endif
995 return true;
998 bool DefineBaseTypes ()
1000 iface_exprs = ResolveBaseTypes (out base_type);
1001 if (partial_parts != null) {
1002 iface_exprs = GetNormalPartialBases (ref base_type);
1006 // GetClassBases calls ResolveBaseTypeExpr() on the various type expressions involved,
1007 // which in turn should have called DefineType()s on base types if necessary.
1009 // None of the code below should trigger DefineType()s on classes that we depend on.
1010 // Thus, we are eligible to be on the topological sort `type_container_resolve_order'.
1012 // Let's do it as soon as possible, since code below can call DefineType() on classes
1013 // that depend on us to be populated before they are.
1015 if (!(this is CompilerGeneratedClass))
1016 RootContext.RegisterOrder (this);
1018 if (!CheckRecursiveDefinition (this))
1019 return false;
1021 if (base_type != null && base_type.Type != null) {
1022 TypeBuilder.SetParent (base_type.Type);
1025 // add interfaces that were not added at type creation
1026 if (iface_exprs != null) {
1027 ifaces = TypeManager.ExpandInterfaces (iface_exprs);
1028 if (ifaces == null)
1029 return false;
1031 foreach (Type itype in ifaces)
1032 TypeBuilder.AddInterfaceImplementation (itype);
1034 if (!CheckGenericInterfaces (ifaces))
1035 return false;
1037 TypeManager.RegisterBuilder (TypeBuilder, ifaces);
1040 return true;
1044 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1046 public TypeBuilder CreateType ()
1048 if (TypeBuilder != null)
1049 return TypeBuilder;
1051 if (error)
1052 return null;
1054 if (!CreateTypeBuilder ()) {
1055 error = true;
1056 return null;
1059 if (partial_parts != null) {
1060 foreach (TypeContainer part in partial_parts)
1061 part.TypeBuilder = TypeBuilder;
1064 if (Types != null) {
1065 foreach (TypeContainer tc in Types) {
1066 if (tc.CreateType () == null) {
1067 error = true;
1068 return null;
1073 return TypeBuilder;
1076 bool type_defined;
1078 public override TypeBuilder DefineType ()
1080 if (error)
1081 return null;
1082 if (type_defined)
1083 return TypeBuilder;
1085 type_defined = true;
1087 if (CreateType () == null) {
1088 error = true;
1089 return null;
1092 if (!DefineBaseTypes ()) {
1093 error = true;
1094 return null;
1097 if (!DefineNestedTypes ()) {
1098 error = true;
1099 return null;
1102 return TypeBuilder;
1105 public override void SetParameterInfo (ArrayList constraints_list)
1107 base.SetParameterInfo (constraints_list);
1109 if (!is_generic || PartialContainer == this)
1110 return;
1112 TypeParameter[] tc_names = PartialContainer.TypeParameters;
1113 for (int i = 0; i < tc_names.Length; ++i) {
1114 if (tc_names [i].Name != type_params [i].Name) {
1115 Report.SymbolRelatedToPreviousError (PartialContainer.Location, "");
1116 Report.Error (264, Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
1117 GetSignatureForError ());
1118 break;
1123 void UpdateTypeParameterConstraints (TypeContainer part)
1125 TypeParameter[] current_params = CurrentTypeParameters;
1126 for (int i = 0; i < current_params.Length; i++) {
1127 Constraints c = part.CurrentTypeParameters [i].Constraints;
1128 if (c == null)
1129 continue;
1131 if (current_params [i].UpdateConstraints (part, c))
1132 continue;
1134 Report.SymbolRelatedToPreviousError (Location, "");
1135 Report.Error (265, part.Location,
1136 "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'",
1137 GetSignatureForError (), current_params [i].GetSignatureForError ());
1141 public bool ResolveType ()
1143 if (!DoResolveType ())
1144 return false;
1146 if (compiler_generated != null) {
1147 foreach (CompilerGeneratedClass c in compiler_generated)
1148 if (!c.ResolveType ())
1149 return false;
1152 return true;
1155 protected virtual bool DoResolveType ()
1157 if (!IsGeneric)
1158 return true;
1160 if (PartialContainer != this)
1161 throw new InternalErrorException ();
1163 TypeExpr current_type = null;
1165 foreach (TypeParameter type_param in CurrentTypeParameters) {
1166 if (!type_param.Resolve (this)) {
1167 error = true;
1168 return false;
1172 if (partial_parts != null && is_generic) {
1173 foreach (TypeContainer part in partial_parts)
1174 UpdateTypeParameterConstraints (part);
1177 for (int i = 0; i < TypeParameters.Length; ++i) {
1179 // FIXME: Same should be done for delegates
1180 // TODO: Quite ugly way how to propagate constraints to
1181 // nested types
1183 if (nested_gen_params != null && i < nested_gen_params.Length) {
1184 TypeParameters [i].SetConstraints (nested_gen_params [i]);
1185 } else {
1186 if (!TypeParameters [i].DefineType (this)) {
1187 error = true;
1188 return false;
1193 // TODO: Very strange, why not simple make generic type from
1194 // current type parameters
1195 current_type = new GenericTypeExpr (this, Location);
1196 current_type = current_type.ResolveAsTypeTerminal (this, false);
1197 if (current_type == null) {
1198 error = true;
1199 return false;
1202 CurrentType = current_type.Type;
1203 return true;
1206 protected virtual bool DefineNestedTypes ()
1208 if (Types != null) {
1209 foreach (TypeContainer tc in Types)
1210 if (tc.DefineType () == null)
1211 return false;
1214 if (Delegates != null) {
1215 foreach (Delegate d in Delegates)
1216 if (d.DefineType () == null)
1217 return false;
1220 return true;
1223 TypeContainer InTransit;
1225 protected bool CheckRecursiveDefinition (TypeContainer tc)
1227 if (InTransit != null) {
1228 Report.SymbolRelatedToPreviousError (this);
1229 if (this is Interface)
1230 Report.Error (
1231 529, tc.Location, "Inherited interface `{0}' causes a " +
1232 "cycle in the interface hierarchy of `{1}'",
1233 GetSignatureForError (), tc.GetSignatureForError ());
1234 else
1235 Report.Error (
1236 146, tc.Location, "Circular base class dependency " +
1237 "involving `{0}' and `{1}'",
1238 tc.GetSignatureForError (), GetSignatureForError ());
1239 return false;
1242 InTransit = tc;
1244 if (base_type != null && base_type.Type != null) {
1245 Type t = TypeManager.DropGenericTypeArguments (base_type.Type);
1246 TypeContainer ptc = TypeManager.LookupTypeContainer (t);
1247 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1248 return false;
1251 if (iface_exprs != null) {
1252 foreach (TypeExpr iface in iface_exprs) {
1253 Type itype = TypeManager.DropGenericTypeArguments (iface.Type);
1254 TypeContainer ptc = TypeManager.LookupTypeContainer (itype);
1255 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1256 return false;
1260 if (!IsTopLevel && !Parent.PartialContainer.CheckRecursiveDefinition (this))
1261 return false;
1263 InTransit = null;
1264 return true;
1267 /// <summary>
1268 /// Populates our TypeBuilder with fields and methods
1269 /// </summary>
1270 public override bool Define ()
1272 if (members_defined)
1273 return members_defined_ok;
1275 members_defined_ok = DoDefineMembers ();
1276 members_defined = true;
1278 return members_defined_ok;
1281 protected virtual bool DoDefineMembers ()
1283 if (iface_exprs != null) {
1284 foreach (TypeExpr iface in iface_exprs) {
1285 ObsoleteAttribute oa = AttributeTester.GetObsoleteAttribute (iface.Type);
1286 if ((oa != null) && !IsInObsoleteScope)
1287 AttributeTester.Report_ObsoleteMessage (
1288 oa, iface.GetSignatureForError (), Location);
1290 GenericTypeExpr ct = iface as GenericTypeExpr;
1291 if (ct != null) {
1292 // TODO: passing `this' is wrong, should be base type iface instead
1293 TypeManager.CheckTypeVariance (ct.Type, Variance.Covariant, this);
1295 if (!ct.CheckConstraints (this))
1296 return false;
1301 if (base_type != null) {
1302 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (base_type.Type);
1303 if (obsolete_attr != null && !IsInObsoleteScope)
1304 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), Location);
1306 GenericTypeExpr ct = base_type as GenericTypeExpr;
1307 if ((ct != null) && !ct.CheckConstraints (this))
1308 return false;
1310 TypeContainer baseContainer = TypeManager.LookupTypeContainer(base_type.Type);
1311 if (baseContainer != null)
1312 baseContainer.Define();
1314 member_cache = new MemberCache (base_type.Type, this);
1315 } else if (Kind == Kind.Interface) {
1316 member_cache = new MemberCache (null, this);
1317 Type [] ifaces = TypeManager.GetInterfaces (TypeBuilder);
1318 for (int i = 0; i < ifaces.Length; ++i)
1319 member_cache.AddInterface (TypeManager.LookupMemberCache (ifaces [i]));
1320 } else {
1321 member_cache = new MemberCache (null, this);
1324 if (types != null)
1325 foreach (TypeContainer tc in types)
1326 member_cache.AddNestedType (tc);
1328 if (delegates != null)
1329 foreach (Delegate d in delegates)
1330 member_cache.AddNestedType (d);
1332 if (partial_parts != null) {
1333 foreach (TypeContainer part in partial_parts)
1334 part.member_cache = member_cache;
1337 if (!IsTopLevel) {
1338 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Basename, false);
1339 if (conflict_symbol == null) {
1340 if ((ModFlags & Modifiers.NEW) != 0)
1341 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
1342 } else {
1343 if ((ModFlags & Modifiers.NEW) == 0) {
1344 Report.SymbolRelatedToPreviousError (conflict_symbol);
1345 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
1346 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
1351 DefineContainerMembers (constants);
1352 DefineContainerMembers (fields);
1354 if (Kind == Kind.Struct || Kind == Kind.Class) {
1355 pending = PendingImplementation.GetPendingImplementations (this);
1357 if (requires_delayed_unmanagedtype_check) {
1358 requires_delayed_unmanagedtype_check = false;
1359 foreach (FieldBase f in fields) {
1360 if (f.MemberType != null && f.MemberType.IsPointer)
1361 TypeManager.VerifyUnManaged (f.MemberType, f.Location);
1367 // Constructors are not in the defined_names array
1369 DefineContainerMembers (instance_constructors);
1371 DefineContainerMembers (events);
1372 DefineContainerMembers (ordered_explicit_member_list);
1373 DefineContainerMembers (ordered_member_list);
1375 DefineContainerMembers (operators);
1376 DefineContainerMembers (delegates);
1378 ComputeIndexerName();
1379 CheckEqualsAndGetHashCode();
1381 if (CurrentType != null) {
1382 GenericType = CurrentType;
1386 // FIXME: This hack is needed because member cache does not work
1387 // with generic types, we rely on runtime to inflate dynamic types.
1388 // TODO: This hack requires member cache refactoring to be removed
1390 if (TypeManager.IsGenericType (TypeBuilder))
1391 member_cache = new MemberCache (this);
1393 return true;
1396 protected virtual void DefineContainerMembers (MemberCoreArrayList mcal)
1398 if (mcal != null)
1399 mcal.DefineContainerMembers ();
1402 protected virtual void ComputeIndexerName ()
1404 if (indexers == null)
1405 return;
1407 string class_indexer_name = null;
1410 // If there's both an explicit and an implicit interface implementation, the
1411 // explicit one actually implements the interface while the other one is just
1412 // a normal indexer. See bug #37714.
1415 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
1416 foreach (Indexer i in indexers) {
1417 if (i.InterfaceType != null) {
1418 if (seen_normal_indexers)
1419 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
1420 continue;
1423 seen_normal_indexers = true;
1425 if (class_indexer_name == null) {
1426 class_indexer_name = i.ShortName;
1427 continue;
1430 if (i.ShortName != class_indexer_name)
1431 Report.Error (668, i.Location, "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
1434 if (class_indexer_name != null)
1435 indexer_name = class_indexer_name;
1438 protected virtual void EmitIndexerName ()
1440 if (!seen_normal_indexers)
1441 return;
1443 PredefinedAttribute pa = PredefinedAttributes.Get.DefaultMember;
1444 if (pa.Constructor == null &&
1445 !pa.ResolveConstructor (Location, TypeManager.string_type))
1446 return;
1448 CustomAttributeBuilder cb = new CustomAttributeBuilder (pa.Constructor, new string [] { IndexerName });
1449 TypeBuilder.SetCustomAttribute (cb);
1452 protected virtual void CheckEqualsAndGetHashCode ()
1454 if (methods == null)
1455 return;
1457 if (HasEquals && !HasGetHashCode) {
1458 Report.Warning (659, 3, this.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", this.GetSignatureForError ());
1462 public MemberInfo FindBaseMemberWithSameName (string name, bool ignore_methods)
1464 return BaseCache == null ? null : BaseCache.FindMemberWithSameName (name, ignore_methods, null);
1467 /// <summary>
1468 /// This function is based by a delegate to the FindMembers routine
1469 /// </summary>
1470 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1472 return true;
1475 /// <summary>
1476 /// This filter is used by FindMembers, and we just keep
1477 /// a global for the filter to `AlwaysAccept'
1478 /// </summary>
1479 static MemberFilter accepting_filter;
1482 static TypeContainer ()
1484 accepting_filter = new MemberFilter (AlwaysAccept);
1487 public MethodInfo[] GetMethods ()
1489 ArrayList members = new ArrayList ();
1491 Define ();
1493 if (methods != null) {
1494 int len = methods.Count;
1495 for (int i = 0; i < len; i++) {
1496 Method m = (Method) methods [i];
1498 members.Add (m.MethodBuilder);
1502 if (operators != null) {
1503 int len = operators.Count;
1504 for (int i = 0; i < len; i++) {
1505 Operator o = (Operator) operators [i];
1507 members.Add (o.MethodBuilder);
1511 if (properties != null) {
1512 int len = properties.Count;
1513 for (int i = 0; i < len; i++) {
1514 Property p = (Property) properties [i];
1516 if (p.GetBuilder != null)
1517 members.Add (p.GetBuilder);
1518 if (p.SetBuilder != null)
1519 members.Add (p.SetBuilder);
1523 if (indexers != null) {
1524 int len = indexers.Count;
1525 for (int i = 0; i < len; i++) {
1526 Indexer ix = (Indexer) indexers [i];
1528 if (ix.GetBuilder != null)
1529 members.Add (ix.GetBuilder);
1530 if (ix.SetBuilder != null)
1531 members.Add (ix.SetBuilder);
1535 if (events != null) {
1536 int len = events.Count;
1537 for (int i = 0; i < len; i++) {
1538 Event e = (Event) events [i];
1540 if (e.AddBuilder != null)
1541 members.Add (e.AddBuilder);
1542 if (e.RemoveBuilder != null)
1543 members.Add (e.RemoveBuilder);
1547 MethodInfo[] retMethods = new MethodInfo [members.Count];
1548 members.CopyTo (retMethods, 0);
1549 return retMethods;
1552 // Indicated whether container has StructLayout attribute set Explicit
1553 public bool HasExplicitLayout {
1554 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
1555 set { caching_flags |= Flags.HasExplicitLayout; }
1558 public bool HasStructLayout {
1559 get { return (caching_flags & Flags.HasStructLayout) != 0; }
1560 set { caching_flags |= Flags.HasStructLayout; }
1564 // Return the nested type with name @name. Ensures that the nested type
1565 // is defined if necessary. Do _not_ use this when you have a MemberCache handy.
1567 public Type FindNestedType (string name)
1569 if (PartialContainer != this)
1570 throw new InternalErrorException ("should not happen");
1572 ArrayList [] lists = { types, delegates };
1574 for (int j = 0; j < lists.Length; ++j) {
1575 ArrayList list = lists [j];
1576 if (list == null)
1577 continue;
1579 int len = list.Count;
1580 for (int i = 0; i < len; ++i) {
1581 DeclSpace ds = (DeclSpace) list [i];
1582 if (ds.Basename == name) {
1583 return ds.DefineType ();
1588 return null;
1591 private void FindMembers_NestedTypes (int modflags,
1592 BindingFlags bf, MemberFilter filter, object criteria,
1593 ref ArrayList members)
1595 ArrayList [] lists = { types, delegates };
1597 for (int j = 0; j < lists.Length; ++j) {
1598 ArrayList list = lists [j];
1599 if (list == null)
1600 continue;
1602 int len = list.Count;
1603 for (int i = 0; i < len; i++) {
1604 DeclSpace ds = (DeclSpace) list [i];
1606 if ((ds.ModFlags & modflags) == 0)
1607 continue;
1609 TypeBuilder tb = ds.TypeBuilder;
1610 if (tb == null) {
1611 if (!(criteria is string) || ds.Basename.Equals (criteria))
1612 tb = ds.DefineType ();
1615 if (tb != null && (filter (tb, criteria) == true)) {
1616 if (members == null)
1617 members = new ArrayList ();
1619 members.Add (tb);
1625 /// <summary>
1626 /// This method returns the members of this type just like Type.FindMembers would
1627 /// Only, we need to use this for types which are _being_ defined because MS'
1628 /// implementation can't take care of that.
1629 /// </summary>
1631 // FIXME: return an empty static array instead of null, that cleans up
1632 // some code and is consistent with some coding conventions I just found
1633 // out existed ;-)
1636 // Notice that in various cases we check if our field is non-null,
1637 // something that would normally mean that there was a bug elsewhere.
1639 // The problem happens while we are defining p-invoke methods, as those
1640 // will trigger a FindMembers, but this happens before things are defined
1642 // Since the whole process is a no-op, it is fine to check for null here.
1644 // TODO: This approach will be one day completely removed, it's already
1645 // used at few places only
1648 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1649 MemberFilter filter, object criteria)
1651 ArrayList members = null;
1653 int modflags = 0;
1654 if ((bf & BindingFlags.Public) != 0)
1655 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1656 Modifiers.INTERNAL;
1657 if ((bf & BindingFlags.NonPublic) != 0)
1658 modflags |= Modifiers.PRIVATE;
1660 int static_mask = 0, static_flags = 0;
1661 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1662 case BindingFlags.Static:
1663 static_mask = static_flags = Modifiers.STATIC;
1664 break;
1666 case BindingFlags.Instance:
1667 static_mask = Modifiers.STATIC;
1668 static_flags = 0;
1669 break;
1671 default:
1672 static_mask = static_flags = 0;
1673 break;
1676 Timer.StartTimer (TimerType.TcFindMembers);
1678 if (filter == null)
1679 filter = accepting_filter;
1681 if ((mt & MemberTypes.Field) != 0) {
1682 if (fields != null) {
1683 int len = fields.Count;
1684 for (int i = 0; i < len; i++) {
1685 FieldBase f = (FieldBase) fields [i];
1687 if ((f.ModFlags & modflags) == 0)
1688 continue;
1689 if ((f.ModFlags & static_mask) != static_flags)
1690 continue;
1692 FieldBuilder fb = f.FieldBuilder;
1693 if (fb != null && filter (fb, criteria) == true) {
1694 if (members == null)
1695 members = new ArrayList ();
1697 members.Add (fb);
1702 if (constants != null) {
1703 int len = constants.Count;
1704 for (int i = 0; i < len; i++) {
1705 Const con = (Const) constants [i];
1707 if ((con.ModFlags & modflags) == 0)
1708 continue;
1709 if ((con.ModFlags & static_mask) != static_flags)
1710 continue;
1712 FieldBuilder fb = con.FieldBuilder;
1713 if (fb == null) {
1714 if (con.Define ())
1715 fb = con.FieldBuilder;
1717 if (fb != null && filter (fb, criteria) == true) {
1718 if (members == null)
1719 members = new ArrayList ();
1721 members.Add (fb);
1727 if ((mt & MemberTypes.Method) != 0) {
1728 if (methods != null) {
1729 int len = methods.Count;
1730 for (int i = 0; i < len; i++) {
1731 MethodOrOperator m = (MethodOrOperator) methods [i];
1733 if ((m.ModFlags & modflags) == 0)
1734 continue;
1735 if ((m.ModFlags & static_mask) != static_flags)
1736 continue;
1738 MethodBuilder mb = m.MethodBuilder;
1740 if (mb != null && filter (mb, criteria) == true) {
1741 if (members == null)
1742 members = new ArrayList ();
1744 members.Add (mb);
1749 if (operators != null) {
1750 int len = operators.Count;
1751 for (int i = 0; i < len; i++) {
1752 Operator o = (Operator) operators [i];
1754 if ((o.ModFlags & modflags) == 0)
1755 continue;
1756 if ((o.ModFlags & static_mask) != static_flags)
1757 continue;
1759 MethodBuilder ob = o.MethodBuilder;
1760 if (ob != null && filter (ob, criteria) == true) {
1761 if (members == null)
1762 members = new ArrayList ();
1764 members.Add (ob);
1769 if (events != null) {
1770 foreach (Event e in events) {
1771 if ((e.ModFlags & modflags) == 0)
1772 continue;
1773 if ((e.ModFlags & static_mask) != static_flags)
1774 continue;
1776 MethodBuilder b = e.AddBuilder;
1777 if (b != null && filter (b, criteria)) {
1778 if (members == null)
1779 members = new ArrayList (4);
1781 members.Add (b);
1784 b = e.RemoveBuilder;
1785 if (b != null && filter (b, criteria)) {
1786 if (members == null)
1787 members = new ArrayList (4);
1789 members.Add (b);
1794 if (properties != null) {
1795 int len = properties.Count;
1796 for (int i = 0; i < len; i++) {
1797 Property p = (Property) properties [i];
1799 if ((p.ModFlags & modflags) == 0)
1800 continue;
1801 if ((p.ModFlags & static_mask) != static_flags)
1802 continue;
1804 MethodBuilder b;
1806 b = p.GetBuilder;
1807 if (b != null && filter (b, criteria) == true) {
1808 if (members == null)
1809 members = new ArrayList ();
1811 members.Add (b);
1814 b = p.SetBuilder;
1815 if (b != null && filter (b, criteria) == true) {
1816 if (members == null)
1817 members = new ArrayList ();
1819 members.Add (b);
1824 if (indexers != null) {
1825 int len = indexers.Count;
1826 for (int i = 0; i < len; i++) {
1827 Indexer ix = (Indexer) indexers [i];
1829 if ((ix.ModFlags & modflags) == 0)
1830 continue;
1831 if ((ix.ModFlags & static_mask) != static_flags)
1832 continue;
1834 MethodBuilder b;
1836 b = ix.GetBuilder;
1837 if (b != null && filter (b, criteria) == true) {
1838 if (members == null)
1839 members = new ArrayList ();
1841 members.Add (b);
1844 b = ix.SetBuilder;
1845 if (b != null && filter (b, criteria) == true) {
1846 if (members == null)
1847 members = new ArrayList ();
1849 members.Add (b);
1855 if ((mt & MemberTypes.Event) != 0) {
1856 if (events != null) {
1857 int len = events.Count;
1858 for (int i = 0; i < len; i++) {
1859 Event e = (Event) events [i];
1861 if ((e.ModFlags & modflags) == 0)
1862 continue;
1863 if ((e.ModFlags & static_mask) != static_flags)
1864 continue;
1866 MemberInfo eb = e.EventBuilder;
1867 if (eb != null && filter (eb, criteria) == true) {
1868 if (members == null)
1869 members = new ArrayList ();
1871 members.Add (e.EventBuilder);
1877 if ((mt & MemberTypes.Property) != 0){
1878 if (properties != null) {
1879 int len = properties.Count;
1880 for (int i = 0; i < len; i++) {
1881 Property p = (Property) properties [i];
1883 if ((p.ModFlags & modflags) == 0)
1884 continue;
1885 if ((p.ModFlags & static_mask) != static_flags)
1886 continue;
1888 MemberInfo pb = p.PropertyBuilder;
1889 if (pb != null && filter (pb, criteria) == true) {
1890 if (members == null)
1891 members = new ArrayList ();
1893 members.Add (p.PropertyBuilder);
1898 if (indexers != null) {
1899 int len = indexers.Count;
1900 for (int i = 0; i < len; i++) {
1901 Indexer ix = (Indexer) indexers [i];
1903 if ((ix.ModFlags & modflags) == 0)
1904 continue;
1905 if ((ix.ModFlags & static_mask) != static_flags)
1906 continue;
1908 MemberInfo ib = ix.PropertyBuilder;
1909 if (ib != null && filter (ib, criteria) == true) {
1910 if (members == null)
1911 members = new ArrayList ();
1913 members.Add (ix.PropertyBuilder);
1919 if ((mt & MemberTypes.NestedType) != 0)
1920 FindMembers_NestedTypes (modflags, bf, filter, criteria, ref members);
1922 if ((mt & MemberTypes.Constructor) != 0){
1923 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1924 int len = instance_constructors.Count;
1925 for (int i = 0; i < len; i++) {
1926 Constructor c = (Constructor) instance_constructors [i];
1928 ConstructorBuilder cb = c.ConstructorBuilder;
1929 if (cb != null && filter (cb, criteria) == true) {
1930 if (members == null)
1931 members = new ArrayList ();
1933 members.Add (cb);
1938 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1939 ConstructorBuilder cb =
1940 default_static_constructor.ConstructorBuilder;
1942 if (cb != null && filter (cb, criteria) == true) {
1943 if (members == null)
1944 members = new ArrayList ();
1946 members.Add (cb);
1952 // Lookup members in base if requested.
1954 if ((bf & BindingFlags.DeclaredOnly) == 0) {
1955 if (TypeBuilder.BaseType != null) {
1956 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1957 if (list.Count > 0) {
1958 if (members == null)
1959 members = new ArrayList ();
1961 members.AddRange (list);
1966 Timer.StopTimer (TimerType.TcFindMembers);
1968 if (members == null)
1969 return MemberList.Empty;
1970 else
1971 return new MemberList (members);
1974 public override MemberCache MemberCache {
1975 get {
1976 return member_cache;
1980 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1981 MemberFilter filter, object criteria)
1983 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1985 if (ds != null)
1986 return ds.FindMembers (mt, bf, filter, criteria);
1987 else
1988 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1991 /// <summary>
1992 /// Emits the values for the constants
1993 /// </summary>
1994 public void EmitConstants ()
1996 if (constants != null)
1997 foreach (Const con in constants)
1998 con.Emit ();
1999 return;
2002 static void CheckMemberUsage (MemberCoreArrayList al, string member_type)
2004 if (al == null)
2005 return;
2007 foreach (MemberCore mc in al) {
2008 if ((mc.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
2009 continue;
2011 if (!mc.IsUsed && (mc.caching_flags & Flags.Excluded) == 0) {
2012 Report.Warning (169, 3, mc.Location, "The private {0} `{1}' is never used", member_type, mc.GetSignatureForError ());
2017 public virtual void VerifyMembers ()
2020 // Check for internal or private fields that were never assigned
2022 if (Report.WarningLevel >= 3) {
2023 CheckMemberUsage (properties, "property");
2024 CheckMemberUsage (methods, "method");
2025 CheckMemberUsage (constants, "constant");
2027 if (fields != null){
2028 bool is_type_exposed = Kind == Kind.Struct || IsExposedFromAssembly ();
2029 foreach (FieldBase f in fields) {
2030 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE) {
2031 if (is_type_exposed)
2032 continue;
2034 f.SetMemberIsUsed ();
2037 if (!f.IsUsed){
2038 if ((f.caching_flags & Flags.IsAssigned) == 0)
2039 Report.Warning (169, 3, f.Location, "The private field `{0}' is never used", f.GetSignatureForError ());
2040 else {
2041 #if NET_2_0
2042 const int error_code = 414;
2043 #else
2044 const int error_code = 169;
2045 #endif
2046 Report.Warning (error_code, 3, f.Location, "The private field `{0}' is assigned but its value is never used",
2047 f.GetSignatureForError ());
2049 continue;
2053 // Only report 649 on level 4
2055 if (Report.WarningLevel < 4)
2056 continue;
2058 if ((f.caching_flags & Flags.IsAssigned) != 0)
2059 continue;
2062 // Don't be pendatic over serializable attributes
2064 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2065 continue;
2067 Constant c = New.Constantify (f.MemberType);
2068 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value `{1}'",
2069 f.GetSignatureForError (), c == null ? "null" : c.AsString ());
2075 // TODO: move to ClassOrStruct
2076 void EmitConstructors ()
2078 if (instance_constructors == null)
2079 return;
2081 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && RootContext.VerifyClsCompliance && IsClsComplianceRequired ()) {
2082 bool has_compliant_args = false;
2084 foreach (Constructor c in instance_constructors) {
2085 try {
2086 c.Emit ();
2088 catch (Exception e) {
2089 throw new InternalErrorException (c, e);
2092 if (has_compliant_args)
2093 continue;
2095 has_compliant_args = c.HasCompliantArgs;
2097 if (!has_compliant_args)
2098 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2099 } else {
2100 foreach (Constructor c in instance_constructors) {
2101 try {
2102 c.Emit ();
2104 catch (Exception e) {
2105 throw new InternalErrorException (c, e);
2111 /// <summary>
2112 /// Emits the code, this step is performed after all
2113 /// the types, enumerations, constructors
2114 /// </summary>
2115 public virtual void EmitType ()
2117 if (OptAttributes != null)
2118 OptAttributes.Emit ();
2120 Emit ();
2122 EmitConstructors ();
2124 // Can not continue if constants are broken
2125 EmitConstants ();
2126 if (Report.Errors > 0)
2127 return;
2129 if (default_static_constructor != null)
2130 default_static_constructor.Emit ();
2132 if (operators != null)
2133 foreach (Operator o in operators)
2134 o.Emit ();
2136 if (properties != null)
2137 foreach (Property p in properties)
2138 p.Emit ();
2140 if (indexers != null) {
2141 foreach (Indexer indx in indexers)
2142 indx.Emit ();
2143 EmitIndexerName ();
2146 if (events != null){
2147 foreach (Event e in Events)
2148 e.Emit ();
2151 if (methods != null) {
2152 for (int i = 0; i < methods.Count; ++i)
2153 ((MethodOrOperator) methods [i]).Emit ();
2156 if (fields != null)
2157 foreach (FieldBase f in fields)
2158 f.Emit ();
2160 if (delegates != null) {
2161 foreach (Delegate d in Delegates) {
2162 d.Emit ();
2166 if (pending != null)
2167 pending.VerifyPendingMethods ();
2169 if (Report.Errors > 0)
2170 return;
2172 if (compiler_generated != null) {
2173 for (int i = 0; i < compiler_generated.Count; ++i)
2174 ((CompilerGeneratedClass) compiler_generated [i]).EmitType ();
2178 public override void CloseType ()
2180 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2181 return;
2183 try {
2184 caching_flags |= Flags.CloseTypeCreated;
2185 TypeBuilder.CreateType ();
2186 } catch (TypeLoadException){
2188 // This is fine, the code still created the type
2190 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
2191 // Console.WriteLine (e.Message);
2192 } catch (Exception e) {
2193 throw new InternalErrorException (this, e);
2196 if (Types != null){
2197 foreach (TypeContainer tc in Types)
2198 if (tc.Kind == Kind.Struct)
2199 tc.CloseType ();
2201 foreach (TypeContainer tc in Types)
2202 if (tc.Kind != Kind.Struct)
2203 tc.CloseType ();
2206 if (Delegates != null)
2207 foreach (Delegate d in Delegates)
2208 d.CloseType ();
2210 if (compiler_generated != null)
2211 foreach (CompilerGeneratedClass c in compiler_generated)
2212 c.CloseType ();
2214 PartialContainer = null;
2215 types = null;
2216 properties = null;
2217 delegates = null;
2218 fields = null;
2219 initialized_fields = null;
2220 initialized_static_fields = null;
2221 constants = null;
2222 ordered_explicit_member_list = null;
2223 ordered_member_list = null;
2224 methods = null;
2225 events = null;
2226 indexers = null;
2227 operators = null;
2228 compiler_generated = null;
2229 default_constructor = null;
2230 default_static_constructor = null;
2231 type_bases = null;
2232 OptAttributes = null;
2233 ifaces = null;
2234 base_cache = null;
2235 member_cache = null;
2239 // Performs the validation on a Method's modifiers (properties have
2240 // the same properties).
2242 public bool MethodModifiersValid (MemberCore mc)
2244 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2245 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2246 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2247 bool ok = true;
2248 int flags = mc.ModFlags;
2251 // At most one of static, virtual or override
2253 if ((flags & Modifiers.STATIC) != 0){
2254 if ((flags & vao) != 0){
2255 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2256 mc.GetSignatureForError ());
2257 ok = false;
2261 if (Kind == Kind.Struct){
2262 if ((flags & va) != 0){
2263 Modifiers.Error_InvalidModifier (mc.Location, "virtual or abstract");
2264 ok = false;
2268 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2269 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2270 mc.GetSignatureForError ());
2271 ok = false;
2275 // If the declaration includes the abstract modifier, then the
2276 // declaration does not include static, virtual or extern
2278 if ((flags & Modifiers.ABSTRACT) != 0){
2279 if ((flags & Modifiers.EXTERN) != 0){
2280 Report.Error (
2281 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2282 ok = false;
2285 if ((flags & Modifiers.SEALED) != 0) {
2286 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2287 ok = false;
2290 if ((flags & Modifiers.VIRTUAL) != 0){
2291 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2292 ok = false;
2295 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2296 Report.SymbolRelatedToPreviousError (this);
2297 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2298 mc.GetSignatureForError (), GetSignatureForError ());
2299 ok = false;
2303 if ((flags & Modifiers.PRIVATE) != 0){
2304 if ((flags & vao) != 0){
2305 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2306 ok = false;
2310 if ((flags & Modifiers.SEALED) != 0){
2311 if ((flags & Modifiers.OVERRIDE) == 0){
2312 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2313 ok = false;
2317 return ok;
2320 public Constructor DefaultStaticConstructor {
2321 get { return default_static_constructor; }
2324 protected override bool VerifyClsCompliance ()
2326 if (!base.VerifyClsCompliance ())
2327 return false;
2329 VerifyClsName ();
2331 Type base_type = TypeBuilder.BaseType;
2332 if (base_type != null && !AttributeTester.IsClsCompliant (base_type)) {
2333 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (base_type));
2335 return true;
2339 /// <summary>
2340 /// Checks whether container name is CLS Compliant
2341 /// </summary>
2342 void VerifyClsName ()
2344 Hashtable base_members = base_cache == null ?
2345 new Hashtable () :
2346 base_cache.GetPublicMembers ();
2347 Hashtable this_members = new Hashtable ();
2349 foreach (DictionaryEntry entry in defined_names) {
2350 MemberCore mc = (MemberCore)entry.Value;
2351 if (!mc.IsClsComplianceRequired ())
2352 continue;
2354 string name = (string) entry.Key;
2355 string basename = name.Substring (name.LastIndexOf ('.') + 1);
2357 string lcase = basename.ToLower (System.Globalization.CultureInfo.InvariantCulture);
2358 object found = base_members [lcase];
2359 if (found == null) {
2360 found = this_members [lcase];
2361 if (found == null) {
2362 this_members.Add (lcase, mc);
2363 continue;
2367 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
2368 continue;
2370 if (found is MemberInfo) {
2371 if (basename == ((MemberInfo) found).Name)
2372 continue;
2373 Report.SymbolRelatedToPreviousError ((MemberInfo) found);
2374 } else {
2375 Report.SymbolRelatedToPreviousError ((MemberCore) found);
2378 Report.Warning (3005, 1, mc.Location, "Identifier `{0}' differing only in case is not CLS-compliant", mc.GetSignatureForError ());
2383 /// <summary>
2384 /// Performs checks for an explicit interface implementation. First it
2385 /// checks whether the `interface_type' is a base inteface implementation.
2386 /// Then it checks whether `name' exists in the interface type.
2387 /// </summary>
2388 public bool VerifyImplements (InterfaceMemberBase mb)
2390 if (ifaces != null) {
2391 foreach (Type t in ifaces){
2392 if (TypeManager.IsEqual (t, mb.InterfaceType))
2393 return true;
2397 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2398 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2399 mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType));
2400 return false;
2403 public override Type LookupAnyGeneric (string typeName)
2405 if (types != null) {
2406 foreach (TypeContainer tc in types) {
2407 if (!tc.IsGeneric)
2408 continue;
2410 int pos = tc.Basename.LastIndexOf ('`');
2411 if (pos == typeName.Length && String.Compare (typeName, 0, tc.Basename, 0, pos) == 0)
2412 return tc.TypeBuilder;
2416 return base.LookupAnyGeneric (typeName);
2419 public void Mark_HasEquals ()
2421 cached_method |= CachedMethods.Equals;
2424 public void Mark_HasGetHashCode ()
2426 cached_method |= CachedMethods.GetHashCode;
2429 /// <summary>
2430 /// Method container contains Equals method
2431 /// </summary>
2432 public bool HasEquals {
2433 get {
2434 return (cached_method & CachedMethods.Equals) != 0;
2438 /// <summary>
2439 /// Method container contains GetHashCode method
2440 /// </summary>
2441 public bool HasGetHashCode {
2442 get {
2443 return (cached_method & CachedMethods.GetHashCode) != 0;
2447 public bool HasStaticFieldInitializer {
2448 get {
2449 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2451 set {
2452 if (value)
2453 cached_method |= CachedMethods.HasStaticFieldInitializer;
2454 else
2455 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2460 // IMemberContainer
2463 string IMemberContainer.Name {
2464 get {
2465 return Name;
2469 Type IMemberContainer.Type {
2470 get {
2471 return TypeBuilder;
2475 bool IMemberContainer.IsInterface {
2476 get {
2477 return Kind == Kind.Interface;
2481 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2483 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2485 if (GenericType != null)
2486 return TypeManager.FindMembers (GenericType, mt, new_bf,
2487 null, null);
2488 else
2489 return FindMembers (mt, new_bf, null, null);
2493 // Generates xml doc comments (if any), and if required,
2494 // handle warning report.
2496 internal override void GenerateDocComment (DeclSpace ds)
2498 DocUtil.GenerateTypeDocComment (this, ds);
2501 public override string DocCommentHeader {
2502 get { return "T:"; }
2505 public MemberCache BaseCache {
2506 get {
2507 if (base_cache != null)
2508 return base_cache;
2509 if (TypeBuilder.BaseType != null)
2510 base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
2511 if (TypeBuilder.IsInterface)
2512 base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
2513 return base_cache;
2518 public abstract class ClassOrStruct : TypeContainer {
2519 ListDictionary declarative_security;
2521 public ClassOrStruct (NamespaceEntry ns, DeclSpace parent,
2522 MemberName name, Attributes attrs, Kind kind)
2523 : base (ns, parent, name, attrs, kind)
2527 protected override bool AddToContainer (MemberCore symbol, string name)
2529 if (name == MemberName.Name) {
2530 if (symbol is TypeParameter) {
2531 Report.Error (694, symbol.Location,
2532 "Type parameter `{0}' has same name as containing type, or method",
2533 symbol.GetSignatureForError ());
2534 return false;
2537 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2538 if (imb == null || !imb.IsExplicitImpl) {
2539 Report.SymbolRelatedToPreviousError (this);
2540 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2541 symbol.GetSignatureForError ());
2542 return false;
2546 return base.AddToContainer (symbol, name);
2549 public override void VerifyMembers ()
2551 base.VerifyMembers ();
2553 if ((events != null) && Report.WarningLevel >= 3) {
2554 foreach (Event e in events){
2555 // Note: The event can be assigned from same class only, so we can report
2556 // this warning for all accessibility modes
2557 if ((e.caching_flags & Flags.IsUsed) == 0)
2558 Report.Warning (67, 3, e.Location, "The event `{0}' is never used", e.GetSignatureForError ());
2563 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2565 if (a.IsValidSecurityAttribute ()) {
2566 if (declarative_security == null)
2567 declarative_security = new ListDictionary ();
2569 a.ExtractSecurityPermissionSet (declarative_security);
2570 return;
2573 if (a.Type == pa.StructLayout) {
2574 PartialContainer.HasStructLayout = true;
2576 if (a.GetLayoutKindValue () == LayoutKind.Explicit)
2577 PartialContainer.HasExplicitLayout = true;
2580 base.ApplyAttributeBuilder (a, cb, pa);
2583 /// <summary>
2584 /// Defines the default constructors
2585 /// </summary>
2586 protected void DefineDefaultConstructor (bool is_static)
2588 // The default instance constructor is public
2589 // If the class is abstract, the default constructor is protected
2590 // The default static constructor is private
2592 int mods;
2593 if (is_static) {
2594 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2595 } else {
2596 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2599 Constructor c = new Constructor (this, MemberName.Name, mods,
2600 null, ParametersCompiled.EmptyReadOnlyParameters,
2601 new GeneratedBaseInitializer (Location),
2602 Location);
2604 AddConstructor (c);
2605 c.Block = new ToplevelBlock (ParametersCompiled.EmptyReadOnlyParameters, Location);
2608 public override bool Define ()
2610 CheckProtectedModifier ();
2612 base.Define ();
2614 if (default_static_constructor != null)
2615 default_static_constructor.Define ();
2617 return true;
2620 public override void Emit ()
2622 if (default_static_constructor == null && PartialContainer.HasStaticFieldInitializer) {
2623 DefineDefaultConstructor (true);
2624 default_static_constructor.Define ();
2627 base.Emit ();
2629 if (declarative_security != null) {
2630 foreach (DictionaryEntry de in declarative_security) {
2631 TypeBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
2636 public override ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
2638 return NamespaceEntry.LookupExtensionMethod (extensionType, this, name, loc);
2641 protected override TypeAttributes TypeAttr {
2642 get {
2643 if (default_static_constructor == null)
2644 return base.TypeAttr | TypeAttributes.BeforeFieldInit;
2646 return base.TypeAttr;
2652 // TODO: should be sealed
2653 public class Class : ClassOrStruct {
2654 const int AllowedModifiers =
2655 Modifiers.NEW |
2656 Modifiers.PUBLIC |
2657 Modifiers.PROTECTED |
2658 Modifiers.INTERNAL |
2659 Modifiers.PRIVATE |
2660 Modifiers.ABSTRACT |
2661 Modifiers.SEALED |
2662 Modifiers.STATIC |
2663 Modifiers.UNSAFE;
2665 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2667 public Class (NamespaceEntry ns, DeclSpace parent, MemberName name, int mod,
2668 Attributes attrs)
2669 : base (ns, parent, name, attrs, Kind.Class)
2671 int accmods = Parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2672 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, Location);
2674 if (IsStatic && RootContext.Version == LanguageVersion.ISO_1) {
2675 Report.FeatureIsNotAvailable (Location, "static classes");
2679 public override void AddBasesForPart (DeclSpace part, ArrayList bases)
2681 if (part.Name == "System.Object")
2682 Report.Error (537, part.Location,
2683 "The class System.Object cannot have a base class or implement an interface.");
2684 base.AddBasesForPart (part, bases);
2687 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2689 if (a.Type == pa.AttributeUsage) {
2690 if (!TypeManager.IsAttributeType (BaseType) &&
2691 TypeBuilder.FullName != "System.Attribute") {
2692 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2696 if (a.Type == pa.Conditional && !TypeManager.IsAttributeType (BaseType)) {
2697 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2698 return;
2701 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2702 a.Error_MissingGuidAttribute ();
2703 return;
2706 if (a.Type == pa.Extension) {
2707 a.Error_MisusedExtensionAttribute ();
2708 return;
2711 if (AttributeTester.IsAttributeExcluded (a.Type, Location))
2712 return;
2714 base.ApplyAttributeBuilder (a, cb, pa);
2717 public override AttributeTargets AttributeTargets {
2718 get {
2719 return AttributeTargets.Class;
2723 protected override void DefineContainerMembers (MemberCoreArrayList list)
2725 if (list == null)
2726 return;
2728 if (!IsStatic) {
2729 base.DefineContainerMembers (list);
2730 return;
2733 foreach (MemberCore m in list) {
2734 if (m is Operator) {
2735 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2736 continue;
2739 if (m is Destructor) {
2740 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2741 continue;
2744 if (m is Indexer) {
2745 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2746 continue;
2749 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is Enum || m is Delegate)
2750 continue;
2752 if (m is Constructor) {
2753 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2754 continue;
2757 Method method = m as Method;
2758 if (method != null && method.Parameters.HasExtensionMethodType) {
2759 Report.Error (1105, m.Location, "`{0}': Extension methods must be declared static", m.GetSignatureForError ());
2760 continue;
2763 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2766 base.DefineContainerMembers (list);
2769 public override bool Define ()
2771 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2772 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2775 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2776 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2779 return base.Define ();
2782 protected override bool DoDefineMembers ()
2784 if (InstanceConstructors == null && !IsStatic)
2785 DefineDefaultConstructor (false);
2787 return base.DoDefineMembers ();
2790 public override void Emit ()
2792 base.Emit ();
2794 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2795 PredefinedAttributes.Get.Extension.EmitAttribute (TypeBuilder);
2798 protected override TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
2800 TypeExpr[] ifaces = base.ResolveBaseTypes (out base_class);
2802 if (base_class == null) {
2803 if (RootContext.StdLib)
2804 base_class = TypeManager.system_object_expr;
2805 else if (Name != "System.Object")
2806 base_class = TypeManager.system_object_expr;
2807 } else {
2808 if (Kind == Kind.Class && base_class is TypeParameterExpr){
2809 Report.Error (
2810 689, base_class.Location,
2811 "Cannot derive from `{0}' because it is a type parameter",
2812 base_class.GetSignatureForError ());
2813 return ifaces;
2816 if (IsGeneric && TypeManager.IsAttributeType (base_class.Type)) {
2817 Report.Error (698, base_class.Location,
2818 "A generic type cannot derive from `{0}' because it is an attribute class",
2819 base_class.GetSignatureForError ());
2822 if (base_class.IsSealed){
2823 Report.SymbolRelatedToPreviousError (base_class.Type);
2824 if (base_class.Type.IsAbstract) {
2825 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2826 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
2827 } else {
2828 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2829 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
2831 return ifaces;
2834 if (!base_class.CanInheritFrom ()){
2835 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2836 GetSignatureForError (), base_class.GetSignatureForError ());
2837 return ifaces;
2840 if (!IsAccessibleAs (base_class.Type)) {
2841 Report.SymbolRelatedToPreviousError (base_class.Type);
2842 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2843 TypeManager.CSharpName (base_class.Type), GetSignatureForError ());
2847 if (PartialContainer.IsStaticClass) {
2848 if (base_class.Type != TypeManager.object_type) {
2849 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2850 GetSignatureForError (), base_class.GetSignatureForError ());
2851 return ifaces;
2854 if (ifaces != null) {
2855 foreach (TypeExpr t in ifaces)
2856 Report.SymbolRelatedToPreviousError (t.Type);
2857 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2861 return ifaces;
2864 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2865 /// Valid only for attribute classes.
2866 public bool IsExcluded ()
2868 if ((caching_flags & Flags.Excluded_Undetected) == 0)
2869 return (caching_flags & Flags.Excluded) != 0;
2871 caching_flags &= ~Flags.Excluded_Undetected;
2873 if (OptAttributes == null)
2874 return false;
2876 Attribute[] attrs = OptAttributes.SearchMulti (PredefinedAttributes.Get.Conditional);
2877 if (attrs == null)
2878 return false;
2880 foreach (Attribute a in attrs) {
2881 string condition = a.GetConditionalAttributeValue ();
2882 if (Location.CompilationUnit.IsConditionalDefined (condition))
2883 return false;
2886 caching_flags |= Flags.Excluded;
2887 return true;
2890 bool IsStatic {
2891 get {
2892 return (ModFlags & Modifiers.STATIC) != 0;
2897 // FIXME: How do we deal with the user specifying a different
2898 // layout?
2900 protected override TypeAttributes TypeAttr {
2901 get {
2902 TypeAttributes ta = base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2903 if (IsStatic)
2904 ta |= StaticClassAttribute;
2905 return ta;
2910 public sealed class Struct : ClassOrStruct {
2912 bool is_unmanaged, has_unmanaged_check_done;
2914 // <summary>
2915 // Modifiers allowed in a struct declaration
2916 // </summary>
2917 const int AllowedModifiers =
2918 Modifiers.NEW |
2919 Modifiers.PUBLIC |
2920 Modifiers.PROTECTED |
2921 Modifiers.INTERNAL |
2922 Modifiers.UNSAFE |
2923 Modifiers.PRIVATE;
2925 public Struct (NamespaceEntry ns, DeclSpace parent, MemberName name,
2926 int mod, Attributes attrs)
2927 : base (ns, parent, name, attrs, Kind.Struct)
2929 int accmods;
2931 if (parent.Parent == null)
2932 accmods = Modifiers.INTERNAL;
2933 else
2934 accmods = Modifiers.PRIVATE;
2936 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, Location);
2938 this.ModFlags |= Modifiers.SEALED;
2941 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2943 base.ApplyAttributeBuilder (a, cb, pa);
2946 // When struct constains fixed fixed and struct layout has explicitly
2947 // set CharSet, its value has to be propagated to compiler generated
2948 // fixed field types
2950 if (a.Type == pa.StructLayout && Fields != null && a.HasField ("CharSet")) {
2951 for (int i = 0; i < Fields.Count; ++i) {
2952 FixedField ff = Fields [i] as FixedField;
2953 if (ff != null)
2954 ff.SetCharSet (TypeBuilder.Attributes);
2959 public override AttributeTargets AttributeTargets {
2960 get {
2961 return AttributeTargets.Struct;
2965 public override bool IsUnmanagedType ()
2967 if (fields == null)
2968 return true;
2970 if (requires_delayed_unmanagedtype_check)
2971 return true;
2973 if (has_unmanaged_check_done)
2974 return is_unmanaged;
2976 has_unmanaged_check_done = true;
2978 foreach (FieldBase f in fields) {
2979 if ((f.ModFlags & Modifiers.STATIC) != 0)
2980 continue;
2982 // It can happen when recursive unmanaged types are defined
2983 // struct S { S* s; }
2984 Type mt = f.MemberType;
2985 if (mt == null) {
2986 has_unmanaged_check_done = false;
2987 requires_delayed_unmanagedtype_check = true;
2988 return true;
2991 // TODO: Remove when pointer types are under mcs control
2992 while (mt.IsPointer)
2993 mt = TypeManager.GetElementType (mt);
2994 if (TypeManager.IsEqual (mt, TypeBuilder))
2995 continue;
2997 if (TypeManager.IsUnmanagedType (mt))
2998 continue;
3000 return false;
3003 is_unmanaged = true;
3004 return true;
3007 protected override TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
3009 TypeExpr[] ifaces = base.ResolveBaseTypes (out base_class);
3011 // If we are compiling our runtime,
3012 // and we are defining ValueType, then our
3013 // base is `System.Object'.
3015 if (base_class == null) {
3016 if (!RootContext.StdLib && Name == "System.ValueType")
3017 base_class = TypeManager.system_object_expr;
3018 else
3019 base_class = TypeManager.system_valuetype_expr;
3022 return ifaces;
3026 // FIXME: Allow the user to specify a different set of attributes
3027 // in some cases (Sealed for example is mandatory for a class,
3028 // but what SequentialLayout can be changed
3030 protected override TypeAttributes TypeAttr {
3031 get {
3032 const TypeAttributes DefaultTypeAttributes =
3033 TypeAttributes.SequentialLayout |
3034 TypeAttributes.Sealed;
3036 return base.TypeAttr | DefaultTypeAttributes;
3040 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
3042 if ((field.ModFlags & Modifiers.STATIC) == 0) {
3043 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
3044 field.GetSignatureForError ());
3045 return;
3047 base.RegisterFieldForInitialization (field, expression);
3052 /// <summary>
3053 /// Interfaces
3054 /// </summary>
3055 public sealed class Interface : TypeContainer, IMemberContainer {
3057 /// <summary>
3058 /// Modifiers allowed in a class declaration
3059 /// </summary>
3060 public const int AllowedModifiers =
3061 Modifiers.NEW |
3062 Modifiers.PUBLIC |
3063 Modifiers.PROTECTED |
3064 Modifiers.INTERNAL |
3065 Modifiers.UNSAFE |
3066 Modifiers.PRIVATE;
3068 public Interface (NamespaceEntry ns, DeclSpace parent, MemberName name, int mod,
3069 Attributes attrs)
3070 : base (ns, parent, name, attrs, Kind.Interface)
3072 int accmods;
3074 if (parent.Parent == null)
3075 accmods = Modifiers.INTERNAL;
3076 else
3077 accmods = Modifiers.PRIVATE;
3079 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, name.Location);
3082 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
3084 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3085 a.Error_MissingGuidAttribute ();
3086 return;
3089 base.ApplyAttributeBuilder (a, cb, pa);
3093 public override AttributeTargets AttributeTargets {
3094 get {
3095 return AttributeTargets.Interface;
3099 protected override TypeAttributes TypeAttr {
3100 get {
3101 const TypeAttributes DefaultTypeAttributes =
3102 TypeAttributes.AutoLayout |
3103 TypeAttributes.Abstract |
3104 TypeAttributes.Interface;
3106 return base.TypeAttr | DefaultTypeAttributes;
3110 protected override bool VerifyClsCompliance ()
3112 if (!base.VerifyClsCompliance ())
3113 return false;
3115 if (ifaces != null) {
3116 foreach (Type t in ifaces) {
3117 if (AttributeTester.IsClsCompliant (t))
3118 continue;
3120 Report.SymbolRelatedToPreviousError (t);
3121 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3122 GetSignatureForError (), TypeManager.CSharpName (t));
3126 return true;
3130 // It is used as a base class for all property based members
3131 // This includes properties, indexers, and events
3132 public abstract class PropertyBasedMember : InterfaceMemberBase
3134 public PropertyBasedMember (DeclSpace parent, GenericMethod generic,
3135 FullNamedExpression type, int mod, int allowed_mod,
3136 MemberName name, Attributes attrs)
3137 : base (parent, generic, type, mod, allowed_mod, name, attrs)
3141 protected override bool VerifyClsCompliance ()
3143 if (!base.VerifyClsCompliance ())
3144 return false;
3146 if (!AttributeTester.IsClsCompliant (MemberType)) {
3147 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
3148 GetSignatureForError ());
3150 return true;
3156 public abstract class MethodCore : InterfaceMemberBase
3158 public readonly ParametersCompiled Parameters;
3159 protected ToplevelBlock block;
3161 public MethodCore (DeclSpace parent, GenericMethod generic,
3162 FullNamedExpression type, int mod, int allowed_mod,
3163 MemberName name, Attributes attrs, ParametersCompiled parameters)
3164 : base (parent, generic, type, mod, allowed_mod, name, attrs)
3166 Parameters = parameters;
3170 // Returns the System.Type array for the parameters of this method
3172 public Type [] ParameterTypes {
3173 get {
3174 return Parameters.Types;
3178 public ParametersCompiled ParameterInfo {
3179 get {
3180 return Parameters;
3184 public ToplevelBlock Block {
3185 get {
3186 return block;
3189 set {
3190 block = value;
3194 public CallingConventions CallingConventions {
3195 get {
3196 CallingConventions cc = Parameters.CallingConvention;
3197 if (!IsInterface)
3198 if ((ModFlags & Modifiers.STATIC) == 0)
3199 cc |= CallingConventions.HasThis;
3201 // FIXME: How is `ExplicitThis' used in C#?
3203 return cc;
3207 protected override bool CheckBase ()
3209 // Check whether arguments were correct.
3210 if (!DefineParameters (Parameters))
3211 return false;
3213 return base.CheckBase ();
3217 // Returns a string that represents the signature for this
3218 // member which should be used in XML documentation.
3220 public override string GetDocCommentName (DeclSpace ds)
3222 return DocUtil.GetMethodDocCommentName (this, Parameters, ds);
3226 // Raised (and passed an XmlElement that contains the comment)
3227 // when GenerateDocComment is writing documentation expectedly.
3229 // FIXME: with a few effort, it could be done with XmlReader,
3230 // that means removal of DOM use.
3232 internal override void OnGenerateDocComment (XmlElement el)
3234 DocUtil.OnMethodGenerateDocComment (this, el);
3238 // Represents header string for documentation comment.
3240 public override string DocCommentHeader
3242 get { return "M:"; }
3245 public override bool EnableOverloadChecks (MemberCore overload)
3247 if (overload is MethodCore || overload is AbstractPropertyEventMethod) {
3248 caching_flags |= Flags.MethodOverloadsExist;
3249 return true;
3252 return base.EnableOverloadChecks (overload);
3255 protected override bool VerifyClsCompliance ()
3257 if (!base.VerifyClsCompliance ())
3258 return false;
3260 if (Parameters.HasArglist) {
3261 Report.Warning (3000, 1, Location, "Methods with variable arguments are not CLS-compliant");
3264 if (!AttributeTester.IsClsCompliant (MemberType)) {
3265 Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant",
3266 GetSignatureForError ());
3269 Parameters.VerifyClsCompliance ();
3270 return true;
3275 public abstract class InterfaceMemberBase : MemberBase {
3277 // Whether this is an interface member.
3279 public bool IsInterface;
3282 // If true, this is an explicit interface implementation
3284 public bool IsExplicitImpl;
3286 protected bool is_external_implementation;
3289 // The interface type we are explicitly implementing
3291 public Type InterfaceType;
3294 // The method we're overriding if this is an override method.
3296 protected MethodInfo base_method;
3298 readonly int explicit_mod_flags;
3299 public MethodAttributes flags;
3301 public InterfaceMemberBase (DeclSpace parent, GenericMethod generic,
3302 FullNamedExpression type, int mod, int allowed_mod,
3303 MemberName name, Attributes attrs)
3304 : base (parent, generic, type, mod, allowed_mod, Modifiers.PRIVATE,
3305 name, attrs)
3307 IsInterface = parent.PartialContainer.Kind == Kind.Interface;
3308 IsExplicitImpl = (MemberName.Left != null);
3309 explicit_mod_flags = mod;
3312 protected override bool CheckBase ()
3314 if (!base.CheckBase ())
3315 return false;
3317 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3318 CheckForDuplications ();
3320 if (IsExplicitImpl)
3321 return true;
3323 // Is null for System.Object while compiling corlib and base interfaces
3324 if (Parent.PartialContainer.BaseCache == null) {
3325 if ((ModFlags & Modifiers.NEW) != 0) {
3326 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3328 return true;
3331 Type base_ret_type = null;
3332 base_method = FindOutBaseMethod (ref base_ret_type);
3334 // method is override
3335 if (base_method != null) {
3336 if (!CheckMethodAgainstBase (base_ret_type))
3337 return false;
3339 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3340 ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (base_method);
3341 if (oa != null) {
3342 if (OptAttributes == null || !OptAttributes.Contains (PredefinedAttributes.Get.Obsolete)) {
3343 Report.SymbolRelatedToPreviousError (base_method);
3344 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3345 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3347 } else {
3348 if (OptAttributes != null && OptAttributes.Contains (PredefinedAttributes.Get.Obsolete)) {
3349 Report.SymbolRelatedToPreviousError (base_method);
3350 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3351 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3355 return true;
3358 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Name, !((this is Event) || (this is Property)));
3359 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3360 if (conflict_symbol != null) {
3361 Report.SymbolRelatedToPreviousError (conflict_symbol);
3362 if (this is Event)
3363 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3364 else if (this is PropertyBase)
3365 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3366 else
3367 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3368 } else {
3369 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3370 GetSignatureForError (), SimpleName.GetMemberType (this));
3372 return false;
3375 if (conflict_symbol == null) {
3376 if ((ModFlags & Modifiers.NEW) != 0) {
3377 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3379 return true;
3382 if ((ModFlags & Modifiers.NEW) == 0) {
3383 if (this is MethodOrOperator && conflict_symbol.MemberType == MemberTypes.Method)
3384 return true;
3386 Report.SymbolRelatedToPreviousError (conflict_symbol);
3387 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3388 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3391 return true;
3394 protected virtual bool CheckForDuplications ()
3396 return Parent.MemberCache.CheckExistingMembersOverloads (
3397 this, GetFullName (MemberName), ParametersCompiled.EmptyReadOnlyParameters);
3401 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3402 // that have been defined.
3404 // `name' is the user visible name for reporting errors (this is used to
3405 // provide the right name regarding method names and properties)
3407 bool CheckMethodAgainstBase (Type base_method_type)
3409 bool ok = true;
3411 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3412 if (!(base_method.IsAbstract || base_method.IsVirtual)){
3413 Report.SymbolRelatedToPreviousError (base_method);
3414 Report.Error (506, Location,
3415 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3416 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3417 ok = false;
3420 // Now we check that the overriden method is not final
3422 if (base_method.IsFinal) {
3423 Report.SymbolRelatedToPreviousError (base_method);
3424 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3425 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3426 ok = false;
3429 // Check that the permissions are not being changed
3431 MethodAttributes thisp = flags & MethodAttributes.MemberAccessMask;
3432 MethodAttributes base_classp = base_method.Attributes & MethodAttributes.MemberAccessMask;
3434 if (!CheckAccessModifiers (thisp, base_classp, base_method)) {
3435 Error_CannotChangeAccessModifiers (Location, base_method, base_classp, null);
3436 ok = false;
3439 if (!TypeManager.IsEqual (MemberType, TypeManager.TypeToCoreType (base_method_type))) {
3440 Report.SymbolRelatedToPreviousError (base_method);
3441 if (this is PropertyBasedMember) {
3442 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3443 GetSignatureForError (), TypeManager.CSharpName (base_method_type), TypeManager.CSharpSignature (base_method));
3445 else {
3446 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3447 GetSignatureForError (), TypeManager.CSharpName (base_method_type), TypeManager.CSharpSignature (base_method));
3449 ok = false;
3453 if ((ModFlags & Modifiers.NEW) == 0) {
3454 if ((ModFlags & Modifiers.OVERRIDE) == 0) {
3455 ModFlags |= Modifiers.NEW;
3456 Report.SymbolRelatedToPreviousError (base_method);
3457 if (!IsInterface && (base_method.IsVirtual || base_method.IsAbstract)) {
3458 Report.Warning (114, 2, Location, "`{0}' hides inherited member `{1}'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword",
3459 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3460 } else {
3461 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3462 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3465 } else {
3466 if (base_method.IsAbstract && !IsInterface) {
3467 Report.SymbolRelatedToPreviousError (base_method);
3468 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3469 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3470 return ok = false;
3474 return ok;
3477 protected bool CheckAccessModifiers (MethodAttributes thisp, MethodAttributes base_classp, MethodInfo base_method)
3479 if ((base_classp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3481 // when overriding protected internal, the method can be declared
3482 // protected internal only within the same assembly or assembly
3483 // which has InternalsVisibleTo
3485 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3486 return TypeManager.IsThisOrFriendAssembly (base_method.DeclaringType.Assembly);
3487 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3489 // if it's not "protected internal", it must be "protected"
3492 return false;
3493 } else if (Parent.TypeBuilder.Assembly == base_method.DeclaringType.Assembly) {
3495 // protected within the same assembly - an error
3497 return false;
3498 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3499 (base_classp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3501 // protected ok, but other attributes differ - report an error
3503 return false;
3505 return true;
3506 } else {
3507 return (thisp == base_classp);
3511 public override bool Define ()
3513 if (IsInterface) {
3514 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3515 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3517 flags = MethodAttributes.Public |
3518 MethodAttributes.Abstract |
3519 MethodAttributes.HideBySig |
3520 MethodAttributes.NewSlot |
3521 MethodAttributes.Virtual;
3522 } else {
3523 Parent.PartialContainer.MethodModifiersValid (this);
3525 flags = Modifiers.MethodAttr (ModFlags);
3528 if (IsExplicitImpl) {
3529 TypeExpr iface_texpr = MemberName.Left.GetTypeExpression ().ResolveAsTypeTerminal (this, false);
3530 if (iface_texpr == null)
3531 return false;
3533 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3534 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3535 GetSignatureForError ());
3538 InterfaceType = iface_texpr.Type;
3540 if (!InterfaceType.IsInterface) {
3541 Report.SymbolRelatedToPreviousError (InterfaceType);
3542 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3543 TypeManager.CSharpName (InterfaceType));
3544 } else {
3545 Parent.PartialContainer.VerifyImplements (this);
3548 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
3551 return base.Define ();
3554 protected bool DefineParameters (ParametersCompiled parameters)
3556 IResolveContext rc = GenericMethod == null ? this : (IResolveContext)ds;
3558 if (!parameters.Resolve (rc))
3559 return false;
3561 bool error = false;
3562 for (int i = 0; i < parameters.Count; ++i) {
3563 Parameter p = parameters [i];
3565 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3566 p.Warning_UselessOptionalParameter ();
3568 if (p.CheckAccessibility (this))
3569 continue;
3571 Type t = parameters.Types [i];
3572 Report.SymbolRelatedToPreviousError (t);
3573 if (this is Indexer)
3574 Report.Error (55, Location,
3575 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3576 TypeManager.CSharpName (t), GetSignatureForError ());
3577 else if (this is Operator)
3578 Report.Error (57, Location,
3579 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3580 TypeManager.CSharpName (t), GetSignatureForError ());
3581 else
3582 Report.Error (51, Location,
3583 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3584 TypeManager.CSharpName (t), GetSignatureForError ());
3585 error = true;
3587 return !error;
3590 public override void Emit()
3592 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3593 // We are more strict than csc and report this as an error because SRE does not allow emit that
3594 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation) {
3595 if (this is Constructor) {
3596 Report.Error (824, Location,
3597 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3598 } else {
3599 Report.Error (626, Location,
3600 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3601 GetSignatureForError ());
3605 base.Emit ();
3608 public override bool EnableOverloadChecks (MemberCore overload)
3611 // Two members can differ in their explicit interface
3612 // type parameter only
3614 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3615 if (imb != null && imb.IsExplicitImpl) {
3616 if (IsExplicitImpl) {
3617 caching_flags |= Flags.MethodOverloadsExist;
3619 return true;
3622 return IsExplicitImpl;
3625 protected void Error_CannotChangeAccessModifiers (Location loc, MemberInfo base_method, MethodAttributes ma, string suffix)
3627 Report.SymbolRelatedToPreviousError (base_method);
3628 string base_name = TypeManager.GetFullNameSignature (base_method);
3629 string this_name = GetSignatureForError ();
3630 if (suffix != null) {
3631 base_name += suffix;
3632 this_name += suffix;
3635 Report.Error (507, loc, "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3636 this_name, Modifiers.GetDescription (ma), base_name);
3639 protected static string Error722 {
3640 get {
3641 return "`{0}': static types cannot be used as return types";
3645 /// <summary>
3646 /// Gets base method and its return type
3647 /// </summary>
3648 protected abstract MethodInfo FindOutBaseMethod (ref Type base_ret_type);
3651 // The "short" name of this property / indexer / event. This is the
3652 // name without the explicit interface.
3654 public string ShortName
3656 get { return MemberName.Name; }
3657 set { SetMemberName (new MemberName (MemberName.Left, value, Location)); }
3661 // Returns full metadata method name
3663 public string GetFullName (MemberName name)
3665 if (!IsExplicitImpl)
3666 return name.Name;
3669 // When dealing with explicit members a full interface type
3670 // name is added to member name to avoid possible name conflicts
3672 // We use CSharpName which gets us full name with benefit of
3673 // replacing predefined names which saves some space and name
3674 // is still unique
3676 return TypeManager.CSharpName (InterfaceType) + "." + name.Name;
3679 protected override bool VerifyClsCompliance ()
3681 if (!base.VerifyClsCompliance ()) {
3682 if (IsInterface && HasClsCompliantAttribute && Parent.IsClsComplianceRequired ()) {
3683 Report.Warning (3010, 1, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
3686 if ((ModFlags & Modifiers.ABSTRACT) != 0 && Parent.TypeBuilder.IsClass && IsExposedFromAssembly () && Parent.IsClsComplianceRequired ()) {
3687 Report.Warning (3011, 1, Location, "`{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
3689 return false;
3692 if (GenericMethod != null)
3693 GenericMethod.VerifyClsCompliance ();
3695 return true;
3698 public override bool IsUsed
3700 get { return IsExplicitImpl || base.IsUsed; }
3705 public abstract class MethodOrOperator : MethodCore, IMethodData
3707 public MethodBuilder MethodBuilder;
3708 ReturnParameter return_attributes;
3709 ListDictionary declarative_security;
3710 protected MethodData MethodData;
3712 static string[] attribute_targets = new string [] { "method", "return" };
3714 protected MethodOrOperator (DeclSpace parent, GenericMethod generic, FullNamedExpression type, int mod,
3715 int allowed_mod, MemberName name,
3716 Attributes attrs, ParametersCompiled parameters)
3717 : base (parent, generic, type, mod, allowed_mod, name,
3718 attrs, parameters)
3722 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
3724 if (a.Target == AttributeTargets.ReturnValue) {
3725 if (return_attributes == null)
3726 return_attributes = new ReturnParameter (MethodBuilder, Location);
3728 return_attributes.ApplyAttributeBuilder (a, cb, pa);
3729 return;
3732 if (a.IsInternalMethodImplAttribute) {
3733 is_external_implementation = true;
3736 if (a.Type == pa.DllImport) {
3737 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3738 if ((ModFlags & extern_static) != extern_static) {
3739 Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
3741 is_external_implementation = true;
3744 if (a.IsValidSecurityAttribute ()) {
3745 if (declarative_security == null)
3746 declarative_security = new ListDictionary ();
3747 a.ExtractSecurityPermissionSet (declarative_security);
3748 return;
3751 if (MethodBuilder != null)
3752 MethodBuilder.SetCustomAttribute (cb);
3755 public override AttributeTargets AttributeTargets {
3756 get {
3757 return AttributeTargets.Method;
3761 protected override bool CheckForDuplications ()
3763 string name = GetFullName (MemberName);
3764 if (MemberName.IsGeneric)
3765 name = MemberName.MakeName (name, MemberName.TypeArguments);
3767 return Parent.MemberCache.CheckExistingMembersOverloads (this, name, Parameters);
3770 public virtual EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
3772 return new EmitContext (
3773 this, tc, this.ds, Location, ig, MemberType, ModFlags, false);
3776 protected override bool ResolveMemberType ()
3778 #if GMCS_SOURCE
3779 if (GenericMethod != null) {
3780 MethodBuilder = Parent.TypeBuilder.DefineMethod (GetFullName (MemberName), flags);
3781 if (!GenericMethod.Define (this))
3782 return false;
3784 #endif
3786 return base.ResolveMemberType ();
3789 public override bool Define ()
3791 if (!base.Define ())
3792 return false;
3794 if (!CheckBase ())
3795 return false;
3797 if (block != null && block.IsIterator && !(Parent is IteratorStorey)) {
3799 // Current method is turned into automatically generated
3800 // wrapper which creates an instance of iterator
3802 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
3803 ModFlags |= Modifiers.DEBUGGER_HIDDEN;
3806 if (IsPartialDefinition) {
3807 caching_flags &= ~Flags.Excluded_Undetected;
3808 caching_flags |= Flags.Excluded;
3809 // Add to member cache only when a partial method implementation is not there
3810 if ((caching_flags & Flags.MethodOverloadsExist) == 0) {
3811 MethodBase mb = new PartialMethodDefinitionInfo (this);
3812 Parent.MemberCache.AddMember (mb, this);
3813 TypeManager.AddMethod (mb, this);
3816 return true;
3819 MethodData = new MethodData (
3820 this, ModFlags, flags, this, MethodBuilder, GenericMethod, base_method);
3822 if (!MethodData.Define (Parent.PartialContainer, GetFullName (MemberName)))
3823 return false;
3825 MethodBuilder = MethodData.MethodBuilder;
3827 if (TypeManager.IsGenericMethod (MethodBuilder))
3828 Parent.MemberCache.AddGenericMember (MethodBuilder, this);
3830 Parent.MemberCache.AddMember (MethodBuilder, this);
3832 return true;
3835 protected override void DoMemberTypeIndependentChecks ()
3837 base.DoMemberTypeIndependentChecks ();
3839 CheckAbstractAndExtern (block != null);
3841 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3842 for (int i = 0; i < Parameters.Count; ++i) {
3843 IParameterData p = Parameters.FixedParameters [i];
3844 if (p.ModFlags == Parameter.Modifier.OUT) {
3845 Report.Error (752, Location, "`{0}': A partial method parameters cannot use `out' modifier",
3846 GetSignatureForError ());
3849 if (p.HasDefaultValue && IsPartialImplementation)
3850 ((Parameter) p).Warning_UselessOptionalParameter ();
3855 protected override void DoMemberTypeDependentChecks ()
3857 base.DoMemberTypeDependentChecks ();
3859 if (!TypeManager.IsGenericParameter (MemberType)) {
3860 if (MemberType.IsAbstract && MemberType.IsSealed) {
3861 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
3866 public override void Emit ()
3868 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
3869 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (MethodBuilder);
3870 if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
3871 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (MethodBuilder);
3873 if (OptAttributes != null)
3874 OptAttributes.Emit ();
3876 if (declarative_security != null) {
3877 foreach (DictionaryEntry de in declarative_security) {
3878 MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
3882 if (MethodData != null)
3883 MethodData.Emit (Parent);
3885 base.Emit ();
3887 Block = null;
3888 MethodData = null;
3891 protected void Error_ConditionalAttributeIsNotValid ()
3893 Report.Error (577, Location,
3894 "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
3895 GetSignatureForError ());
3898 public bool IsPartialDefinition {
3899 get {
3900 return (ModFlags & Modifiers.PARTIAL) != 0 && Block == null;
3904 public bool IsPartialImplementation {
3905 get {
3906 return (ModFlags & Modifiers.PARTIAL) != 0 && Block != null;
3910 public override string[] ValidAttributeTargets {
3911 get {
3912 return attribute_targets;
3916 #region IMethodData Members
3918 public Type ReturnType {
3919 get {
3920 return MemberType;
3924 public MemberName MethodName {
3925 get {
3926 return MemberName;
3930 /// <summary>
3931 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
3932 /// </summary>
3933 public bool IsExcluded () {
3934 if ((caching_flags & Flags.Excluded_Undetected) == 0)
3935 return (caching_flags & Flags.Excluded) != 0;
3937 caching_flags &= ~Flags.Excluded_Undetected;
3939 if (base_method == null) {
3940 if (OptAttributes == null)
3941 return false;
3943 Attribute[] attrs = OptAttributes.SearchMulti (PredefinedAttributes.Get.Conditional);
3945 if (attrs == null)
3946 return false;
3948 foreach (Attribute a in attrs) {
3949 string condition = a.GetConditionalAttributeValue ();
3950 if (condition == null)
3951 return false;
3953 if (Location.CompilationUnit.IsConditionalDefined (condition))
3954 return false;
3957 caching_flags |= Flags.Excluded;
3958 return true;
3961 IMethodData md = TypeManager.GetMethod (TypeManager.DropGenericMethodArguments (base_method));
3962 if (md == null) {
3963 if (AttributeTester.IsConditionalMethodExcluded (base_method, Location)) {
3964 caching_flags |= Flags.Excluded;
3965 return true;
3967 return false;
3970 if (md.IsExcluded ()) {
3971 caching_flags |= Flags.Excluded;
3972 return true;
3974 return false;
3977 GenericMethod IMethodData.GenericMethod {
3978 get {
3979 return GenericMethod;
3983 public virtual void EmitExtraSymbolInfo (SourceMethod source)
3986 #endregion
3990 public class SourceMethod : IMethodDef
3992 MethodBase method;
3993 SourceMethodBuilder builder;
3995 protected SourceMethod (DeclSpace parent, MethodBase method, ICompileUnit file)
3997 this.method = method;
3999 builder = SymbolWriter.OpenMethod (file, parent.NamespaceEntry.SymbolFileID, this);
4002 public string Name {
4003 get { return method.Name; }
4006 public int Token {
4007 get {
4008 if (method is MethodBuilder)
4009 return ((MethodBuilder) method).GetToken ().Token;
4010 else if (method is ConstructorBuilder)
4011 return ((ConstructorBuilder) method).GetToken ().Token;
4012 else
4013 throw new NotSupportedException ();
4017 public void CloseMethod ()
4019 SymbolWriter.CloseMethod ();
4022 public void SetRealMethodName (string name)
4024 if (builder != null)
4025 builder.SetRealMethodName (name);
4028 public static SourceMethod Create (DeclSpace parent, MethodBase method, Block block)
4030 if (!SymbolWriter.HasSymbolWriter)
4031 return null;
4032 if (block == null)
4033 return null;
4035 Location start_loc = block.StartLocation;
4036 if (start_loc.IsNull)
4037 return null;
4039 ICompileUnit compile_unit = start_loc.CompilationUnit;
4040 if (compile_unit == null)
4041 return null;
4043 return new SourceMethod (parent, method, compile_unit);
4047 public class Method : MethodOrOperator {
4049 /// <summary>
4050 /// Modifiers allowed in a class declaration
4051 /// </summary>
4052 const int AllowedModifiers =
4053 Modifiers.NEW |
4054 Modifiers.PUBLIC |
4055 Modifiers.PROTECTED |
4056 Modifiers.INTERNAL |
4057 Modifiers.PRIVATE |
4058 Modifiers.STATIC |
4059 Modifiers.VIRTUAL |
4060 Modifiers.SEALED |
4061 Modifiers.OVERRIDE |
4062 Modifiers.ABSTRACT |
4063 Modifiers.UNSAFE |
4064 Modifiers.EXTERN;
4066 const int AllowedInterfaceModifiers =
4067 Modifiers.NEW | Modifiers.UNSAFE;
4069 public Method (DeclSpace parent, GenericMethod generic,
4070 FullNamedExpression return_type, int mod,
4071 MemberName name, ParametersCompiled parameters, Attributes attrs)
4072 : base (parent, generic, return_type, mod,
4073 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
4074 name, attrs, parameters)
4078 protected Method (DeclSpace parent, FullNamedExpression return_type, int mod, int amod,
4079 MemberName name, ParametersCompiled parameters, Attributes attrs)
4080 : base (parent, null, return_type, mod, amod, name, attrs, parameters)
4084 public override string GetSignatureForError()
4086 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
4089 static void Error_DuplicateEntryPoint (Method b)
4091 Report.Error (17, b.Location,
4092 "Program `{0}' has more than one entry point defined: `{1}'",
4093 CodeGen.FileName, b.GetSignatureForError ());
4096 bool IsEntryPoint ()
4098 if (ReturnType != TypeManager.void_type &&
4099 ReturnType != TypeManager.int32_type)
4100 return false;
4102 if (Parameters.Count == 0)
4103 return true;
4105 if (Parameters.Count > 1)
4106 return false;
4108 Type t = Parameters.Types [0];
4109 return t.IsArray && t.GetArrayRank () == 1 &&
4110 TypeManager.GetElementType (t) == TypeManager.string_type &&
4111 (Parameters[0].ModFlags & ~Parameter.Modifier.PARAMS) == Parameter.Modifier.NONE;
4114 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
4116 if (a.Type == pa.Conditional) {
4117 if (IsExplicitImpl) {
4118 Error_ConditionalAttributeIsNotValid ();
4119 return;
4122 if (ReturnType != TypeManager.void_type) {
4123 Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ());
4124 return;
4127 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
4128 Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ());
4129 return;
4132 if (IsInterface) {
4133 Report.Error (582, Location, "Conditional not valid on interface members");
4134 return;
4137 if (MethodData.implementing != null) {
4138 Report.SymbolRelatedToPreviousError (MethodData.implementing.DeclaringType);
4139 Report.Error (629, Location, "Conditional member `{0}' cannot implement interface member `{1}'",
4140 GetSignatureForError (), TypeManager.CSharpSignature (MethodData.implementing));
4141 return;
4144 for (int i = 0; i < Parameters.Count; ++i) {
4145 if (Parameters.FixedParameters [i].ModFlags == Parameter.Modifier.OUT) {
4146 Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
4147 return;
4152 if (a.Type == pa.Extension) {
4153 a.Error_MisusedExtensionAttribute ();
4154 return;
4157 base.ApplyAttributeBuilder (a, cb, pa);
4160 protected override bool CheckForDuplications ()
4162 if (!base.CheckForDuplications ())
4163 return false;
4165 ArrayList ar = Parent.PartialContainer.Properties;
4166 if (ar != null) {
4167 for (int i = 0; i < ar.Count; ++i) {
4168 PropertyBase pb = (PropertyBase) ar [i];
4169 if (pb.AreAccessorsDuplicateImplementation (this))
4170 return false;
4174 ar = Parent.PartialContainer.Indexers;
4175 if (ar != null) {
4176 for (int i = 0; i < ar.Count; ++i) {
4177 PropertyBase pb = (PropertyBase) ar [i];
4178 if (pb.AreAccessorsDuplicateImplementation (this))
4179 return false;
4183 return true;
4186 protected override bool CheckBase ()
4188 if (!base.CheckBase ())
4189 return false;
4191 if (base_method != null && (ModFlags & Modifiers.OVERRIDE) != 0 && Name == Destructor.MetadataName) {
4192 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
4193 TypeManager.CSharpSignature (base_method));
4196 return true;
4200 // Creates the type
4202 public override bool Define ()
4204 if (type_name == TypeManager.system_void_expr && Parameters.IsEmpty && Name == Destructor.MetadataName) {
4205 Report.Warning (465, 1, Location, "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
4208 if (!base.Define ())
4209 return false;
4211 if (RootContext.StdLib && TypeManager.IsSpecialType (ReturnType)) {
4212 Error1599 (Location, ReturnType);
4213 return false;
4216 if (base_method != null && (ModFlags & Modifiers.NEW) == 0) {
4217 if (Parameters.Count == 1 && ParameterTypes [0] == TypeManager.object_type && Name == "Equals")
4218 Parent.PartialContainer.Mark_HasEquals ();
4219 else if (Parameters.IsEmpty && Name == "GetHashCode")
4220 Parent.PartialContainer.Mark_HasGetHashCode ();
4223 if ((ModFlags & Modifiers.STATIC) == 0)
4224 return true;
4226 if (Parameters.HasExtensionMethodType) {
4227 if (Parent.PartialContainer.IsStaticClass && !Parent.IsGeneric) {
4228 if (!Parent.IsTopLevel)
4229 Report.Error (1109, Location, "`{0}': Extension methods cannot be defined in a nested class",
4230 GetSignatureForError ());
4232 PredefinedAttribute pa = PredefinedAttributes.Get.Extension;
4233 if (!pa.IsDefined) {
4234 Report.Error (1110, Location,
4235 "`{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",
4236 GetSignatureForError ());
4239 ModFlags |= Modifiers.METHOD_EXTENSION;
4240 Parent.PartialContainer.ModFlags |= Modifiers.METHOD_EXTENSION;
4241 CodeGen.Assembly.HasExtensionMethods = true;
4242 } else {
4243 Report.Error (1106, Location, "`{0}': Extension methods must be defined in a non-generic static class",
4244 GetSignatureForError ());
4249 // This is used to track the Entry Point,
4251 if (RootContext.NeedsEntryPoint &&
4252 Name == "Main" &&
4253 (RootContext.MainClass == null ||
4254 RootContext.MainClass == Parent.TypeBuilder.FullName)){
4255 if (IsEntryPoint ()) {
4257 if (RootContext.EntryPoint == null) {
4258 if (Parent.IsGeneric || MemberName.IsGeneric) {
4259 Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type",
4260 GetSignatureForError ());
4261 } else {
4262 SetMemberIsUsed ();
4263 RootContext.EntryPoint = this;
4265 } else {
4266 Error_DuplicateEntryPoint (RootContext.EntryPoint);
4267 Error_DuplicateEntryPoint (this);
4269 } else {
4270 Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point",
4271 GetSignatureForError ());
4275 return true;
4279 // Emits the code
4281 public override void Emit ()
4283 try {
4284 Report.Debug (64, "METHOD EMIT", this, MethodBuilder, Location, Block, MethodData);
4285 if (IsPartialDefinition) {
4287 // Do attribute checks only when partial implementation does not exist
4289 if (MethodBuilder == null)
4290 base.Emit ();
4292 return;
4295 if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.PartialDefinitionExists) == 0)
4296 Report.Error (759, Location, "A partial method `{0}' implementation is missing a partial method declaration",
4297 GetSignatureForError ());
4299 base.Emit ();
4301 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
4302 PredefinedAttributes.Get.Extension.EmitAttribute (MethodBuilder);
4303 } catch {
4304 Console.WriteLine ("Internal compiler error at {0}: exception caught while emitting {1}",
4305 Location, MethodBuilder);
4306 throw;
4310 public override bool EnableOverloadChecks (MemberCore overload)
4312 // TODO: It can be deleted when members will be defined in correct order
4313 if (overload is Operator)
4314 return overload.EnableOverloadChecks (this);
4316 if (overload is Indexer)
4317 return false;
4319 return base.EnableOverloadChecks (overload);
4322 public static void Error1599 (Location loc, Type t)
4324 Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t));
4327 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
4329 MethodInfo mi = (MethodInfo) Parent.PartialContainer.BaseCache.FindMemberToOverride (
4330 Parent.TypeBuilder, Name, Parameters, GenericMethod, false);
4332 if (mi == null)
4333 return null;
4335 if (mi.IsSpecialName)
4336 return null;
4338 base_ret_type = TypeManager.TypeToCoreType (mi.ReturnType);
4339 return mi;
4342 public void SetPartialDefinition (Method methodDefinition)
4344 caching_flags |= Flags.PartialDefinitionExists;
4345 methodDefinition.MethodBuilder = MethodBuilder;
4347 for (int i = 0; i < methodDefinition.Parameters.Count; ++i ) {
4348 Parameters [i].DefaultValue = methodDefinition.Parameters [i].DefaultValue;
4351 if (methodDefinition.attributes == null)
4352 return;
4354 if (attributes == null) {
4355 attributes = methodDefinition.attributes;
4356 } else {
4357 attributes.Attrs.AddRange (methodDefinition.attributes.Attrs);
4361 protected override bool VerifyClsCompliance ()
4363 if (!base.VerifyClsCompliance ())
4364 return false;
4366 if (!Parameters.IsEmpty) {
4367 ArrayList al = (ArrayList)Parent.PartialContainer.MemberCache.Members [Name];
4368 if (al.Count > 1)
4369 MemberCache.VerifyClsParameterConflict (al, this, MethodBuilder);
4372 return true;
4376 public abstract class ConstructorInitializer : ExpressionStatement
4378 Arguments argument_list;
4379 MethodGroupExpr base_constructor_group;
4381 public ConstructorInitializer (Arguments argument_list, Location loc)
4383 this.argument_list = argument_list;
4384 this.loc = loc;
4387 public Arguments Arguments {
4388 get {
4389 return argument_list;
4393 public override Expression CreateExpressionTree (EmitContext ec)
4395 throw new NotSupportedException ("ET");
4398 public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
4400 if (argument_list != null){
4401 argument_list.Resolve (ec);
4404 if (this is ConstructorBaseInitializer) {
4405 if (ec.ContainerType.BaseType == null)
4406 return true;
4408 type = ec.ContainerType.BaseType;
4409 if (TypeManager.IsStruct (ec.ContainerType)) {
4410 Report.Error (522, loc,
4411 "`{0}': Struct constructors cannot call base constructors", TypeManager.CSharpSignature (caller_builder));
4412 return false;
4414 } else {
4416 // It is legal to have "this" initializers that take no arguments
4417 // in structs, they are just no-ops.
4419 // struct D { public D (int a) : this () {}
4421 if (TypeManager.IsStruct (ec.ContainerType) && argument_list == null)
4422 return true;
4424 type = ec.ContainerType;
4427 base_constructor_group = MemberLookupFinal (
4428 ec, null, type, ConstructorBuilder.ConstructorName, MemberTypes.Constructor,
4429 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
4430 loc) as MethodGroupExpr;
4432 if (base_constructor_group == null)
4433 return false;
4435 base_constructor_group = base_constructor_group.OverloadResolve (
4436 ec, ref argument_list, false, loc);
4438 if (base_constructor_group == null)
4439 return false;
4441 ConstructorInfo base_ctor = (ConstructorInfo)base_constructor_group;
4443 if (base_ctor == caller_builder){
4444 Report.Error (516, loc, "Constructor `{0}' cannot call itself", TypeManager.CSharpSignature (caller_builder));
4447 return true;
4450 public override Expression DoResolve (EmitContext ec)
4452 throw new NotSupportedException ();
4455 public override void Emit (EmitContext ec)
4457 // It can be null for static initializers
4458 if (base_constructor_group == null)
4459 return;
4461 ec.Mark (loc);
4462 if (!ec.IsStatic)
4463 base_constructor_group.InstanceExpression = ec.GetThis (loc);
4465 base_constructor_group.EmitCall (ec, argument_list);
4468 public override void EmitStatement (EmitContext ec)
4470 Emit (ec);
4474 public class ConstructorBaseInitializer : ConstructorInitializer {
4475 public ConstructorBaseInitializer (Arguments argument_list, Location l) :
4476 base (argument_list, l)
4481 class GeneratedBaseInitializer: ConstructorBaseInitializer {
4482 public GeneratedBaseInitializer (Location loc):
4483 base (null, loc)
4488 public class ConstructorThisInitializer : ConstructorInitializer {
4489 public ConstructorThisInitializer (Arguments argument_list, Location l) :
4490 base (argument_list, l)
4495 public class Constructor : MethodCore, IMethodData {
4496 public ConstructorBuilder ConstructorBuilder;
4497 public ConstructorInitializer Initializer;
4498 ListDictionary declarative_security;
4499 bool has_compliant_args;
4501 // <summary>
4502 // Modifiers allowed for a constructor.
4503 // </summary>
4504 public const int AllowedModifiers =
4505 Modifiers.PUBLIC |
4506 Modifiers.PROTECTED |
4507 Modifiers.INTERNAL |
4508 Modifiers.STATIC |
4509 Modifiers.UNSAFE |
4510 Modifiers.EXTERN |
4511 Modifiers.PRIVATE;
4513 static readonly string[] attribute_targets = new string [] { "method" };
4516 // The spec claims that static is not permitted, but
4517 // my very own code has static constructors.
4519 public Constructor (DeclSpace parent, string name, int mod, Attributes attrs, ParametersCompiled args,
4520 ConstructorInitializer init, Location loc)
4521 : base (parent, null, null, mod, AllowedModifiers,
4522 new MemberName (name, loc), attrs, args)
4524 Initializer = init;
4527 public bool HasCompliantArgs {
4528 get { return has_compliant_args; }
4531 public override AttributeTargets AttributeTargets {
4532 get { return AttributeTargets.Constructor; }
4536 // Returns true if this is a default constructor
4538 public bool IsDefault ()
4540 if ((ModFlags & Modifiers.STATIC) != 0)
4541 return Parameters.IsEmpty;
4543 return Parameters.IsEmpty &&
4544 (Initializer is ConstructorBaseInitializer) &&
4545 (Initializer.Arguments == null);
4548 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
4550 if (a.IsValidSecurityAttribute ()) {
4551 if (declarative_security == null) {
4552 declarative_security = new ListDictionary ();
4554 a.ExtractSecurityPermissionSet (declarative_security);
4555 return;
4558 if (a.IsInternalMethodImplAttribute) {
4559 is_external_implementation = true;
4562 ConstructorBuilder.SetCustomAttribute (cb);
4565 protected override bool CheckBase ()
4567 if ((ModFlags & Modifiers.STATIC) != 0) {
4568 if (!Parameters.IsEmpty) {
4569 Report.Error (132, Location, "`{0}': The static constructor must be parameterless",
4570 GetSignatureForError ());
4571 return false;
4574 // the rest can be ignored
4575 return true;
4578 // Check whether arguments were correct.
4579 if (!DefineParameters (Parameters))
4580 return false;
4582 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
4583 Parent.MemberCache.CheckExistingMembersOverloads (this, ConstructorInfo.ConstructorName,
4584 Parameters);
4586 if (Parent.PartialContainer.Kind == Kind.Struct) {
4587 if (Parameters.Count == 0) {
4588 Report.Error (568, Location,
4589 "Structs cannot contain explicit parameterless constructors");
4590 return false;
4594 CheckProtectedModifier ();
4596 return true;
4600 // Creates the ConstructorBuilder
4602 public override bool Define ()
4604 if (ConstructorBuilder != null)
4605 return true;
4607 MethodAttributes ca = (MethodAttributes.RTSpecialName |
4608 MethodAttributes.SpecialName);
4610 if ((ModFlags & Modifiers.STATIC) != 0) {
4611 ca |= MethodAttributes.Static | MethodAttributes.Private;
4612 } else {
4613 ca |= MethodAttributes.HideBySig;
4615 if ((ModFlags & Modifiers.PUBLIC) != 0)
4616 ca |= MethodAttributes.Public;
4617 else if ((ModFlags & Modifiers.PROTECTED) != 0){
4618 if ((ModFlags & Modifiers.INTERNAL) != 0)
4619 ca |= MethodAttributes.FamORAssem;
4620 else
4621 ca |= MethodAttributes.Family;
4622 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
4623 ca |= MethodAttributes.Assembly;
4624 else
4625 ca |= MethodAttributes.Private;
4628 if (!CheckAbstractAndExtern (block != null))
4629 return false;
4631 // Check if arguments were correct.
4632 if (!CheckBase ())
4633 return false;
4635 ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
4636 ca, CallingConventions,
4637 Parameters.GetEmitTypes ());
4639 if (Parent.PartialContainer.IsComImport) {
4640 if (!IsDefault ()) {
4641 Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
4642 Parent.GetSignatureForError ());
4644 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
4647 Parent.MemberCache.AddMember (ConstructorBuilder, this);
4648 TypeManager.AddMethod (ConstructorBuilder, this);
4650 // It's here only to report an error
4651 if (block != null && block.IsIterator) {
4652 member_type = TypeManager.void_type;
4653 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
4656 return true;
4660 // Emits the code
4662 public override void Emit ()
4664 if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
4665 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (ConstructorBuilder);
4667 if (OptAttributes != null)
4668 OptAttributes.Emit ();
4670 base.Emit ();
4672 EmitContext ec = CreateEmitContext (null, null);
4675 // If we use a "this (...)" constructor initializer, then
4676 // do not emit field initializers, they are initialized in the other constructor
4678 bool emit_field_initializers = ((ModFlags & Modifiers.STATIC) != 0) ||
4679 !(Initializer is ConstructorThisInitializer);
4681 if (emit_field_initializers)
4682 Parent.PartialContainer.ResolveFieldInitializers (ec);
4684 if (block != null) {
4685 // If this is a non-static `struct' constructor and doesn't have any
4686 // initializer, it must initialize all of the struct's fields.
4687 if ((Parent.PartialContainer.Kind == Kind.Struct) &&
4688 ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
4689 block.AddThisVariable (Parent, Location);
4691 if (!block.ResolveMeta (ec, Parameters))
4692 block = null;
4694 if (block != null && (ModFlags & Modifiers.STATIC) == 0){
4695 if (Parent.PartialContainer.Kind == Kind.Class && Initializer == null)
4696 Initializer = new GeneratedBaseInitializer (Location);
4699 // Spec mandates that Initializers will not have `this' access
4701 if (Initializer != null) {
4702 ec.IsStatic = true;
4703 Initializer.Resolve (ConstructorBuilder, ec);
4704 ec.IsStatic = false;
4705 block.AddScopeStatement (new StatementExpression (Initializer));
4710 Parameters.ApplyAttributes (ConstructorBuilder);
4712 SourceMethod source = null;
4713 if (block == null)
4714 ec.OmitDebuggingInfo = true;
4715 else
4716 source = SourceMethod.Create (Parent, ConstructorBuilder, block);
4718 bool unreachable = false;
4719 if (block != null) {
4720 if (!ec.ResolveTopBlock (null, block, Parameters, this, out unreachable))
4721 return;
4723 ec.EmitMeta (block);
4725 if (Report.Errors > 0)
4726 return;
4728 ec.EmitResolvedTopBlock (block, unreachable);
4731 if (source != null)
4732 source.CloseMethod ();
4734 if (declarative_security != null) {
4735 foreach (DictionaryEntry de in declarative_security) {
4736 ConstructorBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
4740 block = null;
4743 // Is never override
4744 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
4746 return null;
4749 public override string GetSignatureForError()
4751 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
4754 public override string[] ValidAttributeTargets {
4755 get {
4756 return attribute_targets;
4760 protected override bool VerifyClsCompliance ()
4762 if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
4763 return false;
4766 if (!Parameters.IsEmpty) {
4767 ArrayList al = (ArrayList)Parent.MemberCache.Members [ConstructorInfo.ConstructorName];
4768 if (al.Count > 2)
4769 MemberCache.VerifyClsParameterConflict (al, this, ConstructorBuilder);
4771 if (TypeManager.IsSubclassOf (Parent.TypeBuilder, TypeManager.attribute_type)) {
4772 foreach (Type param in Parameters.Types) {
4773 if (param.IsArray) {
4774 return true;
4779 has_compliant_args = true;
4780 return true;
4783 #region IMethodData Members
4785 public MemberName MethodName {
4786 get {
4787 return MemberName;
4791 public Type ReturnType {
4792 get {
4793 return MemberType;
4797 public EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
4799 ILGenerator ig_ = ConstructorBuilder.GetILGenerator ();
4800 EmitContext ec = new EmitContext (this, Parent, Location, ig_, TypeManager.void_type, ModFlags, true);
4801 ec.CurrentBlock = block;
4802 return ec;
4805 public bool IsExcluded()
4807 return false;
4810 GenericMethod IMethodData.GenericMethod {
4811 get {
4812 return null;
4816 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
4819 #endregion
4822 /// <summary>
4823 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
4824 /// </summary>
4825 public interface IMethodData
4827 CallingConventions CallingConventions { get; }
4828 Location Location { get; }
4829 MemberName MethodName { get; }
4830 Type ReturnType { get; }
4831 GenericMethod GenericMethod { get; }
4832 ParametersCompiled ParameterInfo { get; }
4834 Attributes OptAttributes { get; }
4835 ToplevelBlock Block { get; set; }
4837 EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig);
4838 ObsoleteAttribute GetObsoleteAttribute ();
4839 string GetSignatureForError ();
4840 bool IsExcluded ();
4841 bool IsClsComplianceRequired ();
4842 void SetMemberIsUsed ();
4843 void EmitExtraSymbolInfo (SourceMethod source);
4847 // Encapsulates most of the Method's state
4849 public class MethodData {
4850 static FieldInfo methodbuilder_attrs_field;
4851 public readonly IMethodData method;
4853 public readonly GenericMethod GenericMethod;
4856 // Are we implementing an interface ?
4858 public MethodInfo implementing;
4861 // Protected data.
4863 protected InterfaceMemberBase member;
4864 protected int modifiers;
4865 protected MethodAttributes flags;
4866 protected Type declaring_type;
4867 protected MethodInfo parent_method;
4869 MethodBuilder builder = null;
4870 public MethodBuilder MethodBuilder {
4871 get {
4872 return builder;
4876 public Type DeclaringType {
4877 get {
4878 return declaring_type;
4882 public MethodData (InterfaceMemberBase member,
4883 int modifiers, MethodAttributes flags, IMethodData method)
4885 this.member = member;
4886 this.modifiers = modifiers;
4887 this.flags = flags;
4889 this.method = method;
4892 public MethodData (InterfaceMemberBase member,
4893 int modifiers, MethodAttributes flags,
4894 IMethodData method, MethodBuilder builder,
4895 GenericMethod generic, MethodInfo parent_method)
4896 : this (member, modifiers, flags, method)
4898 this.builder = builder;
4899 this.GenericMethod = generic;
4900 this.parent_method = parent_method;
4903 public bool Define (DeclSpace parent, string method_full_name)
4905 string name = method.MethodName.Basename;
4907 TypeContainer container = parent.PartialContainer;
4909 PendingImplementation pending = container.PendingImplementations;
4910 if (pending != null){
4911 implementing = pending.IsInterfaceMethod (name, member.InterfaceType, this);
4913 if (member.InterfaceType != null){
4914 if (implementing == null){
4915 if (member is PropertyBase) {
4916 Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'",
4917 method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType),
4918 member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
4920 } else {
4921 Report.Error (539, method.Location,
4922 "`{0}.{1}' in explicit interface declaration is not a member of interface",
4923 TypeManager.CSharpName (member.InterfaceType), member.ShortName);
4925 return false;
4927 if (implementing.IsSpecialName && !(method is AbstractPropertyEventMethod)) {
4928 Report.SymbolRelatedToPreviousError (implementing);
4929 Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
4930 member.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
4931 return false;
4933 } else {
4934 if (implementing != null) {
4935 AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod;
4936 if (prop_method == null) {
4937 if (TypeManager.IsSpecialMethod (implementing)) {
4938 Report.SymbolRelatedToPreviousError (implementing);
4939 Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}.{2}'",
4940 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing),
4941 implementing.Name.StartsWith ("get_") ? "get" : "set");
4943 } else if (implementing.DeclaringType.IsInterface) {
4944 if (!implementing.IsSpecialName) {
4945 Report.SymbolRelatedToPreviousError (implementing);
4946 Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
4947 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
4948 return false;
4950 PropertyBase.PropertyMethod pm = prop_method as PropertyBase.PropertyMethod;
4951 if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
4952 Report.SymbolRelatedToPreviousError (implementing);
4953 Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'",
4954 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing, true));
4955 return false;
4963 // For implicit implementations, make sure we are public, for
4964 // explicit implementations, make sure we are private.
4966 if (implementing != null){
4968 // Setting null inside this block will trigger a more
4969 // verbose error reporting for missing interface implementations
4971 // The "candidate" function has been flagged already
4972 // but it wont get cleared
4974 if (member.IsExplicitImpl){
4975 if (method.ParameterInfo.HasParams && !TypeManager.GetParameterData (implementing).HasParams) {
4976 Report.SymbolRelatedToPreviousError (implementing);
4977 Report.Error (466, method.Location, "`{0}': the explicit interface implementation cannot introduce the params modifier",
4978 method.GetSignatureForError ());
4979 return false;
4981 } else {
4982 if (implementing.DeclaringType.IsInterface) {
4984 // If this is an interface method implementation,
4985 // check for public accessibility
4987 if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
4989 implementing = null;
4991 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
4992 // We may never be private.
4993 implementing = null;
4995 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
4997 // We may be protected if we're overriding something.
4999 implementing = null;
5004 // Static is not allowed
5006 if ((modifiers & Modifiers.STATIC) != 0){
5007 implementing = null;
5012 // If implementing is still valid, set flags
5014 if (implementing != null){
5016 // When implementing interface methods, set NewSlot
5017 // unless, we are overwriting a method.
5019 if (implementing.DeclaringType.IsInterface){
5020 if ((modifiers & Modifiers.OVERRIDE) == 0)
5021 flags |= MethodAttributes.NewSlot;
5023 flags |=
5024 MethodAttributes.Virtual |
5025 MethodAttributes.HideBySig;
5027 // Set Final unless we're virtual, abstract or already overriding a method.
5028 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
5029 flags |= MethodAttributes.Final;
5032 DefineMethodBuilder (container, method_full_name, method.ParameterInfo);
5034 if (builder == null)
5035 return false;
5037 if (container.CurrentType != null)
5038 declaring_type = container.CurrentType;
5039 else
5040 declaring_type = container.TypeBuilder;
5042 if (implementing != null && member.IsExplicitImpl) {
5043 container.TypeBuilder.DefineMethodOverride (builder, implementing);
5046 TypeManager.AddMethod (builder, method);
5048 if (GenericMethod != null) {
5049 bool is_override = member.IsExplicitImpl |
5050 ((modifiers & Modifiers.OVERRIDE) != 0);
5052 if (implementing != null)
5053 parent_method = implementing;
5055 EmitContext ec = method.CreateEmitContext (container, null);
5056 if (!GenericMethod.DefineType (ec, builder, parent_method, is_override))
5057 return false;
5060 return true;
5064 /// <summary>
5065 /// Create the MethodBuilder for the method
5066 /// </summary>
5067 void DefineMethodBuilder (TypeContainer container, string method_name, ParametersCompiled param)
5069 if (builder == null) {
5070 builder = container.TypeBuilder.DefineMethod (
5071 method_name, flags, method.CallingConventions,
5072 TypeManager.TypeToReflectionType (method.ReturnType),
5073 param.GetEmitTypes ());
5074 return;
5077 #if GMCS_SOURCE
5079 // Generic method has been already defined to resolve method parameters
5080 // correctly when they use type parameters
5082 builder.SetParameters (param.GetEmitTypes ());
5083 builder.SetReturnType (method.ReturnType);
5084 #endif
5085 if (builder.Attributes != flags) {
5086 try {
5087 if (methodbuilder_attrs_field == null)
5088 methodbuilder_attrs_field = typeof (MethodBuilder).GetField ("attrs", BindingFlags.NonPublic | BindingFlags.Instance);
5089 methodbuilder_attrs_field.SetValue (builder, flags);
5090 } catch {
5091 Report.RuntimeMissingSupport (method.Location, "Generic method MethodAttributes");
5097 // Emits the code
5099 public void Emit (DeclSpace parent)
5101 ToplevelBlock block = method.Block;
5103 EmitContext ec;
5104 if (block != null)
5105 ec = method.CreateEmitContext (parent, builder.GetILGenerator ());
5106 else
5107 ec = method.CreateEmitContext (parent, null);
5109 method.ParameterInfo.ApplyAttributes (MethodBuilder);
5111 if (GenericMethod != null)
5112 GenericMethod.EmitAttributes ();
5115 // clear the pending implementation flag
5117 if (implementing != null)
5118 parent.PartialContainer.PendingImplementations.ImplementMethod (method.MethodName.Basename,
5119 member.InterfaceType, this, member.IsExplicitImpl);
5121 SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
5123 ec.EmitTopBlock (method, block);
5125 if (source != null) {
5126 method.EmitExtraSymbolInfo (source);
5127 source.CloseMethod ();
5132 public class Destructor : MethodOrOperator
5134 const int AllowedModifiers =
5135 Modifiers.UNSAFE |
5136 Modifiers.EXTERN;
5138 static readonly string[] attribute_targets = new string [] { "method" };
5140 public static readonly string MetadataName = "Finalize";
5142 public Destructor (DeclSpace parent, int mod, ParametersCompiled parameters, Attributes attrs, Location l)
5143 : base (parent, null, TypeManager.system_void_expr, mod, AllowedModifiers,
5144 new MemberName (MetadataName, l), attrs, parameters)
5146 ModFlags &= ~Modifiers.PRIVATE;
5147 ModFlags |= Modifiers.PROTECTED;
5150 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
5152 if (a.Type == pa.Conditional) {
5153 Error_ConditionalAttributeIsNotValid ();
5154 return;
5157 base.ApplyAttributeBuilder (a, cb, pa);
5160 protected override bool CheckBase ()
5162 flags |= MethodAttributes.Virtual;
5164 if (!base.CheckBase ())
5165 return false;
5167 if (Parent.PartialContainer.BaseCache == null)
5168 return true;
5170 Type base_type = Parent.PartialContainer.BaseCache.Container.Type;
5171 if (base_type != null && Block != null) {
5172 MethodGroupExpr method_expr = Expression.MethodLookup (Parent.TypeBuilder, base_type, MetadataName, Location);
5173 if (method_expr == null)
5174 throw new NotImplementedException ();
5176 method_expr.IsBase = true;
5177 method_expr.InstanceExpression = new CompilerGeneratedThis (Parent.TypeBuilder, Location);
5179 ToplevelBlock new_block = new ToplevelBlock (Block.StartLocation);
5180 new_block.EndLocation = Block.EndLocation;
5182 Block finaly_block = new ExplicitBlock (new_block, Location, Location);
5183 Block try_block = new Block (new_block, block);
5186 // 0-size arguments to avoid CS0250 error
5187 // TODO: Should use AddScopeStatement or something else which emits correct
5188 // debugger scope
5190 finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0))));
5191 new_block.AddStatement (new TryFinally (try_block, finaly_block, Location));
5193 block = new_block;
5196 return true;
5199 public override string GetSignatureForError ()
5201 return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
5204 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
5206 return null;
5209 public override string[] ValidAttributeTargets {
5210 get {
5211 return attribute_targets;
5216 public abstract class MemberBase : MemberCore
5218 protected FullNamedExpression type_name;
5219 protected Type member_type;
5221 public readonly DeclSpace ds;
5222 public readonly GenericMethod GenericMethod;
5224 protected MemberBase (DeclSpace parent, GenericMethod generic,
5225 FullNamedExpression type, int mod, int allowed_mod, int def_mod,
5226 MemberName name, Attributes attrs)
5227 : base (parent, name, attrs)
5229 this.ds = generic != null ? generic : (DeclSpace) parent;
5230 this.type_name = type;
5231 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, Location);
5232 GenericMethod = generic;
5233 if (GenericMethod != null)
5234 GenericMethod.ModFlags = ModFlags;
5238 // Main member define entry
5240 public override bool Define ()
5242 DoMemberTypeIndependentChecks ();
5245 // Returns false only when type resolution failed
5247 if (!ResolveMemberType ())
5248 return false;
5250 DoMemberTypeDependentChecks ();
5251 return true;
5255 // Any type_name independent checks
5257 protected virtual void DoMemberTypeIndependentChecks ()
5259 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
5260 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
5261 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
5262 GetSignatureForError (), Parent.GetSignatureForError ());
5267 // Any type_name dependent checks
5269 protected virtual void DoMemberTypeDependentChecks ()
5271 // verify accessibility
5272 if (!IsAccessibleAs (MemberType)) {
5273 Report.SymbolRelatedToPreviousError (MemberType);
5274 if (this is Property)
5275 Report.Error (53, Location,
5276 "Inconsistent accessibility: property type `" +
5277 TypeManager.CSharpName (MemberType) + "' is less " +
5278 "accessible than property `" + GetSignatureForError () + "'");
5279 else if (this is Indexer)
5280 Report.Error (54, Location,
5281 "Inconsistent accessibility: indexer return type `" +
5282 TypeManager.CSharpName (MemberType) + "' is less " +
5283 "accessible than indexer `" + GetSignatureForError () + "'");
5284 else if (this is MethodCore) {
5285 if (this is Operator)
5286 Report.Error (56, Location,
5287 "Inconsistent accessibility: return type `" +
5288 TypeManager.CSharpName (MemberType) + "' is less " +
5289 "accessible than operator `" + GetSignatureForError () + "'");
5290 else
5291 Report.Error (50, Location,
5292 "Inconsistent accessibility: return type `" +
5293 TypeManager.CSharpName (MemberType) + "' is less " +
5294 "accessible than method `" + GetSignatureForError () + "'");
5295 } else {
5296 Report.Error (52, Location,
5297 "Inconsistent accessibility: field type `" +
5298 TypeManager.CSharpName (MemberType) + "' is less " +
5299 "accessible than field `" + GetSignatureForError () + "'");
5303 Variance variance = this is Event ? Variance.Contravariant : Variance.Covariant;
5304 TypeManager.CheckTypeVariance (MemberType, variance, this);
5307 protected bool IsTypePermitted ()
5309 if (TypeManager.IsSpecialType (MemberType)) {
5310 Report.Error (610, Location, "Field or property cannot be of type `{0}'", TypeManager.CSharpName (MemberType));
5311 return false;
5313 return true;
5316 protected virtual bool CheckBase ()
5318 CheckProtectedModifier ();
5320 return true;
5323 public Type MemberType {
5324 get { return member_type; }
5327 protected virtual bool ResolveMemberType ()
5329 if (member_type != null)
5330 throw new InternalErrorException ("Multi-resolve");
5332 IResolveContext rc = GenericMethod == null ? this : (IResolveContext) ds;
5333 TypeExpr te = type_name.ResolveAsTypeTerminal (rc, false);
5334 if (te == null)
5335 return false;
5338 // Replace original type name, error reporting can use fully resolved name
5340 type_name = te;
5342 member_type = te.Type;
5343 return true;
5348 // Abstract class for all fields
5350 abstract public class FieldBase : MemberBase {
5351 public FieldBuilder FieldBuilder;
5352 public Status status;
5353 protected Expression initializer;
5355 [Flags]
5356 public enum Status : byte {
5357 HAS_OFFSET = 4 // Used by FieldMember.
5360 static readonly string[] attribute_targets = new string [] { "field" };
5362 protected FieldBase (DeclSpace parent, FullNamedExpression type, int mod,
5363 int allowed_mod, MemberName name, Attributes attrs)
5364 : base (parent, null, type, mod, allowed_mod | Modifiers.ABSTRACT, Modifiers.PRIVATE,
5365 name, attrs)
5367 if ((mod & Modifiers.ABSTRACT) != 0)
5368 Report.Error (681, Location, "The modifier 'abstract' is not valid on fields. Try using a property instead");
5371 public override AttributeTargets AttributeTargets {
5372 get {
5373 return AttributeTargets.Field;
5377 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
5379 if (a.Type == pa.FieldOffset) {
5380 status |= Status.HAS_OFFSET;
5382 if (!Parent.PartialContainer.HasExplicitLayout) {
5383 Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)");
5384 return;
5387 if ((ModFlags & Modifiers.STATIC) != 0 || this is Const) {
5388 Report.Error (637, Location, "The FieldOffset attribute is not allowed on static or const fields");
5389 return;
5393 #if NET_2_0
5394 if (a.Type == pa.FixedBuffer) {
5395 Report.Error (1716, Location, "Do not use 'System.Runtime.CompilerServices.FixedBuffer' attribute. Use the 'fixed' field modifier instead");
5396 return;
5398 #endif
5400 #if !NET_2_0
5401 if (a.Type == pa.MarshalAs) {
5402 UnmanagedMarshal marshal = a.GetMarshal (this);
5403 if (marshal != null) {
5404 FieldBuilder.SetMarshal (marshal);
5406 return;
5408 #endif
5409 if ((a.HasSecurityAttribute)) {
5410 a.Error_InvalidSecurityParent ();
5411 return;
5414 FieldBuilder.SetCustomAttribute (cb);
5417 protected override bool CheckBase ()
5419 if (!base.CheckBase ())
5420 return false;
5422 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Name, false);
5423 if (conflict_symbol == null) {
5424 if ((ModFlags & Modifiers.NEW) != 0) {
5425 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
5427 return true;
5430 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE | Modifiers.BACKING_FIELD)) == 0) {
5431 Report.SymbolRelatedToPreviousError (conflict_symbol);
5432 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
5433 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
5436 return true;
5439 protected override void DoMemberTypeDependentChecks ()
5441 base.DoMemberTypeDependentChecks ();
5443 if (TypeManager.IsGenericParameter (MemberType))
5444 return;
5446 if (MemberType.IsSealed && MemberType.IsAbstract) {
5447 Error_VariableOfStaticClass (Location, GetSignatureForError (), MemberType);
5450 CheckBase ();
5451 IsTypePermitted ();
5455 // Represents header string for documentation comment.
5457 public override string DocCommentHeader {
5458 get { return "F:"; }
5461 public override void Emit ()
5463 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
5464 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (FieldBuilder);
5466 if (OptAttributes != null) {
5467 OptAttributes.Emit ();
5470 if (((status & Status.HAS_OFFSET) == 0) && (ModFlags & (Modifiers.STATIC | Modifiers.BACKING_FIELD)) == 0 && Parent.PartialContainer.HasExplicitLayout) {
5471 Report.Error (625, Location, "`{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute", GetSignatureForError ());
5474 base.Emit ();
5477 public static void Error_VariableOfStaticClass (Location loc, string variable_name, Type static_class)
5479 Report.SymbolRelatedToPreviousError (static_class);
5480 Report.Error (723, loc, "`{0}': cannot declare variables of static types",
5481 variable_name);
5484 public Expression Initializer {
5485 set {
5486 if (value != null) {
5487 this.initializer = value;
5492 protected virtual bool IsFieldClsCompliant {
5493 get {
5494 if (FieldBuilder == null)
5495 return true;
5497 return AttributeTester.IsClsCompliant (FieldBuilder.FieldType);
5501 public override string[] ValidAttributeTargets
5503 get {
5504 return attribute_targets;
5508 protected override bool VerifyClsCompliance ()
5510 if (!base.VerifyClsCompliance ())
5511 return false;
5513 if (!IsFieldClsCompliant) {
5514 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
5515 GetSignatureForError ());
5517 return true;
5520 public void SetAssigned ()
5522 caching_flags |= Flags.IsAssigned;
5526 interface IFixedBuffer
5528 FieldInfo Element { get; }
5529 Type ElementType { get; }
5532 public class FixedFieldExternal: IFixedBuffer
5534 FieldInfo element_field;
5536 public FixedFieldExternal (FieldInfo fi)
5538 element_field = fi.FieldType.GetField (FixedField.FixedElementName);
5541 #region IFixedField Members
5543 public FieldInfo Element {
5544 get {
5545 return element_field;
5549 public Type ElementType {
5550 get {
5551 return element_field.FieldType;
5555 #endregion
5558 /// <summary>
5559 /// Fixed buffer implementation
5560 /// </summary>
5561 public class FixedField : FieldBase, IFixedBuffer
5563 public const string FixedElementName = "FixedElementField";
5564 static int GlobalCounter = 0;
5565 static object[] ctor_args = new object[] { (short)LayoutKind.Sequential };
5566 static FieldInfo[] fi;
5568 TypeBuilder fixed_buffer_type;
5569 FieldBuilder element;
5570 Expression size_expr;
5572 const int AllowedModifiers =
5573 Modifiers.NEW |
5574 Modifiers.PUBLIC |
5575 Modifiers.PROTECTED |
5576 Modifiers.INTERNAL |
5577 Modifiers.PRIVATE;
5579 public FixedField (DeclSpace parent, FullNamedExpression type, int mod, string name,
5580 Expression size_expr, Attributes attrs, Location loc):
5581 base (parent, type, mod, AllowedModifiers, new MemberName (name, loc), attrs)
5583 if (RootContext.Version < LanguageVersion.ISO_2)
5584 Report.FeatureIsNotAvailable (loc, "fixed size buffers");
5586 this.size_expr = size_expr;
5589 public override bool Define()
5591 if (!base.Define ())
5592 return false;
5594 if (!TypeManager.IsPrimitiveType (MemberType)) {
5595 Report.Error (1663, Location, "`{0}': Fixed size buffers type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double",
5596 GetSignatureForError ());
5599 // Create nested fixed buffer container
5600 string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++);
5601 fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name, Parent.Module.DefaultCharSetType |
5602 TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, TypeManager.value_type);
5604 element = fixed_buffer_type.DefineField (FixedElementName, MemberType, FieldAttributes.Public);
5605 RootContext.RegisterCompilerGeneratedType (fixed_buffer_type);
5607 FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, Modifiers.FieldAttr (ModFlags));
5608 Parent.MemberCache.AddMember (FieldBuilder, this);
5609 TypeManager.RegisterFieldBase (FieldBuilder, this);
5611 return true;
5614 protected override void DoMemberTypeIndependentChecks ()
5616 base.DoMemberTypeIndependentChecks ();
5618 if (!Parent.IsInUnsafeScope)
5619 Expression.UnsafeError (Location);
5621 if (Parent.PartialContainer.Kind != Kind.Struct) {
5622 Report.Error (1642, Location, "`{0}': Fixed size buffer fields may only be members of structs",
5623 GetSignatureForError ());
5627 public override void Emit()
5629 EmitContext ec = new EmitContext (this, Parent, Location, null, TypeManager.void_type, ModFlags);
5630 Constant c = size_expr.ResolveAsConstant (ec, this);
5631 if (c == null)
5632 return;
5634 IntConstant buffer_size_const = c.ImplicitConversionRequired (ec, TypeManager.int32_type, Location) as IntConstant;
5635 if (buffer_size_const == null)
5636 return;
5638 int buffer_size = buffer_size_const.Value;
5640 if (buffer_size <= 0) {
5641 Report.Error (1665, Location, "`{0}': Fixed size buffers must have a length greater than zero", GetSignatureForError ());
5642 return;
5645 int type_size = Expression.GetTypeSize (MemberType);
5647 if (buffer_size > int.MaxValue / type_size) {
5648 Report.Error (1664, Location, "Fixed size buffer `{0}' of length `{1}' and type `{2}' exceeded 2^31 limit",
5649 GetSignatureForError (), buffer_size.ToString (), TypeManager.CSharpName (MemberType));
5650 return;
5653 buffer_size *= type_size;
5654 EmitFieldSize (buffer_size);
5656 PredefinedAttributes.Get.UnsafeValueType.EmitAttribute (fixed_buffer_type);
5658 base.Emit ();
5661 void EmitFieldSize (int buffer_size)
5663 CustomAttributeBuilder cab;
5664 PredefinedAttribute pa;
5666 pa = PredefinedAttributes.Get.StructLayout;
5667 if (pa.Constructor == null &&
5668 !pa.ResolveConstructor (Location, TypeManager.short_type))
5669 return;
5671 // TODO: It's not cleared
5672 if (fi == null)
5673 fi = new FieldInfo[] { pa.Type.GetField ("Size") };
5675 object[] fi_val = new object[] { buffer_size };
5676 cab = new CustomAttributeBuilder (pa.Constructor,
5677 ctor_args, fi, fi_val);
5678 fixed_buffer_type.SetCustomAttribute (cab);
5681 // Don't emit FixedBufferAttribute attribute for private types
5683 if ((ModFlags & Modifiers.PRIVATE) != 0)
5684 return;
5686 pa = PredefinedAttributes.Get.FixedBuffer;
5687 if (pa.Constructor == null &&
5688 !pa.ResolveConstructor (Location, TypeManager.type_type, TypeManager.int32_type))
5689 return;
5691 cab = new CustomAttributeBuilder (pa.Constructor, new object[] { MemberType, buffer_size });
5692 FieldBuilder.SetCustomAttribute (cab);
5695 protected override bool IsFieldClsCompliant {
5696 get {
5697 return false;
5701 public void SetCharSet (TypeAttributes ta)
5703 TypeAttributes cta = fixed_buffer_type.Attributes;
5704 if ((cta & TypeAttributes.UnicodeClass) != (ta & TypeAttributes.UnicodeClass))
5705 SetTypeBuilderCharSet ((cta & ~TypeAttributes.AutoClass) | TypeAttributes.UnicodeClass);
5706 else if ((cta & TypeAttributes.AutoClass) != (ta & TypeAttributes.AutoClass))
5707 SetTypeBuilderCharSet ((cta & ~TypeAttributes.UnicodeClass) | TypeAttributes.AutoClass);
5708 else if (cta == 0 && ta != 0)
5709 SetTypeBuilderCharSet (cta & ~(TypeAttributes.UnicodeClass | TypeAttributes.AutoClass));
5712 void SetTypeBuilderCharSet (TypeAttributes ta)
5714 MethodInfo mi = typeof (TypeBuilder).GetMethod ("SetCharSet", BindingFlags.Instance | BindingFlags.NonPublic);
5715 if (mi == null) {
5716 Report.RuntimeMissingSupport (Location, "TypeBuilder::SetCharSet");
5717 } else {
5718 mi.Invoke (fixed_buffer_type, new object [] { ta });
5722 #region IFixedField Members
5724 public FieldInfo Element {
5725 get {
5726 return element;
5730 public Type ElementType {
5731 get {
5732 return MemberType;
5736 #endregion
5740 // The Field class is used to represents class/struct fields during parsing.
5742 public class Field : FieldBase {
5743 // <summary>
5744 // Modifiers allowed in a class declaration
5745 // </summary>
5746 const int AllowedModifiers =
5747 Modifiers.NEW |
5748 Modifiers.PUBLIC |
5749 Modifiers.PROTECTED |
5750 Modifiers.INTERNAL |
5751 Modifiers.PRIVATE |
5752 Modifiers.STATIC |
5753 Modifiers.VOLATILE |
5754 Modifiers.UNSAFE |
5755 Modifiers.READONLY;
5757 public Field (DeclSpace parent, FullNamedExpression type, int mod, MemberName name,
5758 Attributes attrs)
5759 : base (parent, type, mod, AllowedModifiers, name, attrs)
5763 bool CanBeVolatile ()
5765 if (TypeManager.IsReferenceType (MemberType))
5766 return true;
5768 if (MemberType == TypeManager.bool_type || MemberType == TypeManager.char_type ||
5769 MemberType == TypeManager.sbyte_type || MemberType == TypeManager.byte_type ||
5770 MemberType == TypeManager.short_type || MemberType == TypeManager.ushort_type ||
5771 MemberType == TypeManager.int32_type || MemberType == TypeManager.uint32_type ||
5772 MemberType == TypeManager.float_type ||
5773 MemberType == TypeManager.intptr_type || MemberType == TypeManager.uintptr_type)
5774 return true;
5776 if (TypeManager.IsEnumType (MemberType))
5777 return true;
5779 return false;
5782 bool CheckStructLayout (Type type, bool isStatic)
5784 if (TypeManager.IsBuiltinType (type))
5785 return true;
5787 if (isStatic) {
5788 if (!TypeManager.IsValueType (type) || TypeManager.IsEqual (type, Parent.TypeBuilder))
5789 return true;
5792 if (!TypeManager.IsEqual (TypeManager.DropGenericTypeArguments (type), Parent.TypeBuilder)) {
5793 if (!TypeManager.IsGenericType (type))
5794 return true;
5796 foreach (Type t in TypeManager.GetTypeArguments (type)) {
5797 if (!CheckStructLayout (t, false))
5798 return false;
5800 return true;
5803 Report.Error (523, Location,
5804 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
5805 GetSignatureForError (), TypeManager.CSharpName (MemberType));
5806 return false;
5809 public override bool Define ()
5811 if (!base.Define ())
5812 return false;
5814 try {
5815 #if GMCS_SOURCE
5816 Type[] required_modifier = null;
5817 if ((ModFlags & Modifiers.VOLATILE) != 0) {
5818 if (TypeManager.isvolatile_type == null)
5819 TypeManager.isvolatile_type = TypeManager.CoreLookupType (
5820 "System.Runtime.CompilerServices", "IsVolatile", Kind.Class, true);
5822 if (TypeManager.isvolatile_type != null)
5823 required_modifier = new Type [] { TypeManager.isvolatile_type };
5826 FieldBuilder = Parent.TypeBuilder.DefineField (
5827 Name, MemberType, required_modifier, null, Modifiers.FieldAttr (ModFlags));
5828 #else
5829 FieldBuilder = Parent.TypeBuilder.DefineField (
5830 Name, MemberType, Modifiers.FieldAttr (ModFlags));
5831 #endif
5832 // Don't cache inaccessible fields
5833 if ((ModFlags & Modifiers.BACKING_FIELD) == 0) {
5834 Parent.MemberCache.AddMember (FieldBuilder, this);
5837 TypeManager.RegisterFieldBase (FieldBuilder, this);
5839 catch (ArgumentException) {
5840 Report.RuntimeMissingSupport (Location, "`void' or `void*' field type");
5841 return false;
5844 if (initializer != null) {
5845 ((TypeContainer) Parent).RegisterFieldForInitialization (this,
5846 new FieldInitializer (FieldBuilder, initializer, this));
5847 } else {
5848 if (Parent.PartialContainer.Kind == Kind.Struct)
5849 CheckStructLayout (member_type, (ModFlags & Modifiers.STATIC) != 0);
5852 return true;
5855 protected override void DoMemberTypeDependentChecks ()
5857 base.DoMemberTypeDependentChecks ();
5859 if ((ModFlags & Modifiers.VOLATILE) != 0) {
5860 if (!CanBeVolatile ()) {
5861 Report.Error (677, Location, "`{0}': A volatile field cannot be of the type `{1}'",
5862 GetSignatureForError (), TypeManager.CSharpName (MemberType));
5865 if ((ModFlags & Modifiers.READONLY) != 0) {
5866 Report.Error (678, Location, "`{0}': A field cannot be both volatile and readonly",
5867 GetSignatureForError ());
5872 protected override bool VerifyClsCompliance ()
5874 if (!base.VerifyClsCompliance ())
5875 return false;
5877 if ((ModFlags & Modifiers.VOLATILE) != 0) {
5878 Report.Warning (3026, 1, Location, "CLS-compliant field `{0}' cannot be volatile", GetSignatureForError ());
5881 return true;
5886 // `set' and `get' accessors are represented with an Accessor.
5888 public class Accessor {
5890 // Null if the accessor is empty, or a Block if not
5892 public const int AllowedModifiers =
5893 Modifiers.PUBLIC |
5894 Modifiers.PROTECTED |
5895 Modifiers.INTERNAL |
5896 Modifiers.PRIVATE;
5898 public ToplevelBlock Block;
5899 public Attributes Attributes;
5900 public Location Location;
5901 public int ModFlags;
5902 public ParametersCompiled Parameters;
5904 public Accessor (ToplevelBlock b, int mod, Attributes attrs, ParametersCompiled p, Location loc)
5906 Block = b;
5907 Attributes = attrs;
5908 Location = loc;
5909 Parameters = p;
5910 ModFlags = Modifiers.Check (AllowedModifiers, mod, 0, loc);
5914 // Ooouh Martin, templates are missing here.
5915 // When it will be possible move here a lot of child code and template method type.
5916 public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData {
5917 protected MethodData method_data;
5918 protected ToplevelBlock block;
5919 protected ListDictionary declarative_security;
5921 // The accessor are created even if they are not wanted.
5922 // But we need them because their names are reserved.
5923 // Field says whether accessor will be emited or not
5924 public readonly bool IsDummy;
5926 protected readonly string prefix;
5928 ReturnParameter return_attributes;
5930 public AbstractPropertyEventMethod (PropertyBasedMember member, string prefix)
5931 : base (member.Parent, SetupName (prefix, member, member.Location), null)
5933 this.prefix = prefix;
5934 IsDummy = true;
5937 public AbstractPropertyEventMethod (InterfaceMemberBase member, Accessor accessor,
5938 string prefix)
5939 : base (member.Parent, SetupName (prefix, member, accessor.Location),
5940 accessor.Attributes)
5942 this.prefix = prefix;
5943 this.block = accessor.Block;
5946 static MemberName SetupName (string prefix, InterfaceMemberBase member, Location loc)
5948 return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc);
5951 public void UpdateName (InterfaceMemberBase member)
5953 SetMemberName (SetupName (prefix, member, Location));
5956 #region IMethodData Members
5958 public ToplevelBlock Block {
5959 get {
5960 return block;
5963 set {
5964 block = value;
5968 public CallingConventions CallingConventions {
5969 get {
5970 return CallingConventions.Standard;
5974 public bool IsExcluded ()
5976 return false;
5979 GenericMethod IMethodData.GenericMethod {
5980 get {
5981 return null;
5985 public MemberName MethodName {
5986 get {
5987 return MemberName;
5991 public Type[] ParameterTypes {
5992 get {
5993 return ParameterInfo.Types;
5997 public abstract ParametersCompiled ParameterInfo { get ; }
5998 public abstract Type ReturnType { get; }
5999 public abstract EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig);
6001 #endregion
6003 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6005 if (a.Type == pa.CLSCompliant || a.Type == pa.Obsolete || a.Type == pa.Conditional) {
6006 Report.Error (1667, a.Location,
6007 "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
6008 TypeManager.CSharpName (a.Type), a.GetValidTargets ());
6009 return;
6012 if (a.IsValidSecurityAttribute ()) {
6013 if (declarative_security == null)
6014 declarative_security = new ListDictionary ();
6015 a.ExtractSecurityPermissionSet (declarative_security);
6016 return;
6019 if (a.Target == AttributeTargets.Method) {
6020 method_data.MethodBuilder.SetCustomAttribute (cb);
6021 return;
6024 if (a.Target == AttributeTargets.ReturnValue) {
6025 if (return_attributes == null)
6026 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
6028 return_attributes.ApplyAttributeBuilder (a, cb, pa);
6029 return;
6032 ApplyToExtraTarget (a, cb, pa);
6035 protected virtual void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6037 throw new NotSupportedException ("You forgot to define special attribute target handling");
6040 // It is not supported for the accessors
6041 public sealed override bool Define()
6043 throw new NotSupportedException ();
6046 public virtual void Emit (DeclSpace parent)
6048 method_data.Emit (parent);
6050 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
6051 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (method_data.MethodBuilder);
6052 if (((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0))
6053 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (method_data.MethodBuilder);
6055 if (OptAttributes != null)
6056 OptAttributes.Emit ();
6058 if (declarative_security != null) {
6059 foreach (DictionaryEntry de in declarative_security) {
6060 method_data.MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
6064 block = null;
6067 public override bool EnableOverloadChecks (MemberCore overload)
6069 // This can only happen with indexers and it will
6070 // be catched as indexer difference
6071 if (overload is AbstractPropertyEventMethod)
6072 return true;
6074 if (overload is MethodCore) {
6075 caching_flags |= Flags.MethodOverloadsExist;
6076 return true;
6078 return false;
6081 public override bool IsClsComplianceRequired()
6083 return false;
6086 public bool IsDuplicateImplementation (MethodCore method)
6088 if (!MemberName.Equals (method.MemberName))
6089 return false;
6091 Type[] param_types = method.ParameterTypes;
6093 if (param_types == null || param_types.Length != ParameterTypes.Length)
6094 return false;
6096 for (int i = 0; i < param_types.Length; i++)
6097 if (param_types [i] != ParameterTypes [i])
6098 return false;
6100 Report.SymbolRelatedToPreviousError (method);
6101 Report.Error (82, Location, "A member `{0}' is already reserved",
6102 method.GetSignatureForError ());
6103 return true;
6106 public override bool IsUsed
6108 get {
6109 if (IsDummy)
6110 return false;
6112 return base.IsUsed;
6117 // Represents header string for documentation comment.
6119 public override string DocCommentHeader {
6120 get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
6123 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
6128 // Properties and Indexers both generate PropertyBuilders, we use this to share
6129 // their common bits.
6131 abstract public class PropertyBase : PropertyBasedMember {
6133 public class GetMethod : PropertyMethod
6135 static string[] attribute_targets = new string [] { "method", "return" };
6137 public GetMethod (PropertyBase method):
6138 base (method, "get_")
6142 public GetMethod (PropertyBase method, Accessor accessor):
6143 base (method, accessor, "get_")
6147 public override MethodBuilder Define (DeclSpace parent)
6149 base.Define (parent);
6151 if (IsDummy)
6152 return null;
6154 method_data = new MethodData (method, ModFlags, flags, this);
6156 if (!method_data.Define (parent, method.GetFullName (MemberName)))
6157 return null;
6159 return method_data.MethodBuilder;
6162 public override Type ReturnType {
6163 get {
6164 return method.MemberType;
6168 public override ParametersCompiled ParameterInfo {
6169 get {
6170 return ParametersCompiled.EmptyReadOnlyParameters;
6174 public override string[] ValidAttributeTargets {
6175 get {
6176 return attribute_targets;
6181 public class SetMethod : PropertyMethod {
6183 static string[] attribute_targets = new string [] { "method", "param", "return" };
6184 ImplicitParameter param_attr;
6185 protected ParametersCompiled parameters;
6187 public SetMethod (PropertyBase method) :
6188 base (method, "set_")
6190 parameters = new ParametersCompiled (
6191 new Parameter (method.type_name, "value", Parameter.Modifier.NONE, null, Location));
6194 public SetMethod (PropertyBase method, Accessor accessor):
6195 base (method, accessor, "set_")
6197 this.parameters = accessor.Parameters;
6200 protected override void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6202 if (a.Target == AttributeTargets.Parameter) {
6203 if (param_attr == null)
6204 param_attr = new ImplicitParameter (method_data.MethodBuilder);
6206 param_attr.ApplyAttributeBuilder (a, cb, pa);
6207 return;
6210 base.ApplyAttributeBuilder (a, cb, pa);
6213 public override ParametersCompiled ParameterInfo {
6214 get {
6215 return parameters;
6219 public override MethodBuilder Define (DeclSpace parent)
6221 parameters.Resolve (ResolveContext);
6223 base.Define (parent);
6225 if (IsDummy)
6226 return null;
6228 method_data = new MethodData (method, ModFlags, flags, this);
6230 if (!method_data.Define (parent, method.GetFullName (MemberName)))
6231 return null;
6233 return method_data.MethodBuilder;
6236 public override Type ReturnType {
6237 get {
6238 return TypeManager.void_type;
6242 public override string[] ValidAttributeTargets {
6243 get {
6244 return attribute_targets;
6249 static string[] attribute_targets = new string [] { "property" };
6251 public abstract class PropertyMethod : AbstractPropertyEventMethod
6253 protected readonly PropertyBase method;
6254 protected MethodAttributes flags;
6256 public PropertyMethod (PropertyBase method, string prefix)
6257 : base (method, prefix)
6259 this.method = method;
6260 this.ModFlags = method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE);
6263 public PropertyMethod (PropertyBase method, Accessor accessor,
6264 string prefix)
6265 : base (method, accessor, prefix)
6267 this.method = method;
6268 this.ModFlags = accessor.ModFlags | (method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE));
6270 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
6271 Report.FeatureIsNotAvailable (Location, "access modifiers on properties");
6275 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6277 if (a.IsInternalMethodImplAttribute) {
6278 method.is_external_implementation = true;
6281 base.ApplyAttributeBuilder (a, cb, pa);
6284 public override AttributeTargets AttributeTargets {
6285 get {
6286 return AttributeTargets.Method;
6290 public override bool IsClsComplianceRequired ()
6292 return method.IsClsComplianceRequired ();
6295 public virtual MethodBuilder Define (DeclSpace parent)
6297 CheckForDuplications ();
6299 if (IsDummy) {
6300 if (method.InterfaceType != null && parent.PartialContainer.PendingImplementations != null) {
6301 MethodInfo mi = parent.PartialContainer.PendingImplementations.IsInterfaceMethod (
6302 MethodName.Name, method.InterfaceType, new MethodData (method, ModFlags, flags, this));
6303 if (mi != null) {
6304 Report.SymbolRelatedToPreviousError (mi);
6305 Report.Error (551, Location, "Explicit interface implementation `{0}' is missing accessor `{1}'",
6306 method.GetSignatureForError (), TypeManager.CSharpSignature (mi, true));
6309 return null;
6312 TypeContainer container = parent.PartialContainer;
6315 // Check for custom access modifier
6317 if ((ModFlags & Modifiers.Accessibility) == 0) {
6318 ModFlags |= method.ModFlags;
6319 flags = method.flags;
6320 } else {
6321 if (container.Kind == Kind.Interface)
6322 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
6323 GetSignatureForError ());
6325 if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
6326 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
6329 CheckModifiers (ModFlags);
6330 ModFlags |= (method.ModFlags & (~Modifiers.Accessibility));
6331 ModFlags |= Modifiers.PROPERTY_CUSTOM;
6332 flags = Modifiers.MethodAttr (ModFlags);
6333 flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
6336 CheckAbstractAndExtern (block != null);
6338 if (block != null && block.IsIterator)
6339 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
6341 return null;
6344 public bool HasCustomAccessModifier {
6345 get {
6346 return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
6350 public PropertyBase Property {
6351 get {
6352 return method;
6356 public override EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
6358 return new EmitContext (this,
6359 ds, method.ds, method.Location, ig, ReturnType,
6360 method.ModFlags, false);
6363 public override ObsoleteAttribute GetObsoleteAttribute ()
6365 return method.GetObsoleteAttribute ();
6368 public override string GetSignatureForError()
6370 return method.GetSignatureForError () + '.' + prefix.Substring (0, 3);
6373 void CheckModifiers (int modflags)
6375 modflags &= Modifiers.Accessibility;
6376 int flags = 0;
6377 int mflags = method.ModFlags & Modifiers.Accessibility;
6379 if ((mflags & Modifiers.PUBLIC) != 0) {
6380 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
6382 else if ((mflags & Modifiers.PROTECTED) != 0) {
6383 if ((mflags & Modifiers.INTERNAL) != 0)
6384 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL;
6386 flags |= Modifiers.PRIVATE;
6388 else if ((mflags & Modifiers.INTERNAL) != 0)
6389 flags |= Modifiers.PRIVATE;
6391 if ((mflags == modflags) || (modflags & (~flags)) != 0) {
6392 Report.Error (273, Location,
6393 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
6394 GetSignatureForError (), method.GetSignatureForError ());
6398 protected bool CheckForDuplications ()
6400 if ((caching_flags & Flags.MethodOverloadsExist) == 0)
6401 return true;
6403 return Parent.MemberCache.CheckExistingMembersOverloads (this, Name, ParameterInfo);
6407 public PropertyMethod Get, Set;
6408 public PropertyBuilder PropertyBuilder;
6409 public MethodBuilder GetBuilder, SetBuilder;
6411 protected bool define_set_first = false;
6413 public PropertyBase (DeclSpace parent, FullNamedExpression type, int mod_flags,
6414 int allowed_mod, MemberName name,
6415 Attributes attrs, bool define_set_first)
6416 : base (parent, null, type, mod_flags, allowed_mod, name, attrs)
6418 this.define_set_first = define_set_first;
6421 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6423 if (a.HasSecurityAttribute) {
6424 a.Error_InvalidSecurityParent ();
6425 return;
6428 PropertyBuilder.SetCustomAttribute (cb);
6431 public override AttributeTargets AttributeTargets {
6432 get {
6433 return AttributeTargets.Property;
6437 protected override void DoMemberTypeDependentChecks ()
6439 base.DoMemberTypeDependentChecks ();
6441 IsTypePermitted ();
6442 #if MS_COMPATIBLE
6443 if (MemberType.IsGenericParameter)
6444 return;
6445 #endif
6447 if ((MemberType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
6448 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
6452 protected override void DoMemberTypeIndependentChecks ()
6454 base.DoMemberTypeIndependentChecks ();
6457 // Accessors modifiers check
6459 if ((Get.ModFlags & Modifiers.Accessibility) != 0 &&
6460 (Set.ModFlags & Modifiers.Accessibility) != 0) {
6461 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
6462 GetSignatureForError ());
6465 if ((ModFlags & Modifiers.OVERRIDE) == 0 &&
6466 (Get.IsDummy && (Set.ModFlags & Modifiers.Accessibility) != 0) ||
6467 (Set.IsDummy && (Get.ModFlags & Modifiers.Accessibility) != 0)) {
6468 Report.Error (276, Location,
6469 "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
6470 GetSignatureForError ());
6474 bool DefineGet ()
6476 GetBuilder = Get.Define (Parent);
6477 return (Get.IsDummy) ? true : GetBuilder != null;
6480 bool DefineSet (bool define)
6482 if (!define)
6483 return true;
6485 SetBuilder = Set.Define (Parent);
6486 return (Set.IsDummy) ? true : SetBuilder != null;
6489 protected bool DefineAccessors ()
6491 return DefineSet (define_set_first) &&
6492 DefineGet () &&
6493 DefineSet (!define_set_first);
6496 protected abstract PropertyInfo ResolveBaseProperty ();
6498 // TODO: rename to Resolve......
6499 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
6501 PropertyInfo base_property = ResolveBaseProperty ();
6502 if (base_property == null)
6503 return null;
6505 base_ret_type = base_property.PropertyType;
6506 MethodInfo get_accessor = base_property.GetGetMethod (true);
6507 MethodInfo set_accessor = base_property.GetSetMethod (true);
6508 MethodAttributes get_accessor_access = 0, set_accessor_access = 0;
6511 // Check base property accessors conflict
6513 if ((ModFlags & (Modifiers.OVERRIDE | Modifiers.NEW)) == Modifiers.OVERRIDE) {
6514 if (get_accessor == null) {
6515 if (Get != null && !Get.IsDummy) {
6516 Report.SymbolRelatedToPreviousError (base_property);
6517 Report.Error (545, Location,
6518 "`{0}.get': cannot override because `{1}' does not have an overridable get accessor",
6519 GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6521 } else {
6522 get_accessor_access = get_accessor.Attributes & MethodAttributes.MemberAccessMask;
6524 if (!Get.IsDummy && !CheckAccessModifiers (
6525 Modifiers.MethodAttr (Get.ModFlags) & MethodAttributes.MemberAccessMask, get_accessor_access, get_accessor))
6526 Error_CannotChangeAccessModifiers (Get.Location, get_accessor, get_accessor_access, ".get");
6529 if (set_accessor == null) {
6530 if (Set != null && !Set.IsDummy) {
6531 Report.SymbolRelatedToPreviousError (base_property);
6532 Report.Error (546, Location,
6533 "`{0}.set': cannot override because `{1}' does not have an overridable set accessor",
6534 GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6536 } else {
6537 set_accessor_access = set_accessor.Attributes & MethodAttributes.MemberAccessMask;
6539 if (!Set.IsDummy && !CheckAccessModifiers (
6540 Modifiers.MethodAttr (Set.ModFlags) & MethodAttributes.MemberAccessMask, set_accessor_access, set_accessor))
6541 Error_CannotChangeAccessModifiers (Set.Location, set_accessor, set_accessor_access, ".set");
6545 // When one accessor does not exist and property hides base one
6546 // we need to propagate this upwards
6547 if (set_accessor == null)
6548 set_accessor = get_accessor;
6551 // Get the less restrictive access
6553 return get_accessor_access > set_accessor_access ? get_accessor : set_accessor;
6556 public override void Emit ()
6559 // The PropertyBuilder can be null for explicit implementations, in that
6560 // case, we do not actually emit the ".property", so there is nowhere to
6561 // put the attribute
6563 if (PropertyBuilder != null && OptAttributes != null)
6564 OptAttributes.Emit ();
6566 if (!Get.IsDummy)
6567 Get.Emit (Parent);
6569 if (!Set.IsDummy)
6570 Set.Emit (Parent);
6572 base.Emit ();
6575 /// <summary>
6576 /// Tests whether accessors are not in collision with some method (CS0111)
6577 /// </summary>
6578 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6580 return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
6583 public override bool IsUsed
6585 get {
6586 if (IsExplicitImpl)
6587 return true;
6589 return Get.IsUsed | Set.IsUsed;
6593 protected override void SetMemberName (MemberName new_name)
6595 base.SetMemberName (new_name);
6597 Get.UpdateName (this);
6598 Set.UpdateName (this);
6601 public override string[] ValidAttributeTargets {
6602 get {
6603 return attribute_targets;
6608 // Represents header string for documentation comment.
6610 public override string DocCommentHeader {
6611 get { return "P:"; }
6615 public class Property : PropertyBase
6617 public sealed class BackingField : Field
6619 readonly Property property;
6621 public BackingField (Property p)
6622 : base (p.Parent, p.type_name,
6623 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
6624 new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
6626 this.property = p;
6629 public override string GetSignatureForError ()
6631 return property.GetSignatureForError ();
6635 const int AllowedModifiers =
6636 Modifiers.NEW |
6637 Modifiers.PUBLIC |
6638 Modifiers.PROTECTED |
6639 Modifiers.INTERNAL |
6640 Modifiers.PRIVATE |
6641 Modifiers.STATIC |
6642 Modifiers.SEALED |
6643 Modifiers.OVERRIDE |
6644 Modifiers.ABSTRACT |
6645 Modifiers.UNSAFE |
6646 Modifiers.EXTERN |
6647 Modifiers.VIRTUAL;
6649 const int AllowedInterfaceModifiers =
6650 Modifiers.NEW;
6652 public Property (DeclSpace parent, FullNamedExpression type, int mod,
6653 MemberName name, Attributes attrs, Accessor get_block,
6654 Accessor set_block, bool define_set_first)
6655 : this (parent, type, mod, name, attrs, get_block, set_block,
6656 define_set_first, null)
6660 public Property (DeclSpace parent, FullNamedExpression type, int mod,
6661 MemberName name, Attributes attrs, Accessor get_block,
6662 Accessor set_block, bool define_set_first, Block current_block)
6663 : base (parent, type, mod,
6664 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
6665 name, attrs, define_set_first)
6667 if (get_block == null)
6668 Get = new GetMethod (this);
6669 else
6670 Get = new GetMethod (this, get_block);
6672 if (set_block == null)
6673 Set = new SetMethod (this);
6674 else
6675 Set = new SetMethod (this, set_block);
6677 if (!IsInterface && (mod & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
6678 get_block != null && get_block.Block == null &&
6679 set_block != null && set_block.Block == null) {
6680 if (RootContext.Version <= LanguageVersion.ISO_2)
6681 Report.FeatureIsNotAvailable (Location, "automatically implemented properties");
6683 Get.ModFlags |= Modifiers.COMPILER_GENERATED;
6684 Set.ModFlags |= Modifiers.COMPILER_GENERATED;
6688 void CreateAutomaticProperty ()
6690 // Create backing field
6691 Field field = new BackingField (this);
6692 if (!field.Define ())
6693 return;
6695 Parent.PartialContainer.AddField (field);
6697 FieldExpr fe = new FieldExpr (field.FieldBuilder, Location);
6698 if ((field.ModFlags & Modifiers.STATIC) == 0)
6699 fe.InstanceExpression = new CompilerGeneratedThis (fe.Type, Location);
6701 // Create get block
6702 Get.Block = new ToplevelBlock (ParametersCompiled.EmptyReadOnlyParameters, Location);
6703 Return r = new Return (fe, Location);
6704 Get.Block.AddStatement (r);
6706 // Create set block
6707 Set.Block = new ToplevelBlock (Set.ParameterInfo, Location);
6708 Assign a = new SimpleAssign (fe, new SimpleName ("value", Location));
6709 Set.Block.AddStatement (new StatementExpression (a));
6712 public override bool Define ()
6714 if (!base.Define ())
6715 return false;
6717 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6719 if ((Get.ModFlags & Modifiers.COMPILER_GENERATED) != 0)
6720 CreateAutomaticProperty ();
6722 if (!DefineAccessors ())
6723 return false;
6725 if (!CheckBase ())
6726 return false;
6728 // FIXME - PropertyAttributes.HasDefault ?
6730 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6731 GetFullName (MemberName), PropertyAttributes.None, MemberType, null);
6733 if (!Get.IsDummy) {
6734 PropertyBuilder.SetGetMethod (GetBuilder);
6735 Parent.MemberCache.AddMember (GetBuilder, Get);
6738 if (!Set.IsDummy) {
6739 PropertyBuilder.SetSetMethod (SetBuilder);
6740 Parent.MemberCache.AddMember (SetBuilder, Set);
6743 TypeManager.RegisterProperty (PropertyBuilder, this);
6744 Parent.MemberCache.AddMember (PropertyBuilder, this);
6745 return true;
6748 public override void Emit ()
6750 if (((Set.ModFlags | Get.ModFlags) & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) {
6751 Report.Error (842, Location,
6752 "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
6753 GetSignatureForError ());
6756 base.Emit ();
6759 protected override PropertyInfo ResolveBaseProperty ()
6761 return Parent.PartialContainer.BaseCache.FindMemberToOverride (
6762 Parent.TypeBuilder, Name, ParametersCompiled.EmptyReadOnlyParameters, null, true) as PropertyInfo;
6766 /// </summary>
6767 /// Gigantic workaround for lameness in SRE follows :
6768 /// This class derives from EventInfo and attempts to basically
6769 /// wrap around the EventBuilder so that FindMembers can quickly
6770 /// return this in it search for members
6771 /// </summary>
6772 public class MyEventBuilder : EventInfo {
6775 // We use this to "point" to our Builder which is
6776 // not really a MemberInfo
6778 EventBuilder MyBuilder;
6781 // We "catch" and wrap these methods
6783 MethodInfo raise, remove, add;
6785 EventAttributes attributes;
6786 Type declaring_type, reflected_type, event_type;
6787 string name;
6789 Event my_event;
6791 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
6793 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
6795 // And now store the values in our own fields.
6797 declaring_type = type_builder;
6799 reflected_type = type_builder;
6801 attributes = event_attr;
6802 this.name = name;
6803 my_event = ev;
6804 this.event_type = event_type;
6808 // Methods that you have to override. Note that you only need
6809 // to "implement" the variants that take the argument (those are
6810 // the "abstract" methods, the others (GetAddMethod()) are
6811 // regular.
6813 public override MethodInfo GetAddMethod (bool nonPublic)
6815 return add;
6818 public override MethodInfo GetRemoveMethod (bool nonPublic)
6820 return remove;
6823 public override MethodInfo GetRaiseMethod (bool nonPublic)
6825 return raise;
6829 // These methods make "MyEventInfo" look like a Builder
6831 public void SetRaiseMethod (MethodBuilder raiseMethod)
6833 raise = raiseMethod;
6834 MyBuilder.SetRaiseMethod (raiseMethod);
6837 public void SetRemoveOnMethod (MethodBuilder removeMethod)
6839 remove = removeMethod;
6840 MyBuilder.SetRemoveOnMethod (removeMethod);
6843 public void SetAddOnMethod (MethodBuilder addMethod)
6845 add = addMethod;
6846 MyBuilder.SetAddOnMethod (addMethod);
6849 public void SetCustomAttribute (CustomAttributeBuilder cb)
6851 MyBuilder.SetCustomAttribute (cb);
6854 public override object [] GetCustomAttributes (bool inherit)
6856 // FIXME : There's nothing which can be seemingly done here because
6857 // we have no way of getting at the custom attribute objects of the
6858 // EventBuilder !
6859 return null;
6862 public override object [] GetCustomAttributes (Type t, bool inherit)
6864 // FIXME : Same here !
6865 return null;
6868 public override bool IsDefined (Type t, bool b)
6870 return true;
6873 public override EventAttributes Attributes {
6874 get {
6875 return attributes;
6879 public override string Name {
6880 get {
6881 return name;
6885 public override Type DeclaringType {
6886 get {
6887 return declaring_type;
6891 public override Type ReflectedType {
6892 get {
6893 return reflected_type;
6897 public Type EventType {
6898 get {
6899 return event_type;
6903 public void SetUsed ()
6905 if (my_event != null) {
6906 // my_event.SetAssigned ();
6907 my_event.SetMemberIsUsed ();
6912 /// <summary>
6913 /// For case when event is declared like property (with add and remove accessors).
6914 /// </summary>
6915 public class EventProperty: Event {
6916 abstract class AEventPropertyAccessor : AEventAccessor
6918 protected AEventPropertyAccessor (Event method, Accessor accessor, string prefix):
6919 base (method, accessor, prefix)
6923 public override MethodBuilder Define (DeclSpace ds)
6925 CheckAbstractAndExtern (block != null);
6926 return base.Define (ds);
6929 public override string GetSignatureForError ()
6931 return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1);
6935 sealed class AddDelegateMethod: AEventPropertyAccessor
6937 public AddDelegateMethod (Event method, Accessor accessor):
6938 base (method, accessor, AddPrefix)
6943 sealed class RemoveDelegateMethod: AEventPropertyAccessor
6945 public RemoveDelegateMethod (Event method, Accessor accessor):
6946 base (method, accessor, RemovePrefix)
6952 static readonly string[] attribute_targets = new string [] { "event" }; // "property" target was disabled for 2.0 version
6954 public EventProperty (DeclSpace parent, FullNamedExpression type, int mod_flags,
6955 MemberName name,
6956 Attributes attrs, Accessor add, Accessor remove)
6957 : base (parent, type, mod_flags, name, attrs)
6959 Add = new AddDelegateMethod (this, add);
6960 Remove = new RemoveDelegateMethod (this, remove);
6963 public override bool Define()
6965 if (!base.Define ())
6966 return false;
6968 SetMemberIsUsed ();
6969 return true;
6972 public override string[] ValidAttributeTargets {
6973 get {
6974 return attribute_targets;
6979 /// <summary>
6980 /// Event is declared like field.
6981 /// </summary>
6982 public class EventField : Event {
6983 abstract class EventFieldAccessor : AEventAccessor
6985 protected EventFieldAccessor (Event method, string prefix)
6986 : base (method, prefix)
6990 public override void Emit (DeclSpace parent)
6992 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
6993 if (parent is Class) {
6994 MethodBuilder mb = method_data.MethodBuilder;
6995 mb.SetImplementationFlags (mb.GetMethodImplementationFlags () | MethodImplAttributes.Synchronized);
6998 // TODO: because we cannot use generics yet
6999 FieldInfo field_info = ((EventField) method).BackingField.FieldBuilder;
7000 FieldExpr f_expr = new FieldExpr (field_info, Location);
7001 if ((method.ModFlags & Modifiers.STATIC) == 0)
7002 f_expr.InstanceExpression = new CompilerGeneratedThis (field_info.FieldType, Location);
7004 block = new ToplevelBlock (ParameterInfo, Location);
7005 block.AddStatement (new StatementExpression (
7006 new CompoundAssign (Operation,
7007 f_expr,
7008 block.GetParameterReference (ParameterInfo[0].Name, Location))));
7011 base.Emit (parent);
7014 protected abstract Binary.Operator Operation { get; }
7017 sealed class AddDelegateMethod: EventFieldAccessor
7019 public AddDelegateMethod (Event method):
7020 base (method, AddPrefix)
7024 protected override Binary.Operator Operation {
7025 get { return Binary.Operator.Addition; }
7029 sealed class RemoveDelegateMethod: EventFieldAccessor
7031 public RemoveDelegateMethod (Event method):
7032 base (method, RemovePrefix)
7036 protected override Binary.Operator Operation {
7037 get { return Binary.Operator.Subtraction; }
7042 static readonly string[] attribute_targets = new string [] { "event", "field", "method" };
7043 static readonly string[] attribute_targets_interface = new string[] { "event", "method" };
7045 public Field BackingField;
7046 public Expression Initializer;
7048 public EventField (DeclSpace parent, FullNamedExpression type, int mod_flags, MemberName name, Attributes attrs)
7049 : base (parent, type, mod_flags, name, attrs)
7051 Add = new AddDelegateMethod (this);
7052 Remove = new RemoveDelegateMethod (this);
7055 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
7057 if (a.Target == AttributeTargets.Field) {
7058 BackingField.ApplyAttributeBuilder (a, cb, pa);
7059 return;
7062 if (a.Target == AttributeTargets.Method) {
7063 int errors = Report.Errors;
7064 Add.ApplyAttributeBuilder (a, cb, pa);
7065 if (errors == Report.Errors)
7066 Remove.ApplyAttributeBuilder (a, cb, pa);
7067 return;
7070 base.ApplyAttributeBuilder (a, cb, pa);
7073 public override bool Define()
7075 if (!base.Define ())
7076 return false;
7078 if (Initializer != null && (ModFlags & Modifiers.ABSTRACT) != 0) {
7079 Report.Error (74, Location, "`{0}': abstract event cannot have an initializer",
7080 GetSignatureForError ());
7083 if (!HasBackingField) {
7084 SetMemberIsUsed ();
7085 return true;
7088 // FIXME: We are unable to detect whether generic event is used because
7089 // we are using FieldExpr instead of EventExpr for event access in that
7090 // case. When this issue will be fixed this hack can be removed.
7091 if (TypeManager.IsGenericType (MemberType))
7092 SetMemberIsUsed ();
7094 if (Add.IsInterfaceImplementation)
7095 SetMemberIsUsed ();
7097 TypeManager.RegisterEventField (EventBuilder, this);
7099 BackingField = new Field (Parent,
7100 new TypeExpression (MemberType, Location),
7101 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
7102 MemberName, null);
7104 Parent.PartialContainer.AddField (BackingField);
7105 BackingField.Initializer = Initializer;
7106 BackingField.ModFlags &= ~Modifiers.COMPILER_GENERATED;
7108 // Call define because we passed fields definition
7109 return BackingField.Define ();
7112 bool HasBackingField {
7113 get {
7114 return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0;
7118 public override string[] ValidAttributeTargets
7120 get {
7121 return HasBackingField ? attribute_targets : attribute_targets_interface;
7126 public abstract class Event : PropertyBasedMember {
7127 public abstract class AEventAccessor : AbstractPropertyEventMethod
7129 protected readonly Event method;
7130 ImplicitParameter param_attr;
7132 static readonly string[] attribute_targets = new string [] { "method", "param", "return" };
7134 public const string AddPrefix = "add_";
7135 public const string RemovePrefix = "remove_";
7137 protected AEventAccessor (Event method, string prefix)
7138 : base (method, prefix)
7140 this.method = method;
7141 this.ModFlags = method.ModFlags;
7144 protected AEventAccessor (Event method, Accessor accessor, string prefix)
7145 : base (method, accessor, prefix)
7147 this.method = method;
7148 this.ModFlags = method.ModFlags;
7151 public bool IsInterfaceImplementation {
7152 get { return method_data.implementing != null; }
7155 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
7157 if (a.IsInternalMethodImplAttribute) {
7158 method.is_external_implementation = true;
7161 base.ApplyAttributeBuilder (a, cb, pa);
7164 protected override void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
7166 if (a.Target == AttributeTargets.Parameter) {
7167 if (param_attr == null)
7168 param_attr = new ImplicitParameter (method_data.MethodBuilder);
7170 param_attr.ApplyAttributeBuilder (a, cb, pa);
7171 return;
7174 base.ApplyAttributeBuilder (a, cb, pa);
7177 public override AttributeTargets AttributeTargets {
7178 get {
7179 return AttributeTargets.Method;
7183 public override bool IsClsComplianceRequired ()
7185 return method.IsClsComplianceRequired ();
7188 public virtual MethodBuilder Define (DeclSpace parent)
7190 method_data = new MethodData (method, method.ModFlags,
7191 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
7193 if (!method_data.Define (parent, method.GetFullName (MemberName)))
7194 return null;
7196 MethodBuilder mb = method_data.MethodBuilder;
7197 ParameterInfo.ApplyAttributes (mb);
7198 return mb;
7201 public override Type ReturnType {
7202 get {
7203 return TypeManager.void_type;
7207 public override EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
7209 return new EmitContext (
7210 this, method.Parent, Location, ig, ReturnType,
7211 method.ModFlags, false);
7214 public override ObsoleteAttribute GetObsoleteAttribute ()
7216 return method.GetObsoleteAttribute ();
7219 public override string[] ValidAttributeTargets {
7220 get {
7221 return attribute_targets;
7225 public override ParametersCompiled ParameterInfo {
7226 get {
7227 return method.parameters;
7233 const int AllowedModifiers =
7234 Modifiers.NEW |
7235 Modifiers.PUBLIC |
7236 Modifiers.PROTECTED |
7237 Modifiers.INTERNAL |
7238 Modifiers.PRIVATE |
7239 Modifiers.STATIC |
7240 Modifiers.VIRTUAL |
7241 Modifiers.SEALED |
7242 Modifiers.OVERRIDE |
7243 Modifiers.UNSAFE |
7244 Modifiers.ABSTRACT |
7245 Modifiers.EXTERN;
7247 const int AllowedInterfaceModifiers =
7248 Modifiers.NEW;
7250 public AEventAccessor Add, Remove;
7251 public MyEventBuilder EventBuilder;
7252 public MethodBuilder AddBuilder, RemoveBuilder;
7254 ParametersCompiled parameters;
7256 protected Event (DeclSpace parent, FullNamedExpression type, int mod_flags, MemberName name, Attributes attrs)
7257 : base (parent, null, type, mod_flags,
7258 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
7259 name, attrs)
7263 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
7265 if ((a.HasSecurityAttribute)) {
7266 a.Error_InvalidSecurityParent ();
7267 return;
7270 EventBuilder.SetCustomAttribute (cb);
7273 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
7275 return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
7278 public override AttributeTargets AttributeTargets {
7279 get {
7280 return AttributeTargets.Event;
7284 public override bool Define ()
7286 if (!base.Define ())
7287 return false;
7289 if (!TypeManager.IsDelegateType (MemberType)) {
7290 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
7293 parameters = ParametersCompiled.CreateFullyResolved (
7294 new Parameter (null, "value", Parameter.Modifier.NONE, null, Location), MemberType);
7296 if (!CheckBase ())
7297 return false;
7299 if (TypeManager.delegate_combine_delegate_delegate == null) {
7300 TypeManager.delegate_combine_delegate_delegate = TypeManager.GetPredefinedMethod (
7301 TypeManager.delegate_type, "Combine", Location,
7302 TypeManager.delegate_type, TypeManager.delegate_type);
7304 if (TypeManager.delegate_remove_delegate_delegate == null) {
7305 TypeManager.delegate_remove_delegate_delegate = TypeManager.GetPredefinedMethod (
7306 TypeManager.delegate_type, "Remove", Location,
7307 TypeManager.delegate_type, TypeManager.delegate_type);
7311 // Now define the accessors
7314 AddBuilder = Add.Define (Parent);
7315 if (AddBuilder == null)
7316 return false;
7318 RemoveBuilder = Remove.Define (Parent);
7319 if (RemoveBuilder == null)
7320 return false;
7322 EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, EventAttributes.None, MemberType);
7323 EventBuilder.SetAddOnMethod (AddBuilder);
7324 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
7326 Parent.MemberCache.AddMember (EventBuilder, this);
7327 Parent.MemberCache.AddMember (AddBuilder, Add);
7328 Parent.MemberCache.AddMember (RemoveBuilder, Remove);
7330 return true;
7333 public override void Emit ()
7335 if (OptAttributes != null) {
7336 OptAttributes.Emit ();
7339 Add.Emit (Parent);
7340 Remove.Emit (Parent);
7342 base.Emit ();
7345 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
7347 MethodInfo mi = (MethodInfo) Parent.PartialContainer.BaseCache.FindBaseEvent (
7348 Parent.TypeBuilder, Name);
7350 if (mi == null)
7351 return null;
7353 AParametersCollection pd = TypeManager.GetParameterData (mi);
7354 base_ret_type = pd.Types [0];
7355 return mi;
7359 // Represents header string for documentation comment.
7361 public override string DocCommentHeader {
7362 get { return "E:"; }
7367 public class Indexer : PropertyBase
7369 public class GetIndexerMethod : GetMethod
7371 ParametersCompiled parameters;
7373 public GetIndexerMethod (Indexer method):
7374 base (method)
7376 this.parameters = method.parameters;
7379 public GetIndexerMethod (PropertyBase method, Accessor accessor):
7380 base (method, accessor)
7382 parameters = accessor.Parameters;
7385 public override MethodBuilder Define (DeclSpace parent)
7387 parameters.Resolve (ResolveContext);
7388 return base.Define (parent);
7391 public override bool EnableOverloadChecks (MemberCore overload)
7393 if (base.EnableOverloadChecks (overload)) {
7394 overload.caching_flags |= Flags.MethodOverloadsExist;
7395 return true;
7398 return false;
7401 public override ParametersCompiled ParameterInfo {
7402 get {
7403 return parameters;
7408 public class SetIndexerMethod: SetMethod
7410 public SetIndexerMethod (Indexer method):
7411 base (method)
7413 parameters = ParametersCompiled.MergeGenerated (method.parameters, false, parameters [0], null);
7416 public SetIndexerMethod (PropertyBase method, Accessor accessor):
7417 base (method, accessor)
7419 parameters = method.Get.IsDummy ? accessor.Parameters : accessor.Parameters.Clone ();
7422 public override bool EnableOverloadChecks (MemberCore overload)
7424 if (base.EnableOverloadChecks (overload)) {
7425 overload.caching_flags |= Flags.MethodOverloadsExist;
7426 return true;
7429 return false;
7433 const int AllowedModifiers =
7434 Modifiers.NEW |
7435 Modifiers.PUBLIC |
7436 Modifiers.PROTECTED |
7437 Modifiers.INTERNAL |
7438 Modifiers.PRIVATE |
7439 Modifiers.VIRTUAL |
7440 Modifiers.SEALED |
7441 Modifiers.OVERRIDE |
7442 Modifiers.UNSAFE |
7443 Modifiers.EXTERN |
7444 Modifiers.ABSTRACT;
7446 const int AllowedInterfaceModifiers =
7447 Modifiers.NEW;
7449 public readonly ParametersCompiled parameters;
7451 public Indexer (DeclSpace parent, FullNamedExpression type, MemberName name, int mod,
7452 ParametersCompiled parameters, Attributes attrs,
7453 Accessor get_block, Accessor set_block, bool define_set_first)
7454 : base (parent, type, mod,
7455 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
7456 name, attrs, define_set_first)
7458 this.parameters = parameters;
7460 if (get_block == null)
7461 Get = new GetIndexerMethod (this);
7462 else
7463 Get = new GetIndexerMethod (this, get_block);
7465 if (set_block == null)
7466 Set = new SetIndexerMethod (this);
7467 else
7468 Set = new SetIndexerMethod (this, set_block);
7471 protected override bool CheckForDuplications ()
7473 return Parent.MemberCache.CheckExistingMembersOverloads (this, GetFullName (MemberName), parameters);
7476 public override bool Define ()
7478 if (!base.Define ())
7479 return false;
7481 if (!DefineParameters (parameters))
7482 return false;
7484 if (OptAttributes != null) {
7485 Attribute indexer_attr = OptAttributes.Search (PredefinedAttributes.Get.IndexerName);
7486 if (indexer_attr != null) {
7487 // Remove the attribute from the list because it is not emitted
7488 OptAttributes.Attrs.Remove (indexer_attr);
7490 string name = indexer_attr.GetIndexerAttributeValue ();
7491 if (name == null)
7492 return false;
7494 ShortName = name;
7496 if (IsExplicitImpl) {
7497 Report.Error (415, indexer_attr.Location,
7498 "The `IndexerName' attribute is valid only on an " +
7499 "indexer that is not an explicit interface member declaration");
7500 return false;
7503 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
7504 Report.Error (609, indexer_attr.Location,
7505 "Cannot set the `IndexerName' attribute on an indexer marked override");
7506 return false;
7511 if (InterfaceType != null) {
7512 string base_IndexerName = TypeManager.IndexerPropertyName (InterfaceType);
7513 if (base_IndexerName != Name)
7514 ShortName = base_IndexerName;
7517 if (!Parent.PartialContainer.AddMember (this) ||
7518 !Parent.PartialContainer.AddMember (Get) || !Parent.PartialContainer.AddMember (Set))
7519 return false;
7521 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
7523 if (!DefineAccessors ())
7524 return false;
7526 if (!CheckBase ())
7527 return false;
7530 // Now name the parameters
7532 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
7533 GetFullName (MemberName), PropertyAttributes.None, MemberType, parameters.GetEmitTypes ());
7535 if (!Get.IsDummy) {
7536 PropertyBuilder.SetGetMethod (GetBuilder);
7537 Parent.MemberCache.AddMember (GetBuilder, Get);
7540 if (!Set.IsDummy) {
7541 PropertyBuilder.SetSetMethod (SetBuilder);
7542 Parent.MemberCache.AddMember (SetBuilder, Set);
7545 TypeManager.RegisterIndexer (PropertyBuilder, parameters);
7546 Parent.MemberCache.AddMember (PropertyBuilder, this);
7547 return true;
7550 public override bool EnableOverloadChecks (MemberCore overload)
7552 if (overload is Indexer) {
7553 caching_flags |= Flags.MethodOverloadsExist;
7554 return true;
7557 return base.EnableOverloadChecks (overload);
7560 public override string GetDocCommentName (DeclSpace ds)
7562 return DocUtil.GetMethodDocCommentName (this, parameters, ds);
7565 public override string GetSignatureForError ()
7567 StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
7568 if (MemberName.Left != null) {
7569 sb.Append ('.');
7570 sb.Append (MemberName.Left.GetSignatureForError ());
7573 sb.Append (".this");
7574 sb.Append (parameters.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
7575 return sb.ToString ();
7578 protected override PropertyInfo ResolveBaseProperty ()
7580 return Parent.PartialContainer.BaseCache.FindMemberToOverride (
7581 Parent.TypeBuilder, Name, parameters, null, true) as PropertyInfo;
7584 protected override bool VerifyClsCompliance ()
7586 if (!base.VerifyClsCompliance ())
7587 return false;
7589 parameters.VerifyClsCompliance ();
7590 return true;
7594 public class Operator : MethodOrOperator {
7596 const int AllowedModifiers =
7597 Modifiers.PUBLIC |
7598 Modifiers.UNSAFE |
7599 Modifiers.EXTERN |
7600 Modifiers.STATIC;
7602 public enum OpType : byte {
7604 // Unary operators
7605 LogicalNot,
7606 OnesComplement,
7607 Increment,
7608 Decrement,
7609 True,
7610 False,
7612 // Unary and Binary operators
7613 Addition,
7614 Subtraction,
7616 UnaryPlus,
7617 UnaryNegation,
7619 // Binary operators
7620 Multiply,
7621 Division,
7622 Modulus,
7623 BitwiseAnd,
7624 BitwiseOr,
7625 ExclusiveOr,
7626 LeftShift,
7627 RightShift,
7628 Equality,
7629 Inequality,
7630 GreaterThan,
7631 LessThan,
7632 GreaterThanOrEqual,
7633 LessThanOrEqual,
7635 // Implicit and Explicit
7636 Implicit,
7637 Explicit,
7639 // Just because of enum
7643 public readonly OpType OperatorType;
7645 static readonly string [] [] names;
7647 static Operator ()
7649 names = new string[(int)OpType.TOP][];
7650 names [(int) OpType.LogicalNot] = new string [] { "!", "op_LogicalNot" };
7651 names [(int) OpType.OnesComplement] = new string [] { "~", "op_OnesComplement" };
7652 names [(int) OpType.Increment] = new string [] { "++", "op_Increment" };
7653 names [(int) OpType.Decrement] = new string [] { "--", "op_Decrement" };
7654 names [(int) OpType.True] = new string [] { "true", "op_True" };
7655 names [(int) OpType.False] = new string [] { "false", "op_False" };
7656 names [(int) OpType.Addition] = new string [] { "+", "op_Addition" };
7657 names [(int) OpType.Subtraction] = new string [] { "-", "op_Subtraction" };
7658 names [(int) OpType.UnaryPlus] = new string [] { "+", "op_UnaryPlus" };
7659 names [(int) OpType.UnaryNegation] = new string [] { "-", "op_UnaryNegation" };
7660 names [(int) OpType.Multiply] = new string [] { "*", "op_Multiply" };
7661 names [(int) OpType.Division] = new string [] { "/", "op_Division" };
7662 names [(int) OpType.Modulus] = new string [] { "%", "op_Modulus" };
7663 names [(int) OpType.BitwiseAnd] = new string [] { "&", "op_BitwiseAnd" };
7664 names [(int) OpType.BitwiseOr] = new string [] { "|", "op_BitwiseOr" };
7665 names [(int) OpType.ExclusiveOr] = new string [] { "^", "op_ExclusiveOr" };
7666 names [(int) OpType.LeftShift] = new string [] { "<<", "op_LeftShift" };
7667 names [(int) OpType.RightShift] = new string [] { ">>", "op_RightShift" };
7668 names [(int) OpType.Equality] = new string [] { "==", "op_Equality" };
7669 names [(int) OpType.Inequality] = new string [] { "!=", "op_Inequality" };
7670 names [(int) OpType.GreaterThan] = new string [] { ">", "op_GreaterThan" };
7671 names [(int) OpType.LessThan] = new string [] { "<", "op_LessThan" };
7672 names [(int) OpType.GreaterThanOrEqual] = new string [] { ">=", "op_GreaterThanOrEqual" };
7673 names [(int) OpType.LessThanOrEqual] = new string [] { "<=", "op_LessThanOrEqual" };
7674 names [(int) OpType.Implicit] = new string [] { "implicit", "op_Implicit" };
7675 names [(int) OpType.Explicit] = new string [] { "explicit", "op_Explicit" };
7678 public Operator (DeclSpace parent, OpType type, FullNamedExpression ret_type,
7679 int mod_flags, ParametersCompiled parameters,
7680 ToplevelBlock block, Attributes attrs, Location loc)
7681 : base (parent, null, ret_type, mod_flags, AllowedModifiers,
7682 new MemberName (GetMetadataName (type), loc), attrs, parameters)
7684 OperatorType = type;
7685 Block = block;
7688 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
7690 if (a.Type == pa.Conditional) {
7691 Error_ConditionalAttributeIsNotValid ();
7692 return;
7695 base.ApplyAttributeBuilder (a, cb, pa);
7698 public override bool Define ()
7700 const int RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
7701 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
7702 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
7705 if (!base.Define ())
7706 return false;
7708 // imlicit and explicit operator of same types are not allowed
7709 if (OperatorType == OpType.Explicit)
7710 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Implicit), Parameters);
7711 else if (OperatorType == OpType.Implicit)
7712 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Explicit), Parameters);
7714 Type declaring_type = MethodData.DeclaringType;
7715 Type return_type = MemberType;
7716 Type first_arg_type = ParameterTypes [0];
7718 Type first_arg_type_unwrap = first_arg_type;
7719 if (TypeManager.IsNullableType (first_arg_type))
7720 first_arg_type_unwrap = TypeManager.GetTypeArguments (first_arg_type) [0];
7722 Type return_type_unwrap = return_type;
7723 if (TypeManager.IsNullableType (return_type))
7724 return_type_unwrap = TypeManager.GetTypeArguments (return_type) [0];
7727 // Rules for conversion operators
7729 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7730 if (first_arg_type_unwrap == return_type_unwrap && first_arg_type_unwrap == declaring_type){
7731 Report.Error (555, Location,
7732 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
7733 return false;
7736 Type conv_type;
7737 if (TypeManager.IsEqual (declaring_type, return_type) || declaring_type == return_type_unwrap) {
7738 conv_type = first_arg_type;
7739 } else if (TypeManager.IsEqual (declaring_type, first_arg_type) || declaring_type == first_arg_type_unwrap) {
7740 conv_type = return_type;
7741 } else {
7742 Report.Error (556, Location,
7743 "User-defined conversion must convert to or from the enclosing type");
7744 return false;
7748 // Because IsInterface and IsClass are not supported
7750 if (!TypeManager.IsGenericParameter (conv_type)) {
7751 if (conv_type.IsInterface) {
7752 Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
7753 GetSignatureForError ());
7754 return false;
7757 if (conv_type.IsClass) {
7758 if (TypeManager.IsSubclassOf (declaring_type, conv_type)) {
7759 Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from a base class",
7760 GetSignatureForError ());
7761 return false;
7764 if (TypeManager.IsSubclassOf (conv_type, declaring_type)) {
7765 Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from a derived class",
7766 GetSignatureForError ());
7767 return false;
7771 } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
7772 if (first_arg_type != declaring_type || Parameters.Types [1] != TypeManager.int32_type) {
7773 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");
7774 return false;
7776 } else if (Parameters.Count == 1) {
7777 // Checks for Unary operators
7779 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
7780 if (return_type != declaring_type && !TypeManager.IsSubclassOf (return_type, declaring_type)) {
7781 Report.Error (448, Location,
7782 "The return type for ++ or -- operator must be the containing type or derived from the containing type");
7783 return false;
7785 if (first_arg_type != declaring_type) {
7786 Report.Error (
7787 559, Location, "The parameter type for ++ or -- operator must be the containing type");
7788 return false;
7792 if (!TypeManager.IsEqual (first_arg_type_unwrap, declaring_type)){
7793 Report.Error (562, Location,
7794 "The parameter type of a unary operator must be the containing type");
7795 return false;
7798 if (OperatorType == OpType.True || OperatorType == OpType.False) {
7799 if (return_type != TypeManager.bool_type){
7800 Report.Error (
7801 215, Location,
7802 "The return type of operator True or False " +
7803 "must be bool");
7804 return false;
7808 } else {
7809 // Checks for Binary operators
7811 if (first_arg_type != declaring_type &&
7812 Parameters.Types [1] != declaring_type){
7813 Report.Error (
7814 563, Location,
7815 "One of the parameters of a binary operator must " +
7816 "be the containing type");
7817 return false;
7821 return true;
7824 protected override bool ResolveMemberType ()
7826 if (!base.ResolveMemberType ())
7827 return false;
7829 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
7830 return true;
7833 // Operator cannot be override
7834 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
7836 return null;
7839 public static string GetName (OpType ot)
7841 return names [(int) ot] [0];
7844 public static string GetName (string metadata_name)
7846 for (int i = 0; i < names.Length; ++i) {
7847 if (names [i] [1] == metadata_name)
7848 return names [i] [0];
7850 return null;
7853 public static string GetMetadataName (OpType ot)
7855 return names [(int) ot] [1];
7858 public static string GetMetadataName (string name)
7860 for (int i = 0; i < names.Length; ++i) {
7861 if (names [i] [0] == name)
7862 return names [i] [1];
7864 return null;
7867 public OpType GetMatchingOperator ()
7869 switch (OperatorType) {
7870 case OpType.Equality:
7871 return OpType.Inequality;
7872 case OpType.Inequality:
7873 return OpType.Equality;
7874 case OpType.True:
7875 return OpType.False;
7876 case OpType.False:
7877 return OpType.True;
7878 case OpType.GreaterThan:
7879 return OpType.LessThan;
7880 case OpType.LessThan:
7881 return OpType.GreaterThan;
7882 case OpType.GreaterThanOrEqual:
7883 return OpType.LessThanOrEqual;
7884 case OpType.LessThanOrEqual:
7885 return OpType.GreaterThanOrEqual;
7886 default:
7887 return OpType.TOP;
7891 public override string GetSignatureForError ()
7893 StringBuilder sb = new StringBuilder ();
7894 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7895 sb.AppendFormat ("{0}.{1} operator {2}",
7896 Parent.GetSignatureForError (), GetName (OperatorType), type_name.GetSignatureForError ());
7898 else {
7899 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
7902 sb.Append (Parameters.GetSignatureForError ());
7903 return sb.ToString ();
7908 // This is used to compare method signatures
7910 struct MethodSignature {
7911 public string Name;
7912 public Type RetType;
7913 public Type [] Parameters;
7915 /// <summary>
7916 /// This delegate is used to extract methods which have the
7917 /// same signature as the argument
7918 /// </summary>
7919 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
7921 public MethodSignature (string name, Type ret_type, Type [] parameters)
7923 Name = name;
7924 RetType = ret_type;
7926 if (parameters == null)
7927 Parameters = Type.EmptyTypes;
7928 else
7929 Parameters = parameters;
7932 public override string ToString ()
7934 string pars = "";
7935 if (Parameters.Length != 0){
7936 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
7937 for (int i = 0; i < Parameters.Length; i++){
7938 sb.Append (Parameters [i]);
7939 if (i+1 < Parameters.Length)
7940 sb.Append (", ");
7942 pars = sb.ToString ();
7945 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
7948 public override int GetHashCode ()
7950 return Name.GetHashCode ();
7953 public override bool Equals (Object o)
7955 MethodSignature other = (MethodSignature) o;
7957 if (other.Name != Name)
7958 return false;
7960 if (other.RetType != RetType)
7961 return false;
7963 if (Parameters == null){
7964 if (other.Parameters == null)
7965 return true;
7966 return false;
7969 if (other.Parameters == null)
7970 return false;
7972 int c = Parameters.Length;
7973 if (other.Parameters.Length != c)
7974 return false;
7976 for (int i = 0; i < c; i++)
7977 if (other.Parameters [i] != Parameters [i])
7978 return false;
7980 return true;
7983 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
7985 MethodSignature sig = (MethodSignature) filter_criteria;
7987 if (m.Name != sig.Name)
7988 return false;
7990 Type ReturnType;
7991 MethodInfo mi = m as MethodInfo;
7992 PropertyInfo pi = m as PropertyInfo;
7994 if (mi != null)
7995 ReturnType = mi.ReturnType;
7996 else if (pi != null)
7997 ReturnType = pi.PropertyType;
7998 else
7999 return false;
8002 // we use sig.RetType == null to mean `do not check the
8003 // method return value.
8005 if (sig.RetType != null) {
8006 if (!TypeManager.IsEqual (ReturnType, sig.RetType))
8007 return false;
8010 Type [] args;
8011 if (mi != null)
8012 args = TypeManager.GetParameterData (mi).Types;
8013 else
8014 args = TypeManager.GetParameterData (pi).Types;
8015 Type [] sigp = sig.Parameters;
8017 if (args.Length != sigp.Length)
8018 return false;
8020 for (int i = args.Length - 1; i >= 0; i--)
8021 if (!TypeManager.IsEqual (args [i], sigp [i]))
8022 return false;
8024 return true;