monotouch uses the real HttpWebRequest
[mcs.git] / mcs / class.cs
blob58dd13113a6f3fa6da4f55b3d9c5811563f17981
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 if (fne_resolved is DynamicTypeExpr)
826 Report.Error (1965, Location, "Class `{0}' cannot derive from dynamic type",
827 GetSignatureForError ());
828 else
829 base_class = fne_resolved;
830 continue;
833 if (ifaces == null)
834 ifaces = new TypeExpr [count - i];
836 if (fne_resolved.Type.IsInterface) {
837 for (int ii = 0; ii < j; ++ii) {
838 if (TypeManager.IsEqual (fne_resolved.Type, ifaces [ii].Type)) {
839 Report.Error (528, Location, "`{0}' is already listed in interface list",
840 fne_resolved.GetSignatureForError ());
841 break;
845 if (Kind == Kind.Interface && !IsAccessibleAs (fne_resolved.Type)) {
846 Report.Error (61, fne.Location,
847 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
848 fne_resolved.GetSignatureForError (), GetSignatureForError ());
850 } else {
851 Report.SymbolRelatedToPreviousError (fne_resolved.Type);
852 if (Kind != Kind.Class) {
853 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
854 } else if (base_class != null)
855 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
856 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
857 else {
858 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
859 GetSignatureForError (), fne_resolved.GetSignatureForError ());
863 ifaces [j++] = fne_resolved;
866 return ifaces;
869 TypeExpr[] GetNormalPartialBases (ref TypeExpr base_class)
871 ArrayList ifaces = new ArrayList (0);
872 if (iface_exprs != null)
873 ifaces.AddRange (iface_exprs);
875 foreach (TypeContainer part in partial_parts) {
876 TypeExpr new_base_class;
877 TypeExpr[] new_ifaces = part.ResolveBaseTypes (out new_base_class);
878 if (new_base_class != TypeManager.system_object_expr) {
879 if (base_class == TypeManager.system_object_expr)
880 base_class = new_base_class;
881 else {
882 if (new_base_class != null && !new_base_class.Equals (base_class)) {
883 Report.SymbolRelatedToPreviousError (base_class.Location, "");
884 Report.Error (263, part.Location,
885 "Partial declarations of `{0}' must not specify different base classes",
886 part.GetSignatureForError ());
888 return null;
893 if (new_ifaces == null)
894 continue;
896 foreach (TypeExpr iface in new_ifaces) {
897 if (ifaces.Contains (iface))
898 continue;
900 ifaces.Add (iface);
904 if (ifaces.Count == 0)
905 return null;
907 return (TypeExpr[])ifaces.ToArray (typeof (TypeExpr));
910 bool CheckGenericInterfaces (Type[] ifaces)
912 #if GMCS_SOURCE
913 ArrayList already_checked = new ArrayList ();
915 for (int i = 0; i < ifaces.Length; i++) {
916 Type iface = ifaces [i];
917 foreach (Type t in already_checked) {
918 if (iface == t)
919 continue;
921 Type[] inferred = new Type [CountTypeParameters];
922 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t, inferred, null))
923 continue;
925 Report.Error (695, Location,
926 "`{0}' cannot implement both `{1}' and `{2}' " +
927 "because they may unify for some type parameter substitutions",
928 TypeManager.CSharpName (TypeBuilder), TypeManager.CSharpName (iface),
929 TypeManager.CSharpName (t));
930 return false;
933 already_checked.Add (iface);
935 #endif
937 return true;
940 bool error = false;
942 bool CreateTypeBuilder ()
944 try {
945 Type default_parent = null;
946 if (Kind == Kind.Struct)
947 default_parent = TypeManager.value_type;
948 else if (Kind == Kind.Enum)
949 default_parent = TypeManager.enum_type;
952 // Sets .size to 1 for structs with no instance fields
954 int type_size = Kind == Kind.Struct && first_nonstatic_field == null ? 1 : 0;
956 if (IsTopLevel){
957 if (TypeManager.NamespaceClash (Name, Location)) {
958 return false;
961 ModuleBuilder builder = Module.Builder;
962 TypeBuilder = builder.DefineType (
963 Name, TypeAttr, default_parent, type_size);
964 } else {
965 TypeBuilder builder = Parent.TypeBuilder;
967 TypeBuilder = builder.DefineNestedType (
968 Basename, TypeAttr, default_parent, type_size);
970 } catch (ArgumentException) {
971 Report.RuntimeMissingSupport (Location, "static classes");
972 return false;
975 TypeManager.AddUserType (this);
977 if (IsGeneric) {
978 string[] param_names = new string [TypeParameters.Length];
979 for (int i = 0; i < TypeParameters.Length; i++)
980 param_names [i] = TypeParameters [i].Name;
982 #if GMCS_SOURCE
983 GenericTypeParameterBuilder[] gen_params = TypeBuilder.DefineGenericParameters (param_names);
985 int offset = CountTypeParameters - CurrentTypeParameters.Length;
986 if (offset > 0) {
987 nested_gen_params = new GenericTypeParameterBuilder [offset];
988 Array.Copy (gen_params, nested_gen_params, offset);
991 for (int i = offset; i < gen_params.Length; i++)
992 CurrentTypeParameters [i - offset].Define (gen_params [i]);
993 #else
994 nested_gen_params = null;
995 throw new NotSupportedException ();
996 #endif
999 return true;
1002 bool DefineBaseTypes ()
1004 iface_exprs = ResolveBaseTypes (out base_type);
1005 if (partial_parts != null) {
1006 iface_exprs = GetNormalPartialBases (ref base_type);
1010 // GetClassBases calls ResolveBaseTypeExpr() on the various type expressions involved,
1011 // which in turn should have called DefineType()s on base types if necessary.
1013 // None of the code below should trigger DefineType()s on classes that we depend on.
1014 // Thus, we are eligible to be on the topological sort `type_container_resolve_order'.
1016 // Let's do it as soon as possible, since code below can call DefineType() on classes
1017 // that depend on us to be populated before they are.
1019 if (!(this is CompilerGeneratedClass))
1020 RootContext.RegisterOrder (this);
1022 if (!CheckRecursiveDefinition (this))
1023 return false;
1025 if (base_type != null && base_type.Type != null) {
1026 TypeBuilder.SetParent (base_type.Type);
1029 // add interfaces that were not added at type creation
1030 if (iface_exprs != null) {
1031 ifaces = TypeManager.ExpandInterfaces (iface_exprs);
1032 if (ifaces == null)
1033 return false;
1035 foreach (Type itype in ifaces)
1036 TypeBuilder.AddInterfaceImplementation (itype);
1038 if (!CheckGenericInterfaces (ifaces))
1039 return false;
1041 TypeManager.RegisterBuilder (TypeBuilder, ifaces);
1044 return true;
1048 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1050 public TypeBuilder CreateType ()
1052 if (TypeBuilder != null)
1053 return TypeBuilder;
1055 if (error)
1056 return null;
1058 if (!CreateTypeBuilder ()) {
1059 error = true;
1060 return null;
1063 if (partial_parts != null) {
1064 foreach (TypeContainer part in partial_parts)
1065 part.TypeBuilder = TypeBuilder;
1068 if (Types != null) {
1069 foreach (TypeContainer tc in Types) {
1070 if (tc.CreateType () == null) {
1071 error = true;
1072 return null;
1077 return TypeBuilder;
1080 bool type_defined;
1082 public override TypeBuilder DefineType ()
1084 if (error)
1085 return null;
1086 if (type_defined)
1087 return TypeBuilder;
1089 type_defined = true;
1091 if (CreateType () == null) {
1092 error = true;
1093 return null;
1096 if (!DefineBaseTypes ()) {
1097 error = true;
1098 return null;
1101 if (!DefineNestedTypes ()) {
1102 error = true;
1103 return null;
1106 return TypeBuilder;
1109 public override void SetParameterInfo (ArrayList constraints_list)
1111 base.SetParameterInfo (constraints_list);
1113 if (!is_generic || PartialContainer == this)
1114 return;
1116 TypeParameter[] tc_names = PartialContainer.TypeParameters;
1117 for (int i = 0; i < tc_names.Length; ++i) {
1118 if (tc_names [i].Name != type_params [i].Name) {
1119 Report.SymbolRelatedToPreviousError (PartialContainer.Location, "");
1120 Report.Error (264, Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
1121 GetSignatureForError ());
1122 break;
1127 void UpdateTypeParameterConstraints (TypeContainer part)
1129 TypeParameter[] current_params = CurrentTypeParameters;
1130 for (int i = 0; i < current_params.Length; i++) {
1131 Constraints c = part.CurrentTypeParameters [i].Constraints;
1132 if (c == null)
1133 continue;
1135 if (current_params [i].UpdateConstraints (part, c))
1136 continue;
1138 Report.SymbolRelatedToPreviousError (Location, "");
1139 Report.Error (265, part.Location,
1140 "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'",
1141 GetSignatureForError (), current_params [i].GetSignatureForError ());
1145 public bool ResolveType ()
1147 if (!DoResolveType ())
1148 return false;
1150 if (compiler_generated != null) {
1151 foreach (CompilerGeneratedClass c in compiler_generated)
1152 if (!c.ResolveType ())
1153 return false;
1156 return true;
1159 protected virtual bool DoResolveType ()
1161 if (!IsGeneric)
1162 return true;
1164 if (PartialContainer != this)
1165 throw new InternalErrorException ();
1167 TypeExpr current_type = null;
1169 foreach (TypeParameter type_param in CurrentTypeParameters) {
1170 if (!type_param.Resolve (this)) {
1171 error = true;
1172 return false;
1176 if (partial_parts != null && is_generic) {
1177 foreach (TypeContainer part in partial_parts)
1178 UpdateTypeParameterConstraints (part);
1181 for (int i = 0; i < TypeParameters.Length; ++i) {
1183 // FIXME: Same should be done for delegates
1184 // TODO: Quite ugly way how to propagate constraints to
1185 // nested types
1187 if (nested_gen_params != null && i < nested_gen_params.Length) {
1188 TypeParameters [i].SetConstraints (nested_gen_params [i]);
1189 } else {
1190 if (!TypeParameters [i].DefineType (this)) {
1191 error = true;
1192 return false;
1197 // TODO: Very strange, why not simple make generic type from
1198 // current type parameters
1199 current_type = new GenericTypeExpr (this, Location);
1200 current_type = current_type.ResolveAsTypeTerminal (this, false);
1201 if (current_type == null) {
1202 error = true;
1203 return false;
1206 CurrentType = current_type.Type;
1207 return true;
1210 protected virtual bool DefineNestedTypes ()
1212 if (Types != null) {
1213 foreach (TypeContainer tc in Types)
1214 if (tc.DefineType () == null)
1215 return false;
1218 if (Delegates != null) {
1219 foreach (Delegate d in Delegates)
1220 if (d.DefineType () == null)
1221 return false;
1224 return true;
1227 TypeContainer InTransit;
1229 protected bool CheckRecursiveDefinition (TypeContainer tc)
1231 if (InTransit != null) {
1232 Report.SymbolRelatedToPreviousError (this);
1233 if (this is Interface)
1234 Report.Error (
1235 529, tc.Location, "Inherited interface `{0}' causes a " +
1236 "cycle in the interface hierarchy of `{1}'",
1237 GetSignatureForError (), tc.GetSignatureForError ());
1238 else
1239 Report.Error (
1240 146, tc.Location, "Circular base class dependency " +
1241 "involving `{0}' and `{1}'",
1242 tc.GetSignatureForError (), GetSignatureForError ());
1243 return false;
1246 InTransit = tc;
1248 if (base_type != null && base_type.Type != null) {
1249 Type t = TypeManager.DropGenericTypeArguments (base_type.Type);
1250 TypeContainer ptc = TypeManager.LookupTypeContainer (t);
1251 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1252 return false;
1255 if (iface_exprs != null) {
1256 foreach (TypeExpr iface in iface_exprs) {
1257 Type itype = TypeManager.DropGenericTypeArguments (iface.Type);
1258 TypeContainer ptc = TypeManager.LookupTypeContainer (itype);
1259 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1260 return false;
1264 if (!IsTopLevel && !Parent.PartialContainer.CheckRecursiveDefinition (this))
1265 return false;
1267 InTransit = null;
1268 return true;
1271 /// <summary>
1272 /// Populates our TypeBuilder with fields and methods
1273 /// </summary>
1274 public override bool Define ()
1276 if (members_defined)
1277 return members_defined_ok;
1279 members_defined_ok = DoDefineMembers ();
1280 members_defined = true;
1282 return members_defined_ok;
1285 protected virtual bool DoDefineMembers ()
1287 if (iface_exprs != null) {
1288 foreach (TypeExpr iface in iface_exprs) {
1289 ObsoleteAttribute oa = AttributeTester.GetObsoleteAttribute (iface.Type);
1290 if ((oa != null) && !IsInObsoleteScope)
1291 AttributeTester.Report_ObsoleteMessage (
1292 oa, iface.GetSignatureForError (), Location);
1294 GenericTypeExpr ct = iface as GenericTypeExpr;
1295 if (ct != null) {
1296 // TODO: passing `this' is wrong, should be base type iface instead
1297 TypeManager.CheckTypeVariance (ct.Type, Variance.Covariant, this);
1299 if (!ct.CheckConstraints (this))
1300 return false;
1305 if (base_type != null) {
1306 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (base_type.Type);
1307 if (obsolete_attr != null && !IsInObsoleteScope)
1308 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), Location);
1310 GenericTypeExpr ct = base_type as GenericTypeExpr;
1311 if ((ct != null) && !ct.CheckConstraints (this))
1312 return false;
1314 TypeContainer baseContainer = TypeManager.LookupTypeContainer(base_type.Type);
1315 if (baseContainer != null)
1316 baseContainer.Define();
1318 member_cache = new MemberCache (base_type.Type, this);
1319 } else if (Kind == Kind.Interface) {
1320 member_cache = new MemberCache (null, this);
1321 Type [] ifaces = TypeManager.GetInterfaces (TypeBuilder);
1322 for (int i = 0; i < ifaces.Length; ++i)
1323 member_cache.AddInterface (TypeManager.LookupMemberCache (ifaces [i]));
1324 } else {
1325 member_cache = new MemberCache (null, this);
1328 if (types != null)
1329 foreach (TypeContainer tc in types)
1330 member_cache.AddNestedType (tc);
1332 if (delegates != null)
1333 foreach (Delegate d in delegates)
1334 member_cache.AddNestedType (d);
1336 if (partial_parts != null) {
1337 foreach (TypeContainer part in partial_parts)
1338 part.member_cache = member_cache;
1341 if (!IsTopLevel) {
1342 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Basename, false);
1343 if (conflict_symbol == null) {
1344 if ((ModFlags & Modifiers.NEW) != 0)
1345 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
1346 } else {
1347 if ((ModFlags & Modifiers.NEW) == 0) {
1348 Report.SymbolRelatedToPreviousError (conflict_symbol);
1349 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
1350 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
1355 DefineContainerMembers (constants);
1356 DefineContainerMembers (fields);
1358 if (Kind == Kind.Struct || Kind == Kind.Class) {
1359 pending = PendingImplementation.GetPendingImplementations (this);
1361 if (requires_delayed_unmanagedtype_check) {
1362 requires_delayed_unmanagedtype_check = false;
1363 foreach (FieldBase f in fields) {
1364 if (f.MemberType != null && f.MemberType.IsPointer)
1365 TypeManager.VerifyUnManaged (f.MemberType, f.Location);
1371 // Constructors are not in the defined_names array
1373 DefineContainerMembers (instance_constructors);
1375 DefineContainerMembers (events);
1376 DefineContainerMembers (ordered_explicit_member_list);
1377 DefineContainerMembers (ordered_member_list);
1379 DefineContainerMembers (operators);
1380 DefineContainerMembers (delegates);
1382 ComputeIndexerName();
1383 CheckEqualsAndGetHashCode();
1385 if (CurrentType != null) {
1386 GenericType = CurrentType;
1390 // FIXME: This hack is needed because member cache does not work
1391 // with generic types, we rely on runtime to inflate dynamic types.
1392 // TODO: This hack requires member cache refactoring to be removed
1394 if (TypeManager.IsGenericType (TypeBuilder))
1395 member_cache = new MemberCache (this);
1397 return true;
1400 protected virtual void DefineContainerMembers (MemberCoreArrayList mcal)
1402 if (mcal != null)
1403 mcal.DefineContainerMembers ();
1406 protected virtual void ComputeIndexerName ()
1408 if (indexers == null)
1409 return;
1411 string class_indexer_name = null;
1414 // If there's both an explicit and an implicit interface implementation, the
1415 // explicit one actually implements the interface while the other one is just
1416 // a normal indexer. See bug #37714.
1419 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
1420 foreach (Indexer i in indexers) {
1421 if (i.InterfaceType != null) {
1422 if (seen_normal_indexers)
1423 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
1424 continue;
1427 seen_normal_indexers = true;
1429 if (class_indexer_name == null) {
1430 class_indexer_name = i.ShortName;
1431 continue;
1434 if (i.ShortName != class_indexer_name)
1435 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");
1438 if (class_indexer_name != null)
1439 indexer_name = class_indexer_name;
1442 protected virtual void EmitIndexerName ()
1444 if (!seen_normal_indexers)
1445 return;
1447 PredefinedAttribute pa = PredefinedAttributes.Get.DefaultMember;
1448 if (pa.Constructor == null &&
1449 !pa.ResolveConstructor (Location, TypeManager.string_type))
1450 return;
1452 CustomAttributeBuilder cb = new CustomAttributeBuilder (pa.Constructor, new string [] { IndexerName });
1453 TypeBuilder.SetCustomAttribute (cb);
1456 protected virtual void CheckEqualsAndGetHashCode ()
1458 if (methods == null)
1459 return;
1461 if (HasEquals && !HasGetHashCode) {
1462 Report.Warning (659, 3, this.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", this.GetSignatureForError ());
1466 public MemberInfo FindBaseMemberWithSameName (string name, bool ignore_methods)
1468 return BaseCache == null ? null : BaseCache.FindMemberWithSameName (name, ignore_methods, null);
1471 /// <summary>
1472 /// This function is based by a delegate to the FindMembers routine
1473 /// </summary>
1474 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1476 return true;
1479 /// <summary>
1480 /// This filter is used by FindMembers, and we just keep
1481 /// a global for the filter to `AlwaysAccept'
1482 /// </summary>
1483 static MemberFilter accepting_filter;
1486 static TypeContainer ()
1488 accepting_filter = new MemberFilter (AlwaysAccept);
1491 public MethodInfo[] GetMethods ()
1493 ArrayList members = new ArrayList ();
1495 Define ();
1497 if (methods != null) {
1498 int len = methods.Count;
1499 for (int i = 0; i < len; i++) {
1500 Method m = (Method) methods [i];
1502 members.Add (m.MethodBuilder);
1506 if (operators != null) {
1507 int len = operators.Count;
1508 for (int i = 0; i < len; i++) {
1509 Operator o = (Operator) operators [i];
1511 members.Add (o.MethodBuilder);
1515 if (properties != null) {
1516 int len = properties.Count;
1517 for (int i = 0; i < len; i++) {
1518 Property p = (Property) properties [i];
1520 if (p.GetBuilder != null)
1521 members.Add (p.GetBuilder);
1522 if (p.SetBuilder != null)
1523 members.Add (p.SetBuilder);
1527 if (indexers != null) {
1528 int len = indexers.Count;
1529 for (int i = 0; i < len; i++) {
1530 Indexer ix = (Indexer) indexers [i];
1532 if (ix.GetBuilder != null)
1533 members.Add (ix.GetBuilder);
1534 if (ix.SetBuilder != null)
1535 members.Add (ix.SetBuilder);
1539 if (events != null) {
1540 int len = events.Count;
1541 for (int i = 0; i < len; i++) {
1542 Event e = (Event) events [i];
1544 if (e.AddBuilder != null)
1545 members.Add (e.AddBuilder);
1546 if (e.RemoveBuilder != null)
1547 members.Add (e.RemoveBuilder);
1551 MethodInfo[] retMethods = new MethodInfo [members.Count];
1552 members.CopyTo (retMethods, 0);
1553 return retMethods;
1556 // Indicated whether container has StructLayout attribute set Explicit
1557 public bool HasExplicitLayout {
1558 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
1559 set { caching_flags |= Flags.HasExplicitLayout; }
1562 public bool HasStructLayout {
1563 get { return (caching_flags & Flags.HasStructLayout) != 0; }
1564 set { caching_flags |= Flags.HasStructLayout; }
1568 // Return the nested type with name @name. Ensures that the nested type
1569 // is defined if necessary. Do _not_ use this when you have a MemberCache handy.
1571 public Type FindNestedType (string name)
1573 if (PartialContainer != this)
1574 throw new InternalErrorException ("should not happen");
1576 ArrayList [] lists = { types, delegates };
1578 for (int j = 0; j < lists.Length; ++j) {
1579 ArrayList list = lists [j];
1580 if (list == null)
1581 continue;
1583 int len = list.Count;
1584 for (int i = 0; i < len; ++i) {
1585 DeclSpace ds = (DeclSpace) list [i];
1586 if (ds.Basename == name) {
1587 return ds.DefineType ();
1592 return null;
1595 private void FindMembers_NestedTypes (int modflags,
1596 BindingFlags bf, MemberFilter filter, object criteria,
1597 ref ArrayList members)
1599 ArrayList [] lists = { types, delegates };
1601 for (int j = 0; j < lists.Length; ++j) {
1602 ArrayList list = lists [j];
1603 if (list == null)
1604 continue;
1606 int len = list.Count;
1607 for (int i = 0; i < len; i++) {
1608 DeclSpace ds = (DeclSpace) list [i];
1610 if ((ds.ModFlags & modflags) == 0)
1611 continue;
1613 TypeBuilder tb = ds.TypeBuilder;
1614 if (tb == null) {
1615 if (!(criteria is string) || ds.Basename.Equals (criteria))
1616 tb = ds.DefineType ();
1619 if (tb != null && (filter (tb, criteria) == true)) {
1620 if (members == null)
1621 members = new ArrayList ();
1623 members.Add (tb);
1629 /// <summary>
1630 /// This method returns the members of this type just like Type.FindMembers would
1631 /// Only, we need to use this for types which are _being_ defined because MS'
1632 /// implementation can't take care of that.
1633 /// </summary>
1635 // FIXME: return an empty static array instead of null, that cleans up
1636 // some code and is consistent with some coding conventions I just found
1637 // out existed ;-)
1640 // Notice that in various cases we check if our field is non-null,
1641 // something that would normally mean that there was a bug elsewhere.
1643 // The problem happens while we are defining p-invoke methods, as those
1644 // will trigger a FindMembers, but this happens before things are defined
1646 // Since the whole process is a no-op, it is fine to check for null here.
1648 // TODO: This approach will be one day completely removed, it's already
1649 // used at few places only
1652 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1653 MemberFilter filter, object criteria)
1655 ArrayList members = null;
1657 int modflags = 0;
1658 if ((bf & BindingFlags.Public) != 0)
1659 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1660 Modifiers.INTERNAL;
1661 if ((bf & BindingFlags.NonPublic) != 0)
1662 modflags |= Modifiers.PRIVATE;
1664 int static_mask = 0, static_flags = 0;
1665 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1666 case BindingFlags.Static:
1667 static_mask = static_flags = Modifiers.STATIC;
1668 break;
1670 case BindingFlags.Instance:
1671 static_mask = Modifiers.STATIC;
1672 static_flags = 0;
1673 break;
1675 default:
1676 static_mask = static_flags = 0;
1677 break;
1680 Timer.StartTimer (TimerType.TcFindMembers);
1682 if (filter == null)
1683 filter = accepting_filter;
1685 if ((mt & MemberTypes.Field) != 0) {
1686 if (fields != null) {
1687 int len = fields.Count;
1688 for (int i = 0; i < len; i++) {
1689 FieldBase f = (FieldBase) fields [i];
1691 if ((f.ModFlags & modflags) == 0)
1692 continue;
1693 if ((f.ModFlags & static_mask) != static_flags)
1694 continue;
1696 FieldBuilder fb = f.FieldBuilder;
1697 if (fb != null && filter (fb, criteria) == true) {
1698 if (members == null)
1699 members = new ArrayList ();
1701 members.Add (fb);
1706 if (constants != null) {
1707 int len = constants.Count;
1708 for (int i = 0; i < len; i++) {
1709 Const con = (Const) constants [i];
1711 if ((con.ModFlags & modflags) == 0)
1712 continue;
1713 if ((con.ModFlags & static_mask) != static_flags)
1714 continue;
1716 FieldBuilder fb = con.FieldBuilder;
1717 if (fb == null) {
1718 if (con.Define ())
1719 fb = con.FieldBuilder;
1721 if (fb != null && filter (fb, criteria) == true) {
1722 if (members == null)
1723 members = new ArrayList ();
1725 members.Add (fb);
1731 if ((mt & MemberTypes.Method) != 0) {
1732 if (methods != null) {
1733 int len = methods.Count;
1734 for (int i = 0; i < len; i++) {
1735 MethodOrOperator m = (MethodOrOperator) methods [i];
1737 if ((m.ModFlags & modflags) == 0)
1738 continue;
1739 if ((m.ModFlags & static_mask) != static_flags)
1740 continue;
1742 MethodBuilder mb = m.MethodBuilder;
1744 if (mb != null && filter (mb, criteria) == true) {
1745 if (members == null)
1746 members = new ArrayList ();
1748 members.Add (mb);
1753 if (operators != null) {
1754 int len = operators.Count;
1755 for (int i = 0; i < len; i++) {
1756 Operator o = (Operator) operators [i];
1758 if ((o.ModFlags & modflags) == 0)
1759 continue;
1760 if ((o.ModFlags & static_mask) != static_flags)
1761 continue;
1763 MethodBuilder ob = o.MethodBuilder;
1764 if (ob != null && filter (ob, criteria) == true) {
1765 if (members == null)
1766 members = new ArrayList ();
1768 members.Add (ob);
1773 if (events != null) {
1774 foreach (Event e in events) {
1775 if ((e.ModFlags & modflags) == 0)
1776 continue;
1777 if ((e.ModFlags & static_mask) != static_flags)
1778 continue;
1780 MethodBuilder b = e.AddBuilder;
1781 if (b != null && filter (b, criteria)) {
1782 if (members == null)
1783 members = new ArrayList (4);
1785 members.Add (b);
1788 b = e.RemoveBuilder;
1789 if (b != null && filter (b, criteria)) {
1790 if (members == null)
1791 members = new ArrayList (4);
1793 members.Add (b);
1798 if (properties != null) {
1799 int len = properties.Count;
1800 for (int i = 0; i < len; i++) {
1801 Property p = (Property) properties [i];
1803 if ((p.ModFlags & modflags) == 0)
1804 continue;
1805 if ((p.ModFlags & static_mask) != static_flags)
1806 continue;
1808 MethodBuilder b;
1810 b = p.GetBuilder;
1811 if (b != null && filter (b, criteria) == true) {
1812 if (members == null)
1813 members = new ArrayList ();
1815 members.Add (b);
1818 b = p.SetBuilder;
1819 if (b != null && filter (b, criteria) == true) {
1820 if (members == null)
1821 members = new ArrayList ();
1823 members.Add (b);
1828 if (indexers != null) {
1829 int len = indexers.Count;
1830 for (int i = 0; i < len; i++) {
1831 Indexer ix = (Indexer) indexers [i];
1833 if ((ix.ModFlags & modflags) == 0)
1834 continue;
1835 if ((ix.ModFlags & static_mask) != static_flags)
1836 continue;
1838 MethodBuilder b;
1840 b = ix.GetBuilder;
1841 if (b != null && filter (b, criteria) == true) {
1842 if (members == null)
1843 members = new ArrayList ();
1845 members.Add (b);
1848 b = ix.SetBuilder;
1849 if (b != null && filter (b, criteria) == true) {
1850 if (members == null)
1851 members = new ArrayList ();
1853 members.Add (b);
1859 if ((mt & MemberTypes.Event) != 0) {
1860 if (events != null) {
1861 int len = events.Count;
1862 for (int i = 0; i < len; i++) {
1863 Event e = (Event) events [i];
1865 if ((e.ModFlags & modflags) == 0)
1866 continue;
1867 if ((e.ModFlags & static_mask) != static_flags)
1868 continue;
1870 MemberInfo eb = e.EventBuilder;
1871 if (eb != null && filter (eb, criteria) == true) {
1872 if (members == null)
1873 members = new ArrayList ();
1875 members.Add (e.EventBuilder);
1881 if ((mt & MemberTypes.Property) != 0){
1882 if (properties != null) {
1883 int len = properties.Count;
1884 for (int i = 0; i < len; i++) {
1885 Property p = (Property) properties [i];
1887 if ((p.ModFlags & modflags) == 0)
1888 continue;
1889 if ((p.ModFlags & static_mask) != static_flags)
1890 continue;
1892 MemberInfo pb = p.PropertyBuilder;
1893 if (pb != null && filter (pb, criteria) == true) {
1894 if (members == null)
1895 members = new ArrayList ();
1897 members.Add (p.PropertyBuilder);
1902 if (indexers != null) {
1903 int len = indexers.Count;
1904 for (int i = 0; i < len; i++) {
1905 Indexer ix = (Indexer) indexers [i];
1907 if ((ix.ModFlags & modflags) == 0)
1908 continue;
1909 if ((ix.ModFlags & static_mask) != static_flags)
1910 continue;
1912 MemberInfo ib = ix.PropertyBuilder;
1913 if (ib != null && filter (ib, criteria) == true) {
1914 if (members == null)
1915 members = new ArrayList ();
1917 members.Add (ix.PropertyBuilder);
1923 if ((mt & MemberTypes.NestedType) != 0)
1924 FindMembers_NestedTypes (modflags, bf, filter, criteria, ref members);
1926 if ((mt & MemberTypes.Constructor) != 0){
1927 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1928 int len = instance_constructors.Count;
1929 for (int i = 0; i < len; i++) {
1930 Constructor c = (Constructor) instance_constructors [i];
1932 ConstructorBuilder cb = c.ConstructorBuilder;
1933 if (cb != null && filter (cb, criteria) == true) {
1934 if (members == null)
1935 members = new ArrayList ();
1937 members.Add (cb);
1942 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1943 ConstructorBuilder cb =
1944 default_static_constructor.ConstructorBuilder;
1946 if (cb != null && filter (cb, criteria) == true) {
1947 if (members == null)
1948 members = new ArrayList ();
1950 members.Add (cb);
1956 // Lookup members in base if requested.
1958 if ((bf & BindingFlags.DeclaredOnly) == 0) {
1959 if (TypeBuilder.BaseType != null) {
1960 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1961 if (list.Count > 0) {
1962 if (members == null)
1963 members = new ArrayList ();
1965 members.AddRange (list);
1970 Timer.StopTimer (TimerType.TcFindMembers);
1972 if (members == null)
1973 return MemberList.Empty;
1974 else
1975 return new MemberList (members);
1978 public override MemberCache MemberCache {
1979 get {
1980 return member_cache;
1984 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1985 MemberFilter filter, object criteria)
1987 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1989 if (ds != null)
1990 return ds.FindMembers (mt, bf, filter, criteria);
1991 else
1992 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1995 /// <summary>
1996 /// Emits the values for the constants
1997 /// </summary>
1998 public void EmitConstants ()
2000 if (constants != null)
2001 foreach (Const con in constants)
2002 con.Emit ();
2003 return;
2006 static void CheckMemberUsage (MemberCoreArrayList al, string member_type)
2008 if (al == null)
2009 return;
2011 foreach (MemberCore mc in al) {
2012 if ((mc.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
2013 continue;
2015 if (!mc.IsUsed && (mc.caching_flags & Flags.Excluded) == 0) {
2016 Report.Warning (169, 3, mc.Location, "The private {0} `{1}' is never used", member_type, mc.GetSignatureForError ());
2021 public virtual void VerifyMembers ()
2024 // Check for internal or private fields that were never assigned
2026 if (Report.WarningLevel >= 3) {
2027 CheckMemberUsage (properties, "property");
2028 CheckMemberUsage (methods, "method");
2029 CheckMemberUsage (constants, "constant");
2031 if (fields != null){
2032 bool is_type_exposed = Kind == Kind.Struct || IsExposedFromAssembly ();
2033 foreach (FieldBase f in fields) {
2034 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE) {
2035 if (is_type_exposed)
2036 continue;
2038 f.SetMemberIsUsed ();
2041 if (!f.IsUsed){
2042 if ((f.caching_flags & Flags.IsAssigned) == 0)
2043 Report.Warning (169, 3, f.Location, "The private field `{0}' is never used", f.GetSignatureForError ());
2044 else {
2045 #if NET_2_0
2046 const int error_code = 414;
2047 #else
2048 const int error_code = 169;
2049 #endif
2050 Report.Warning (error_code, 3, f.Location, "The private field `{0}' is assigned but its value is never used",
2051 f.GetSignatureForError ());
2053 continue;
2057 // Only report 649 on level 4
2059 if (Report.WarningLevel < 4)
2060 continue;
2062 if ((f.caching_flags & Flags.IsAssigned) != 0)
2063 continue;
2066 // Don't be pendatic over serializable attributes
2068 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2069 continue;
2071 Constant c = New.Constantify (f.MemberType);
2072 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value `{1}'",
2073 f.GetSignatureForError (), c == null ? "null" : c.AsString ());
2079 // TODO: move to ClassOrStruct
2080 void EmitConstructors ()
2082 if (instance_constructors == null)
2083 return;
2085 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && RootContext.VerifyClsCompliance && IsClsComplianceRequired ()) {
2086 bool has_compliant_args = false;
2088 foreach (Constructor c in instance_constructors) {
2089 try {
2090 c.Emit ();
2092 catch (Exception e) {
2093 throw new InternalErrorException (c, e);
2096 if (has_compliant_args)
2097 continue;
2099 has_compliant_args = c.HasCompliantArgs;
2101 if (!has_compliant_args)
2102 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2103 } else {
2104 foreach (Constructor c in instance_constructors) {
2105 try {
2106 c.Emit ();
2108 catch (Exception e) {
2109 throw new InternalErrorException (c, e);
2115 /// <summary>
2116 /// Emits the code, this step is performed after all
2117 /// the types, enumerations, constructors
2118 /// </summary>
2119 public virtual void EmitType ()
2121 if (OptAttributes != null)
2122 OptAttributes.Emit ();
2124 Emit ();
2126 EmitConstructors ();
2128 // Can not continue if constants are broken
2129 EmitConstants ();
2130 if (Report.Errors > 0)
2131 return;
2133 if (default_static_constructor != null)
2134 default_static_constructor.Emit ();
2136 if (operators != null)
2137 foreach (Operator o in operators)
2138 o.Emit ();
2140 if (properties != null)
2141 foreach (Property p in properties)
2142 p.Emit ();
2144 if (indexers != null) {
2145 foreach (Indexer indx in indexers)
2146 indx.Emit ();
2147 EmitIndexerName ();
2150 if (events != null){
2151 foreach (Event e in Events)
2152 e.Emit ();
2155 if (methods != null) {
2156 for (int i = 0; i < methods.Count; ++i)
2157 ((MethodOrOperator) methods [i]).Emit ();
2160 if (fields != null)
2161 foreach (FieldBase f in fields)
2162 f.Emit ();
2164 if (delegates != null) {
2165 foreach (Delegate d in Delegates) {
2166 d.Emit ();
2170 if (pending != null)
2171 pending.VerifyPendingMethods ();
2173 if (Report.Errors > 0)
2174 return;
2176 if (compiler_generated != null) {
2177 for (int i = 0; i < compiler_generated.Count; ++i)
2178 ((CompilerGeneratedClass) compiler_generated [i]).EmitType ();
2182 public override void CloseType ()
2184 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2185 return;
2187 try {
2188 caching_flags |= Flags.CloseTypeCreated;
2189 TypeBuilder.CreateType ();
2190 } catch (TypeLoadException){
2192 // This is fine, the code still created the type
2194 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
2195 // Console.WriteLine (e.Message);
2196 } catch (Exception e) {
2197 throw new InternalErrorException (this, e);
2200 if (Types != null){
2201 foreach (TypeContainer tc in Types)
2202 if (tc.Kind == Kind.Struct)
2203 tc.CloseType ();
2205 foreach (TypeContainer tc in Types)
2206 if (tc.Kind != Kind.Struct)
2207 tc.CloseType ();
2210 if (Delegates != null)
2211 foreach (Delegate d in Delegates)
2212 d.CloseType ();
2214 if (compiler_generated != null)
2215 foreach (CompilerGeneratedClass c in compiler_generated)
2216 c.CloseType ();
2218 PartialContainer = null;
2219 types = null;
2220 properties = null;
2221 delegates = null;
2222 fields = null;
2223 initialized_fields = null;
2224 initialized_static_fields = null;
2225 constants = null;
2226 ordered_explicit_member_list = null;
2227 ordered_member_list = null;
2228 methods = null;
2229 events = null;
2230 indexers = null;
2231 operators = null;
2232 compiler_generated = null;
2233 default_constructor = null;
2234 default_static_constructor = null;
2235 type_bases = null;
2236 OptAttributes = null;
2237 ifaces = null;
2238 base_cache = null;
2239 member_cache = null;
2243 // Performs the validation on a Method's modifiers (properties have
2244 // the same properties).
2246 public bool MethodModifiersValid (MemberCore mc)
2248 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2249 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2250 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2251 bool ok = true;
2252 int flags = mc.ModFlags;
2255 // At most one of static, virtual or override
2257 if ((flags & Modifiers.STATIC) != 0){
2258 if ((flags & vao) != 0){
2259 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2260 mc.GetSignatureForError ());
2261 ok = false;
2265 if (Kind == Kind.Struct){
2266 if ((flags & va) != 0){
2267 Modifiers.Error_InvalidModifier (mc.Location, "virtual or abstract");
2268 ok = false;
2272 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2273 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2274 mc.GetSignatureForError ());
2275 ok = false;
2279 // If the declaration includes the abstract modifier, then the
2280 // declaration does not include static, virtual or extern
2282 if ((flags & Modifiers.ABSTRACT) != 0){
2283 if ((flags & Modifiers.EXTERN) != 0){
2284 Report.Error (
2285 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2286 ok = false;
2289 if ((flags & Modifiers.SEALED) != 0) {
2290 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2291 ok = false;
2294 if ((flags & Modifiers.VIRTUAL) != 0){
2295 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2296 ok = false;
2299 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2300 Report.SymbolRelatedToPreviousError (this);
2301 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2302 mc.GetSignatureForError (), GetSignatureForError ());
2303 ok = false;
2307 if ((flags & Modifiers.PRIVATE) != 0){
2308 if ((flags & vao) != 0){
2309 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2310 ok = false;
2314 if ((flags & Modifiers.SEALED) != 0){
2315 if ((flags & Modifiers.OVERRIDE) == 0){
2316 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2317 ok = false;
2321 return ok;
2324 public Constructor DefaultStaticConstructor {
2325 get { return default_static_constructor; }
2328 protected override bool VerifyClsCompliance ()
2330 if (!base.VerifyClsCompliance ())
2331 return false;
2333 VerifyClsName ();
2335 Type base_type = TypeBuilder.BaseType;
2336 if (base_type != null && !AttributeTester.IsClsCompliant (base_type)) {
2337 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (base_type));
2339 return true;
2343 /// <summary>
2344 /// Checks whether container name is CLS Compliant
2345 /// </summary>
2346 void VerifyClsName ()
2348 Hashtable base_members = base_cache == null ?
2349 new Hashtable () :
2350 base_cache.GetPublicMembers ();
2351 Hashtable this_members = new Hashtable ();
2353 foreach (DictionaryEntry entry in defined_names) {
2354 MemberCore mc = (MemberCore)entry.Value;
2355 if (!mc.IsClsComplianceRequired ())
2356 continue;
2358 string name = (string) entry.Key;
2359 string basename = name.Substring (name.LastIndexOf ('.') + 1);
2361 string lcase = basename.ToLower (System.Globalization.CultureInfo.InvariantCulture);
2362 object found = base_members [lcase];
2363 if (found == null) {
2364 found = this_members [lcase];
2365 if (found == null) {
2366 this_members.Add (lcase, mc);
2367 continue;
2371 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
2372 continue;
2374 if (found is MemberInfo) {
2375 if (basename == ((MemberInfo) found).Name)
2376 continue;
2377 Report.SymbolRelatedToPreviousError ((MemberInfo) found);
2378 } else {
2379 Report.SymbolRelatedToPreviousError ((MemberCore) found);
2382 Report.Warning (3005, 1, mc.Location, "Identifier `{0}' differing only in case is not CLS-compliant", mc.GetSignatureForError ());
2387 /// <summary>
2388 /// Performs checks for an explicit interface implementation. First it
2389 /// checks whether the `interface_type' is a base inteface implementation.
2390 /// Then it checks whether `name' exists in the interface type.
2391 /// </summary>
2392 public bool VerifyImplements (InterfaceMemberBase mb)
2394 if (ifaces != null) {
2395 foreach (Type t in ifaces){
2396 if (TypeManager.IsEqual (t, mb.InterfaceType))
2397 return true;
2401 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2402 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2403 mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType));
2404 return false;
2407 public override Type LookupAnyGeneric (string typeName)
2409 if (types != null) {
2410 foreach (TypeContainer tc in types) {
2411 if (!tc.IsGeneric)
2412 continue;
2414 int pos = tc.Basename.LastIndexOf ('`');
2415 if (pos == typeName.Length && String.Compare (typeName, 0, tc.Basename, 0, pos) == 0)
2416 return tc.TypeBuilder;
2420 return base.LookupAnyGeneric (typeName);
2423 public void Mark_HasEquals ()
2425 cached_method |= CachedMethods.Equals;
2428 public void Mark_HasGetHashCode ()
2430 cached_method |= CachedMethods.GetHashCode;
2433 /// <summary>
2434 /// Method container contains Equals method
2435 /// </summary>
2436 public bool HasEquals {
2437 get {
2438 return (cached_method & CachedMethods.Equals) != 0;
2442 /// <summary>
2443 /// Method container contains GetHashCode method
2444 /// </summary>
2445 public bool HasGetHashCode {
2446 get {
2447 return (cached_method & CachedMethods.GetHashCode) != 0;
2451 public bool HasStaticFieldInitializer {
2452 get {
2453 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2455 set {
2456 if (value)
2457 cached_method |= CachedMethods.HasStaticFieldInitializer;
2458 else
2459 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2464 // IMemberContainer
2467 string IMemberContainer.Name {
2468 get {
2469 return Name;
2473 Type IMemberContainer.Type {
2474 get {
2475 return TypeBuilder;
2479 bool IMemberContainer.IsInterface {
2480 get {
2481 return Kind == Kind.Interface;
2485 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2487 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2489 if (GenericType != null)
2490 return TypeManager.FindMembers (GenericType, mt, new_bf,
2491 null, null);
2492 else
2493 return FindMembers (mt, new_bf, null, null);
2497 // Generates xml doc comments (if any), and if required,
2498 // handle warning report.
2500 internal override void GenerateDocComment (DeclSpace ds)
2502 DocUtil.GenerateTypeDocComment (this, ds);
2505 public override string DocCommentHeader {
2506 get { return "T:"; }
2509 public MemberCache BaseCache {
2510 get {
2511 if (base_cache != null)
2512 return base_cache;
2513 if (TypeBuilder.BaseType != null)
2514 base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
2515 if (TypeBuilder.IsInterface)
2516 base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
2517 return base_cache;
2522 public abstract class ClassOrStruct : TypeContainer {
2523 ListDictionary declarative_security;
2525 public ClassOrStruct (NamespaceEntry ns, DeclSpace parent,
2526 MemberName name, Attributes attrs, Kind kind)
2527 : base (ns, parent, name, attrs, kind)
2531 protected override bool AddToContainer (MemberCore symbol, string name)
2533 if (name == MemberName.Name) {
2534 if (symbol is TypeParameter) {
2535 Report.Error (694, symbol.Location,
2536 "Type parameter `{0}' has same name as containing type, or method",
2537 symbol.GetSignatureForError ());
2538 return false;
2541 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2542 if (imb == null || !imb.IsExplicitImpl) {
2543 Report.SymbolRelatedToPreviousError (this);
2544 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2545 symbol.GetSignatureForError ());
2546 return false;
2550 return base.AddToContainer (symbol, name);
2553 public override void VerifyMembers ()
2555 base.VerifyMembers ();
2557 if ((events != null) && Report.WarningLevel >= 3) {
2558 foreach (Event e in events){
2559 // Note: The event can be assigned from same class only, so we can report
2560 // this warning for all accessibility modes
2561 if ((e.caching_flags & Flags.IsUsed) == 0)
2562 Report.Warning (67, 3, e.Location, "The event `{0}' is never used", e.GetSignatureForError ());
2567 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2569 if (a.IsValidSecurityAttribute ()) {
2570 if (declarative_security == null)
2571 declarative_security = new ListDictionary ();
2573 a.ExtractSecurityPermissionSet (declarative_security);
2574 return;
2577 if (a.Type == pa.StructLayout) {
2578 PartialContainer.HasStructLayout = true;
2580 if (a.GetLayoutKindValue () == LayoutKind.Explicit)
2581 PartialContainer.HasExplicitLayout = true;
2584 base.ApplyAttributeBuilder (a, cb, pa);
2587 /// <summary>
2588 /// Defines the default constructors
2589 /// </summary>
2590 protected void DefineDefaultConstructor (bool is_static)
2592 // The default instance constructor is public
2593 // If the class is abstract, the default constructor is protected
2594 // The default static constructor is private
2596 int mods;
2597 if (is_static) {
2598 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2599 } else {
2600 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2603 Constructor c = new Constructor (this, MemberName.Name, mods,
2604 null, ParametersCompiled.EmptyReadOnlyParameters,
2605 new GeneratedBaseInitializer (Location),
2606 Location);
2608 AddConstructor (c);
2609 c.Block = new ToplevelBlock (ParametersCompiled.EmptyReadOnlyParameters, Location);
2612 public override bool Define ()
2614 CheckProtectedModifier ();
2616 base.Define ();
2618 if (default_static_constructor != null)
2619 default_static_constructor.Define ();
2621 return true;
2624 public override void Emit ()
2626 if (default_static_constructor == null && PartialContainer.HasStaticFieldInitializer) {
2627 DefineDefaultConstructor (true);
2628 default_static_constructor.Define ();
2631 base.Emit ();
2633 if (declarative_security != null) {
2634 foreach (DictionaryEntry de in declarative_security) {
2635 TypeBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
2640 public override ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
2642 return NamespaceEntry.LookupExtensionMethod (extensionType, this, name, loc);
2645 protected override TypeAttributes TypeAttr {
2646 get {
2647 if (default_static_constructor == null)
2648 return base.TypeAttr | TypeAttributes.BeforeFieldInit;
2650 return base.TypeAttr;
2656 // TODO: should be sealed
2657 public class Class : ClassOrStruct {
2658 const int AllowedModifiers =
2659 Modifiers.NEW |
2660 Modifiers.PUBLIC |
2661 Modifiers.PROTECTED |
2662 Modifiers.INTERNAL |
2663 Modifiers.PRIVATE |
2664 Modifiers.ABSTRACT |
2665 Modifiers.SEALED |
2666 Modifiers.STATIC |
2667 Modifiers.UNSAFE;
2669 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2671 public Class (NamespaceEntry ns, DeclSpace parent, MemberName name, int mod,
2672 Attributes attrs)
2673 : base (ns, parent, name, attrs, Kind.Class)
2675 int accmods = Parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2676 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, Location);
2678 if (IsStatic && RootContext.Version == LanguageVersion.ISO_1) {
2679 Report.FeatureIsNotAvailable (Location, "static classes");
2683 public override void AddBasesForPart (DeclSpace part, ArrayList bases)
2685 if (part.Name == "System.Object")
2686 Report.Error (537, part.Location,
2687 "The class System.Object cannot have a base class or implement an interface.");
2688 base.AddBasesForPart (part, bases);
2691 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2693 if (a.Type == pa.AttributeUsage) {
2694 if (!TypeManager.IsAttributeType (BaseType) &&
2695 TypeBuilder.FullName != "System.Attribute") {
2696 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2700 if (a.Type == pa.Conditional && !TypeManager.IsAttributeType (BaseType)) {
2701 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2702 return;
2705 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2706 a.Error_MissingGuidAttribute ();
2707 return;
2710 if (a.Type == pa.Extension) {
2711 a.Error_MisusedExtensionAttribute ();
2712 return;
2715 if (AttributeTester.IsAttributeExcluded (a.Type, Location))
2716 return;
2718 base.ApplyAttributeBuilder (a, cb, pa);
2721 public override AttributeTargets AttributeTargets {
2722 get {
2723 return AttributeTargets.Class;
2727 protected override void DefineContainerMembers (MemberCoreArrayList list)
2729 if (list == null)
2730 return;
2732 if (!IsStatic) {
2733 base.DefineContainerMembers (list);
2734 return;
2737 foreach (MemberCore m in list) {
2738 if (m is Operator) {
2739 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2740 continue;
2743 if (m is Destructor) {
2744 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2745 continue;
2748 if (m is Indexer) {
2749 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2750 continue;
2753 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is Enum || m is Delegate)
2754 continue;
2756 if (m is Constructor) {
2757 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2758 continue;
2761 Method method = m as Method;
2762 if (method != null && method.Parameters.HasExtensionMethodType) {
2763 Report.Error (1105, m.Location, "`{0}': Extension methods must be declared static", m.GetSignatureForError ());
2764 continue;
2767 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2770 base.DefineContainerMembers (list);
2773 public override bool Define ()
2775 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2776 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2779 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2780 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2783 return base.Define ();
2786 protected override bool DoDefineMembers ()
2788 if (InstanceConstructors == null && !IsStatic)
2789 DefineDefaultConstructor (false);
2791 return base.DoDefineMembers ();
2794 public override void Emit ()
2796 base.Emit ();
2798 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2799 PredefinedAttributes.Get.Extension.EmitAttribute (TypeBuilder);
2802 protected override TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
2804 TypeExpr[] ifaces = base.ResolveBaseTypes (out base_class);
2806 if (base_class == null) {
2807 if (RootContext.StdLib)
2808 base_class = TypeManager.system_object_expr;
2809 else if (Name != "System.Object")
2810 base_class = TypeManager.system_object_expr;
2811 } else {
2812 if (Kind == Kind.Class && base_class is TypeParameterExpr){
2813 Report.Error (
2814 689, base_class.Location,
2815 "Cannot derive from `{0}' because it is a type parameter",
2816 base_class.GetSignatureForError ());
2817 return ifaces;
2820 if (IsGeneric && TypeManager.IsAttributeType (base_class.Type)) {
2821 Report.Error (698, base_class.Location,
2822 "A generic type cannot derive from `{0}' because it is an attribute class",
2823 base_class.GetSignatureForError ());
2826 if (base_class.IsSealed){
2827 Report.SymbolRelatedToPreviousError (base_class.Type);
2828 if (base_class.Type.IsAbstract) {
2829 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2830 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
2831 } else {
2832 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2833 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
2835 return ifaces;
2838 if (!base_class.CanInheritFrom ()){
2839 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2840 GetSignatureForError (), base_class.GetSignatureForError ());
2841 return ifaces;
2844 if (!IsAccessibleAs (base_class.Type)) {
2845 Report.SymbolRelatedToPreviousError (base_class.Type);
2846 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2847 TypeManager.CSharpName (base_class.Type), GetSignatureForError ());
2851 if (PartialContainer.IsStaticClass) {
2852 if (base_class.Type != TypeManager.object_type) {
2853 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2854 GetSignatureForError (), base_class.GetSignatureForError ());
2855 return ifaces;
2858 if (ifaces != null) {
2859 foreach (TypeExpr t in ifaces)
2860 Report.SymbolRelatedToPreviousError (t.Type);
2861 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2865 return ifaces;
2868 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2869 /// Valid only for attribute classes.
2870 public bool IsExcluded ()
2872 if ((caching_flags & Flags.Excluded_Undetected) == 0)
2873 return (caching_flags & Flags.Excluded) != 0;
2875 caching_flags &= ~Flags.Excluded_Undetected;
2877 if (OptAttributes == null)
2878 return false;
2880 Attribute[] attrs = OptAttributes.SearchMulti (PredefinedAttributes.Get.Conditional);
2881 if (attrs == null)
2882 return false;
2884 foreach (Attribute a in attrs) {
2885 string condition = a.GetConditionalAttributeValue ();
2886 if (Location.CompilationUnit.IsConditionalDefined (condition))
2887 return false;
2890 caching_flags |= Flags.Excluded;
2891 return true;
2894 bool IsStatic {
2895 get {
2896 return (ModFlags & Modifiers.STATIC) != 0;
2901 // FIXME: How do we deal with the user specifying a different
2902 // layout?
2904 protected override TypeAttributes TypeAttr {
2905 get {
2906 TypeAttributes ta = base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2907 if (IsStatic)
2908 ta |= StaticClassAttribute;
2909 return ta;
2914 public sealed class Struct : ClassOrStruct {
2916 bool is_unmanaged, has_unmanaged_check_done;
2918 // <summary>
2919 // Modifiers allowed in a struct declaration
2920 // </summary>
2921 const int AllowedModifiers =
2922 Modifiers.NEW |
2923 Modifiers.PUBLIC |
2924 Modifiers.PROTECTED |
2925 Modifiers.INTERNAL |
2926 Modifiers.UNSAFE |
2927 Modifiers.PRIVATE;
2929 public Struct (NamespaceEntry ns, DeclSpace parent, MemberName name,
2930 int mod, Attributes attrs)
2931 : base (ns, parent, name, attrs, Kind.Struct)
2933 int accmods;
2935 if (parent.Parent == null)
2936 accmods = Modifiers.INTERNAL;
2937 else
2938 accmods = Modifiers.PRIVATE;
2940 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, Location);
2942 this.ModFlags |= Modifiers.SEALED;
2945 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2947 base.ApplyAttributeBuilder (a, cb, pa);
2950 // When struct constains fixed fixed and struct layout has explicitly
2951 // set CharSet, its value has to be propagated to compiler generated
2952 // fixed field types
2954 if (a.Type == pa.StructLayout && Fields != null && a.HasField ("CharSet")) {
2955 for (int i = 0; i < Fields.Count; ++i) {
2956 FixedField ff = Fields [i] as FixedField;
2957 if (ff != null)
2958 ff.SetCharSet (TypeBuilder.Attributes);
2963 public override AttributeTargets AttributeTargets {
2964 get {
2965 return AttributeTargets.Struct;
2969 public override bool IsUnmanagedType ()
2971 if (fields == null)
2972 return true;
2974 if (requires_delayed_unmanagedtype_check)
2975 return true;
2977 if (has_unmanaged_check_done)
2978 return is_unmanaged;
2980 has_unmanaged_check_done = true;
2982 foreach (FieldBase f in fields) {
2983 if ((f.ModFlags & Modifiers.STATIC) != 0)
2984 continue;
2986 // It can happen when recursive unmanaged types are defined
2987 // struct S { S* s; }
2988 Type mt = f.MemberType;
2989 if (mt == null) {
2990 has_unmanaged_check_done = false;
2991 requires_delayed_unmanagedtype_check = true;
2992 return true;
2995 // TODO: Remove when pointer types are under mcs control
2996 while (mt.IsPointer)
2997 mt = TypeManager.GetElementType (mt);
2998 if (TypeManager.IsEqual (mt, TypeBuilder))
2999 continue;
3001 if (TypeManager.IsUnmanagedType (mt))
3002 continue;
3004 return false;
3007 is_unmanaged = true;
3008 return true;
3011 protected override TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
3013 TypeExpr[] ifaces = base.ResolveBaseTypes (out base_class);
3015 // If we are compiling our runtime,
3016 // and we are defining ValueType, then our
3017 // base is `System.Object'.
3019 if (base_class == null) {
3020 if (!RootContext.StdLib && Name == "System.ValueType")
3021 base_class = TypeManager.system_object_expr;
3022 else
3023 base_class = TypeManager.system_valuetype_expr;
3026 return ifaces;
3030 // FIXME: Allow the user to specify a different set of attributes
3031 // in some cases (Sealed for example is mandatory for a class,
3032 // but what SequentialLayout can be changed
3034 protected override TypeAttributes TypeAttr {
3035 get {
3036 const TypeAttributes DefaultTypeAttributes =
3037 TypeAttributes.SequentialLayout |
3038 TypeAttributes.Sealed;
3040 return base.TypeAttr | DefaultTypeAttributes;
3044 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
3046 if ((field.ModFlags & Modifiers.STATIC) == 0) {
3047 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
3048 field.GetSignatureForError ());
3049 return;
3051 base.RegisterFieldForInitialization (field, expression);
3056 /// <summary>
3057 /// Interfaces
3058 /// </summary>
3059 public sealed class Interface : TypeContainer, IMemberContainer {
3061 /// <summary>
3062 /// Modifiers allowed in a class declaration
3063 /// </summary>
3064 public const int AllowedModifiers =
3065 Modifiers.NEW |
3066 Modifiers.PUBLIC |
3067 Modifiers.PROTECTED |
3068 Modifiers.INTERNAL |
3069 Modifiers.UNSAFE |
3070 Modifiers.PRIVATE;
3072 public Interface (NamespaceEntry ns, DeclSpace parent, MemberName name, int mod,
3073 Attributes attrs)
3074 : base (ns, parent, name, attrs, Kind.Interface)
3076 int accmods;
3078 if (parent.Parent == null)
3079 accmods = Modifiers.INTERNAL;
3080 else
3081 accmods = Modifiers.PRIVATE;
3083 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, name.Location);
3086 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
3088 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3089 a.Error_MissingGuidAttribute ();
3090 return;
3093 base.ApplyAttributeBuilder (a, cb, pa);
3097 public override AttributeTargets AttributeTargets {
3098 get {
3099 return AttributeTargets.Interface;
3103 protected override TypeAttributes TypeAttr {
3104 get {
3105 const TypeAttributes DefaultTypeAttributes =
3106 TypeAttributes.AutoLayout |
3107 TypeAttributes.Abstract |
3108 TypeAttributes.Interface;
3110 return base.TypeAttr | DefaultTypeAttributes;
3114 protected override bool VerifyClsCompliance ()
3116 if (!base.VerifyClsCompliance ())
3117 return false;
3119 if (ifaces != null) {
3120 foreach (Type t in ifaces) {
3121 if (AttributeTester.IsClsCompliant (t))
3122 continue;
3124 Report.SymbolRelatedToPreviousError (t);
3125 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3126 GetSignatureForError (), TypeManager.CSharpName (t));
3130 return true;
3134 // It is used as a base class for all property based members
3135 // This includes properties, indexers, and events
3136 public abstract class PropertyBasedMember : InterfaceMemberBase
3138 public PropertyBasedMember (DeclSpace parent, GenericMethod generic,
3139 FullNamedExpression type, int mod, int allowed_mod,
3140 MemberName name, Attributes attrs)
3141 : base (parent, generic, type, mod, allowed_mod, name, attrs)
3145 protected override bool VerifyClsCompliance ()
3147 if (!base.VerifyClsCompliance ())
3148 return false;
3150 if (!AttributeTester.IsClsCompliant (MemberType)) {
3151 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
3152 GetSignatureForError ());
3154 return true;
3160 public abstract class MethodCore : InterfaceMemberBase
3162 public readonly ParametersCompiled Parameters;
3163 protected ToplevelBlock block;
3165 public MethodCore (DeclSpace parent, GenericMethod generic,
3166 FullNamedExpression type, int mod, int allowed_mod,
3167 MemberName name, Attributes attrs, ParametersCompiled parameters)
3168 : base (parent, generic, type, mod, allowed_mod, name, attrs)
3170 Parameters = parameters;
3174 // Returns the System.Type array for the parameters of this method
3176 public Type [] ParameterTypes {
3177 get {
3178 return Parameters.Types;
3182 public ParametersCompiled ParameterInfo {
3183 get {
3184 return Parameters;
3188 public ToplevelBlock Block {
3189 get {
3190 return block;
3193 set {
3194 block = value;
3198 public CallingConventions CallingConventions {
3199 get {
3200 CallingConventions cc = Parameters.CallingConvention;
3201 if (!IsInterface)
3202 if ((ModFlags & Modifiers.STATIC) == 0)
3203 cc |= CallingConventions.HasThis;
3205 // FIXME: How is `ExplicitThis' used in C#?
3207 return cc;
3211 protected override bool CheckBase ()
3213 // Check whether arguments were correct.
3214 if (!DefineParameters (Parameters))
3215 return false;
3217 return base.CheckBase ();
3221 // Returns a string that represents the signature for this
3222 // member which should be used in XML documentation.
3224 public override string GetDocCommentName (DeclSpace ds)
3226 return DocUtil.GetMethodDocCommentName (this, Parameters, ds);
3230 // Raised (and passed an XmlElement that contains the comment)
3231 // when GenerateDocComment is writing documentation expectedly.
3233 // FIXME: with a few effort, it could be done with XmlReader,
3234 // that means removal of DOM use.
3236 internal override void OnGenerateDocComment (XmlElement el)
3238 DocUtil.OnMethodGenerateDocComment (this, el);
3242 // Represents header string for documentation comment.
3244 public override string DocCommentHeader
3246 get { return "M:"; }
3249 public override bool EnableOverloadChecks (MemberCore overload)
3251 if (overload is MethodCore || overload is AbstractPropertyEventMethod) {
3252 caching_flags |= Flags.MethodOverloadsExist;
3253 return true;
3256 return base.EnableOverloadChecks (overload);
3259 protected override bool VerifyClsCompliance ()
3261 if (!base.VerifyClsCompliance ())
3262 return false;
3264 if (Parameters.HasArglist) {
3265 Report.Warning (3000, 1, Location, "Methods with variable arguments are not CLS-compliant");
3268 if (!AttributeTester.IsClsCompliant (MemberType)) {
3269 Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant",
3270 GetSignatureForError ());
3273 Parameters.VerifyClsCompliance ();
3274 return true;
3279 public abstract class InterfaceMemberBase : MemberBase {
3281 // Whether this is an interface member.
3283 public bool IsInterface;
3286 // If true, this is an explicit interface implementation
3288 public bool IsExplicitImpl;
3290 protected bool is_external_implementation;
3293 // The interface type we are explicitly implementing
3295 public Type InterfaceType;
3298 // The method we're overriding if this is an override method.
3300 protected MethodInfo base_method;
3302 readonly int explicit_mod_flags;
3303 public MethodAttributes flags;
3305 public InterfaceMemberBase (DeclSpace parent, GenericMethod generic,
3306 FullNamedExpression type, int mod, int allowed_mod,
3307 MemberName name, Attributes attrs)
3308 : base (parent, generic, type, mod, allowed_mod, Modifiers.PRIVATE,
3309 name, attrs)
3311 IsInterface = parent.PartialContainer.Kind == Kind.Interface;
3312 IsExplicitImpl = (MemberName.Left != null);
3313 explicit_mod_flags = mod;
3316 protected override bool CheckBase ()
3318 if (!base.CheckBase ())
3319 return false;
3321 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3322 CheckForDuplications ();
3324 if (IsExplicitImpl)
3325 return true;
3327 // Is null for System.Object while compiling corlib and base interfaces
3328 if (Parent.PartialContainer.BaseCache == null) {
3329 if ((ModFlags & Modifiers.NEW) != 0) {
3330 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3332 return true;
3335 Type base_ret_type = null;
3336 base_method = FindOutBaseMethod (ref base_ret_type);
3338 // method is override
3339 if (base_method != null) {
3340 if (!CheckMethodAgainstBase (base_ret_type))
3341 return false;
3343 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3344 ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (base_method);
3345 if (oa != null) {
3346 if (OptAttributes == null || !OptAttributes.Contains (PredefinedAttributes.Get.Obsolete)) {
3347 Report.SymbolRelatedToPreviousError (base_method);
3348 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3349 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3351 } else {
3352 if (OptAttributes != null && OptAttributes.Contains (PredefinedAttributes.Get.Obsolete)) {
3353 Report.SymbolRelatedToPreviousError (base_method);
3354 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3355 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3359 return true;
3362 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Name, !((this is Event) || (this is Property)));
3363 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3364 if (conflict_symbol != null) {
3365 Report.SymbolRelatedToPreviousError (conflict_symbol);
3366 if (this is Event)
3367 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3368 else if (this is PropertyBase)
3369 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3370 else
3371 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3372 } else {
3373 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3374 GetSignatureForError (), SimpleName.GetMemberType (this));
3376 return false;
3379 if (conflict_symbol == null) {
3380 if ((ModFlags & Modifiers.NEW) != 0) {
3381 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3383 return true;
3386 if ((ModFlags & Modifiers.NEW) == 0) {
3387 if (this is MethodOrOperator && conflict_symbol.MemberType == MemberTypes.Method)
3388 return true;
3390 Report.SymbolRelatedToPreviousError (conflict_symbol);
3391 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3392 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3395 return true;
3398 protected virtual bool CheckForDuplications ()
3400 return Parent.MemberCache.CheckExistingMembersOverloads (
3401 this, GetFullName (MemberName), ParametersCompiled.EmptyReadOnlyParameters);
3405 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3406 // that have been defined.
3408 // `name' is the user visible name for reporting errors (this is used to
3409 // provide the right name regarding method names and properties)
3411 bool CheckMethodAgainstBase (Type base_method_type)
3413 bool ok = true;
3415 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3416 if (!(base_method.IsAbstract || base_method.IsVirtual)){
3417 Report.SymbolRelatedToPreviousError (base_method);
3418 Report.Error (506, Location,
3419 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3420 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3421 ok = false;
3424 // Now we check that the overriden method is not final
3426 if (base_method.IsFinal) {
3427 Report.SymbolRelatedToPreviousError (base_method);
3428 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3429 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3430 ok = false;
3433 // Check that the permissions are not being changed
3435 MethodAttributes thisp = flags & MethodAttributes.MemberAccessMask;
3436 MethodAttributes base_classp = base_method.Attributes & MethodAttributes.MemberAccessMask;
3438 if (!CheckAccessModifiers (thisp, base_classp, base_method)) {
3439 Error_CannotChangeAccessModifiers (Location, base_method, base_classp, null);
3440 ok = false;
3443 if (!TypeManager.IsEqual (MemberType, TypeManager.TypeToCoreType (base_method_type))) {
3444 Report.SymbolRelatedToPreviousError (base_method);
3445 if (this is PropertyBasedMember) {
3446 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3447 GetSignatureForError (), TypeManager.CSharpName (base_method_type), TypeManager.CSharpSignature (base_method));
3449 else {
3450 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3451 GetSignatureForError (), TypeManager.CSharpName (base_method_type), TypeManager.CSharpSignature (base_method));
3453 ok = false;
3457 if ((ModFlags & Modifiers.NEW) == 0) {
3458 if ((ModFlags & Modifiers.OVERRIDE) == 0) {
3459 ModFlags |= Modifiers.NEW;
3460 Report.SymbolRelatedToPreviousError (base_method);
3461 if (!IsInterface && (base_method.IsVirtual || base_method.IsAbstract)) {
3462 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",
3463 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3464 } else {
3465 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3466 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3469 } else {
3470 if (base_method.IsAbstract && !IsInterface) {
3471 Report.SymbolRelatedToPreviousError (base_method);
3472 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3473 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3474 return ok = false;
3478 return ok;
3481 protected bool CheckAccessModifiers (MethodAttributes thisp, MethodAttributes base_classp, MethodInfo base_method)
3483 if ((base_classp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3485 // when overriding protected internal, the method can be declared
3486 // protected internal only within the same assembly or assembly
3487 // which has InternalsVisibleTo
3489 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3490 return TypeManager.IsThisOrFriendAssembly (base_method.DeclaringType.Assembly);
3491 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3493 // if it's not "protected internal", it must be "protected"
3496 return false;
3497 } else if (Parent.TypeBuilder.Assembly == base_method.DeclaringType.Assembly) {
3499 // protected within the same assembly - an error
3501 return false;
3502 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3503 (base_classp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3505 // protected ok, but other attributes differ - report an error
3507 return false;
3509 return true;
3510 } else {
3511 return (thisp == base_classp);
3515 public override bool Define ()
3517 if (IsInterface) {
3518 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3519 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3521 flags = MethodAttributes.Public |
3522 MethodAttributes.Abstract |
3523 MethodAttributes.HideBySig |
3524 MethodAttributes.NewSlot |
3525 MethodAttributes.Virtual;
3526 } else {
3527 Parent.PartialContainer.MethodModifiersValid (this);
3529 flags = Modifiers.MethodAttr (ModFlags);
3532 if (IsExplicitImpl) {
3533 TypeExpr iface_texpr = MemberName.Left.GetTypeExpression ().ResolveAsTypeTerminal (this, false);
3534 if (iface_texpr == null)
3535 return false;
3537 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3538 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3539 GetSignatureForError ());
3542 InterfaceType = iface_texpr.Type;
3544 if (!InterfaceType.IsInterface) {
3545 Report.SymbolRelatedToPreviousError (InterfaceType);
3546 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3547 TypeManager.CSharpName (InterfaceType));
3548 } else {
3549 Parent.PartialContainer.VerifyImplements (this);
3552 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
3555 return base.Define ();
3558 protected bool DefineParameters (ParametersCompiled parameters)
3560 IResolveContext rc = GenericMethod == null ? this : (IResolveContext)ds;
3562 if (!parameters.Resolve (rc))
3563 return false;
3565 bool error = false;
3566 for (int i = 0; i < parameters.Count; ++i) {
3567 Parameter p = parameters [i];
3569 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3570 p.Warning_UselessOptionalParameter ();
3572 if (p.CheckAccessibility (this))
3573 continue;
3575 Type t = parameters.Types [i];
3576 Report.SymbolRelatedToPreviousError (t);
3577 if (this is Indexer)
3578 Report.Error (55, Location,
3579 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3580 TypeManager.CSharpName (t), GetSignatureForError ());
3581 else if (this is Operator)
3582 Report.Error (57, Location,
3583 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3584 TypeManager.CSharpName (t), GetSignatureForError ());
3585 else
3586 Report.Error (51, Location,
3587 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3588 TypeManager.CSharpName (t), GetSignatureForError ());
3589 error = true;
3591 return !error;
3594 public override void Emit()
3596 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3597 // We are more strict than csc and report this as an error because SRE does not allow emit that
3598 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation) {
3599 if (this is Constructor) {
3600 Report.Error (824, Location,
3601 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3602 } else {
3603 Report.Error (626, Location,
3604 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3605 GetSignatureForError ());
3609 base.Emit ();
3612 public override bool EnableOverloadChecks (MemberCore overload)
3615 // Two members can differ in their explicit interface
3616 // type parameter only
3618 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3619 if (imb != null && imb.IsExplicitImpl) {
3620 if (IsExplicitImpl) {
3621 caching_flags |= Flags.MethodOverloadsExist;
3623 return true;
3626 return IsExplicitImpl;
3629 protected void Error_CannotChangeAccessModifiers (Location loc, MemberInfo base_method, MethodAttributes ma, string suffix)
3631 Report.SymbolRelatedToPreviousError (base_method);
3632 string base_name = TypeManager.GetFullNameSignature (base_method);
3633 string this_name = GetSignatureForError ();
3634 if (suffix != null) {
3635 base_name += suffix;
3636 this_name += suffix;
3639 Report.Error (507, loc, "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3640 this_name, Modifiers.GetDescription (ma), base_name);
3643 protected static string Error722 {
3644 get {
3645 return "`{0}': static types cannot be used as return types";
3649 /// <summary>
3650 /// Gets base method and its return type
3651 /// </summary>
3652 protected abstract MethodInfo FindOutBaseMethod (ref Type base_ret_type);
3655 // The "short" name of this property / indexer / event. This is the
3656 // name without the explicit interface.
3658 public string ShortName
3660 get { return MemberName.Name; }
3661 set { SetMemberName (new MemberName (MemberName.Left, value, Location)); }
3665 // Returns full metadata method name
3667 public string GetFullName (MemberName name)
3669 if (!IsExplicitImpl)
3670 return name.Name;
3673 // When dealing with explicit members a full interface type
3674 // name is added to member name to avoid possible name conflicts
3676 // We use CSharpName which gets us full name with benefit of
3677 // replacing predefined names which saves some space and name
3678 // is still unique
3680 return TypeManager.CSharpName (InterfaceType) + "." + name.Name;
3683 protected override bool VerifyClsCompliance ()
3685 if (!base.VerifyClsCompliance ()) {
3686 if (IsInterface && HasClsCompliantAttribute && Parent.IsClsComplianceRequired ()) {
3687 Report.Warning (3010, 1, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
3690 if ((ModFlags & Modifiers.ABSTRACT) != 0 && Parent.TypeBuilder.IsClass && IsExposedFromAssembly () && Parent.IsClsComplianceRequired ()) {
3691 Report.Warning (3011, 1, Location, "`{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
3693 return false;
3696 if (GenericMethod != null)
3697 GenericMethod.VerifyClsCompliance ();
3699 return true;
3702 public override bool IsUsed
3704 get { return IsExplicitImpl || base.IsUsed; }
3709 public abstract class MethodOrOperator : MethodCore, IMethodData
3711 public MethodBuilder MethodBuilder;
3712 ReturnParameter return_attributes;
3713 ListDictionary declarative_security;
3714 protected MethodData MethodData;
3716 static string[] attribute_targets = new string [] { "method", "return" };
3718 protected MethodOrOperator (DeclSpace parent, GenericMethod generic, FullNamedExpression type, int mod,
3719 int allowed_mod, MemberName name,
3720 Attributes attrs, ParametersCompiled parameters)
3721 : base (parent, generic, type, mod, allowed_mod, name,
3722 attrs, parameters)
3726 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
3728 if (a.Target == AttributeTargets.ReturnValue) {
3729 if (return_attributes == null)
3730 return_attributes = new ReturnParameter (MethodBuilder, Location);
3732 return_attributes.ApplyAttributeBuilder (a, cb, pa);
3733 return;
3736 if (a.IsInternalMethodImplAttribute) {
3737 is_external_implementation = true;
3740 if (a.Type == pa.DllImport) {
3741 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3742 if ((ModFlags & extern_static) != extern_static) {
3743 Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
3745 is_external_implementation = true;
3748 if (a.IsValidSecurityAttribute ()) {
3749 if (declarative_security == null)
3750 declarative_security = new ListDictionary ();
3751 a.ExtractSecurityPermissionSet (declarative_security);
3752 return;
3755 if (MethodBuilder != null)
3756 MethodBuilder.SetCustomAttribute (cb);
3759 public override AttributeTargets AttributeTargets {
3760 get {
3761 return AttributeTargets.Method;
3765 protected override bool CheckForDuplications ()
3767 string name = GetFullName (MemberName);
3768 if (MemberName.IsGeneric)
3769 name = MemberName.MakeName (name, MemberName.TypeArguments);
3771 return Parent.MemberCache.CheckExistingMembersOverloads (this, name, Parameters);
3774 public virtual EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
3776 return new EmitContext (
3777 this, tc, this.ds, Location, ig, MemberType, ModFlags, false);
3780 protected override bool ResolveMemberType ()
3782 #if GMCS_SOURCE
3783 if (GenericMethod != null) {
3784 MethodBuilder = Parent.TypeBuilder.DefineMethod (GetFullName (MemberName), flags);
3785 if (!GenericMethod.Define (this))
3786 return false;
3788 #endif
3790 return base.ResolveMemberType ();
3793 public override bool Define ()
3795 if (!base.Define ())
3796 return false;
3798 if (!CheckBase ())
3799 return false;
3801 if (block != null && block.IsIterator && !(Parent is IteratorStorey)) {
3803 // Current method is turned into automatically generated
3804 // wrapper which creates an instance of iterator
3806 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
3807 ModFlags |= Modifiers.DEBUGGER_HIDDEN;
3810 if (IsPartialDefinition) {
3811 caching_flags &= ~Flags.Excluded_Undetected;
3812 caching_flags |= Flags.Excluded;
3813 // Add to member cache only when a partial method implementation is not there
3814 if ((caching_flags & Flags.MethodOverloadsExist) == 0) {
3815 MethodBase mb = new PartialMethodDefinitionInfo (this);
3816 Parent.MemberCache.AddMember (mb, this);
3817 TypeManager.AddMethod (mb, this);
3820 return true;
3823 MethodData = new MethodData (
3824 this, ModFlags, flags, this, MethodBuilder, GenericMethod, base_method);
3826 if (!MethodData.Define (Parent.PartialContainer, GetFullName (MemberName)))
3827 return false;
3829 MethodBuilder = MethodData.MethodBuilder;
3831 if (TypeManager.IsGenericMethod (MethodBuilder))
3832 Parent.MemberCache.AddGenericMember (MethodBuilder, this);
3834 Parent.MemberCache.AddMember (MethodBuilder, this);
3836 return true;
3839 protected override void DoMemberTypeIndependentChecks ()
3841 base.DoMemberTypeIndependentChecks ();
3843 CheckAbstractAndExtern (block != null);
3845 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3846 for (int i = 0; i < Parameters.Count; ++i) {
3847 IParameterData p = Parameters.FixedParameters [i];
3848 if (p.ModFlags == Parameter.Modifier.OUT) {
3849 Report.Error (752, Location, "`{0}': A partial method parameters cannot use `out' modifier",
3850 GetSignatureForError ());
3853 if (p.HasDefaultValue && IsPartialImplementation)
3854 ((Parameter) p).Warning_UselessOptionalParameter ();
3859 protected override void DoMemberTypeDependentChecks ()
3861 base.DoMemberTypeDependentChecks ();
3863 if (!TypeManager.IsGenericParameter (MemberType)) {
3864 if (MemberType.IsAbstract && MemberType.IsSealed) {
3865 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
3870 public override void Emit ()
3872 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
3873 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (MethodBuilder);
3874 if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
3875 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (MethodBuilder);
3877 if (TypeManager.IsDynamicType (ReturnType)) {
3878 return_attributes = new ReturnParameter (MethodBuilder, Location);
3879 return_attributes.EmitPredefined (PredefinedAttributes.Get.Dynamic, Location);
3882 if (OptAttributes != null)
3883 OptAttributes.Emit ();
3885 if (declarative_security != null) {
3886 foreach (DictionaryEntry de in declarative_security) {
3887 MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
3891 if (MethodData != null)
3892 MethodData.Emit (Parent);
3894 base.Emit ();
3896 Block = null;
3897 MethodData = null;
3900 protected void Error_ConditionalAttributeIsNotValid ()
3902 Report.Error (577, Location,
3903 "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
3904 GetSignatureForError ());
3907 public bool IsPartialDefinition {
3908 get {
3909 return (ModFlags & Modifiers.PARTIAL) != 0 && Block == null;
3913 public bool IsPartialImplementation {
3914 get {
3915 return (ModFlags & Modifiers.PARTIAL) != 0 && Block != null;
3919 public override string[] ValidAttributeTargets {
3920 get {
3921 return attribute_targets;
3925 #region IMethodData Members
3927 public Type ReturnType {
3928 get {
3929 return MemberType;
3933 public MemberName MethodName {
3934 get {
3935 return MemberName;
3939 /// <summary>
3940 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
3941 /// </summary>
3942 public bool IsExcluded () {
3943 if ((caching_flags & Flags.Excluded_Undetected) == 0)
3944 return (caching_flags & Flags.Excluded) != 0;
3946 caching_flags &= ~Flags.Excluded_Undetected;
3948 if (base_method == null) {
3949 if (OptAttributes == null)
3950 return false;
3952 Attribute[] attrs = OptAttributes.SearchMulti (PredefinedAttributes.Get.Conditional);
3954 if (attrs == null)
3955 return false;
3957 foreach (Attribute a in attrs) {
3958 string condition = a.GetConditionalAttributeValue ();
3959 if (condition == null)
3960 return false;
3962 if (Location.CompilationUnit.IsConditionalDefined (condition))
3963 return false;
3966 caching_flags |= Flags.Excluded;
3967 return true;
3970 IMethodData md = TypeManager.GetMethod (TypeManager.DropGenericMethodArguments (base_method));
3971 if (md == null) {
3972 if (AttributeTester.IsConditionalMethodExcluded (base_method, Location)) {
3973 caching_flags |= Flags.Excluded;
3974 return true;
3976 return false;
3979 if (md.IsExcluded ()) {
3980 caching_flags |= Flags.Excluded;
3981 return true;
3983 return false;
3986 GenericMethod IMethodData.GenericMethod {
3987 get {
3988 return GenericMethod;
3992 public virtual void EmitExtraSymbolInfo (SourceMethod source)
3995 #endregion
3999 public class SourceMethod : IMethodDef
4001 MethodBase method;
4002 SourceMethodBuilder builder;
4004 protected SourceMethod (DeclSpace parent, MethodBase method, ICompileUnit file)
4006 this.method = method;
4008 builder = SymbolWriter.OpenMethod (file, parent.NamespaceEntry.SymbolFileID, this);
4011 public string Name {
4012 get { return method.Name; }
4015 public int Token {
4016 get {
4017 if (method is MethodBuilder)
4018 return ((MethodBuilder) method).GetToken ().Token;
4019 else if (method is ConstructorBuilder)
4020 return ((ConstructorBuilder) method).GetToken ().Token;
4021 else
4022 throw new NotSupportedException ();
4026 public void CloseMethod ()
4028 SymbolWriter.CloseMethod ();
4031 public void SetRealMethodName (string name)
4033 if (builder != null)
4034 builder.SetRealMethodName (name);
4037 public static SourceMethod Create (DeclSpace parent, MethodBase method, Block block)
4039 if (!SymbolWriter.HasSymbolWriter)
4040 return null;
4041 if (block == null)
4042 return null;
4044 Location start_loc = block.StartLocation;
4045 if (start_loc.IsNull)
4046 return null;
4048 ICompileUnit compile_unit = start_loc.CompilationUnit;
4049 if (compile_unit == null)
4050 return null;
4052 return new SourceMethod (parent, method, compile_unit);
4056 public class Method : MethodOrOperator {
4058 /// <summary>
4059 /// Modifiers allowed in a class declaration
4060 /// </summary>
4061 const int AllowedModifiers =
4062 Modifiers.NEW |
4063 Modifiers.PUBLIC |
4064 Modifiers.PROTECTED |
4065 Modifiers.INTERNAL |
4066 Modifiers.PRIVATE |
4067 Modifiers.STATIC |
4068 Modifiers.VIRTUAL |
4069 Modifiers.SEALED |
4070 Modifiers.OVERRIDE |
4071 Modifiers.ABSTRACT |
4072 Modifiers.UNSAFE |
4073 Modifiers.EXTERN;
4075 const int AllowedInterfaceModifiers =
4076 Modifiers.NEW | Modifiers.UNSAFE;
4078 public Method (DeclSpace parent, GenericMethod generic,
4079 FullNamedExpression return_type, int mod,
4080 MemberName name, ParametersCompiled parameters, Attributes attrs)
4081 : base (parent, generic, return_type, mod,
4082 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
4083 name, attrs, parameters)
4087 protected Method (DeclSpace parent, FullNamedExpression return_type, int mod, int amod,
4088 MemberName name, ParametersCompiled parameters, Attributes attrs)
4089 : base (parent, null, return_type, mod, amod, name, attrs, parameters)
4093 public override string GetSignatureForError()
4095 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
4098 static void Error_DuplicateEntryPoint (Method b)
4100 Report.Error (17, b.Location,
4101 "Program `{0}' has more than one entry point defined: `{1}'",
4102 CodeGen.FileName, b.GetSignatureForError ());
4105 bool IsEntryPoint ()
4107 if (ReturnType != TypeManager.void_type &&
4108 ReturnType != TypeManager.int32_type)
4109 return false;
4111 if (Parameters.Count == 0)
4112 return true;
4114 if (Parameters.Count > 1)
4115 return false;
4117 Type t = Parameters.Types [0];
4118 return t.IsArray && t.GetArrayRank () == 1 &&
4119 TypeManager.GetElementType (t) == TypeManager.string_type &&
4120 (Parameters[0].ModFlags & ~Parameter.Modifier.PARAMS) == Parameter.Modifier.NONE;
4123 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
4125 if (a.Type == pa.Conditional) {
4126 if (IsExplicitImpl) {
4127 Error_ConditionalAttributeIsNotValid ();
4128 return;
4131 if (ReturnType != TypeManager.void_type) {
4132 Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ());
4133 return;
4136 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
4137 Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ());
4138 return;
4141 if (IsInterface) {
4142 Report.Error (582, Location, "Conditional not valid on interface members");
4143 return;
4146 if (MethodData.implementing != null) {
4147 Report.SymbolRelatedToPreviousError (MethodData.implementing.DeclaringType);
4148 Report.Error (629, Location, "Conditional member `{0}' cannot implement interface member `{1}'",
4149 GetSignatureForError (), TypeManager.CSharpSignature (MethodData.implementing));
4150 return;
4153 for (int i = 0; i < Parameters.Count; ++i) {
4154 if (Parameters.FixedParameters [i].ModFlags == Parameter.Modifier.OUT) {
4155 Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
4156 return;
4161 if (a.Type == pa.Extension) {
4162 a.Error_MisusedExtensionAttribute ();
4163 return;
4166 base.ApplyAttributeBuilder (a, cb, pa);
4169 protected override bool CheckForDuplications ()
4171 if (!base.CheckForDuplications ())
4172 return false;
4174 ArrayList ar = Parent.PartialContainer.Properties;
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 ar = Parent.PartialContainer.Indexers;
4184 if (ar != null) {
4185 for (int i = 0; i < ar.Count; ++i) {
4186 PropertyBase pb = (PropertyBase) ar [i];
4187 if (pb.AreAccessorsDuplicateImplementation (this))
4188 return false;
4192 return true;
4195 protected override bool CheckBase ()
4197 if (!base.CheckBase ())
4198 return false;
4200 if (base_method != null && (ModFlags & Modifiers.OVERRIDE) != 0 && Name == Destructor.MetadataName) {
4201 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
4202 TypeManager.CSharpSignature (base_method));
4205 return true;
4209 // Creates the type
4211 public override bool Define ()
4213 if (type_name == TypeManager.system_void_expr && Parameters.IsEmpty && Name == Destructor.MetadataName) {
4214 Report.Warning (465, 1, Location, "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
4217 if (!base.Define ())
4218 return false;
4220 if (RootContext.StdLib && TypeManager.IsSpecialType (ReturnType)) {
4221 Error1599 (Location, ReturnType);
4222 return false;
4225 if (base_method != null && (ModFlags & Modifiers.NEW) == 0) {
4226 if (Parameters.Count == 1 && ParameterTypes [0] == TypeManager.object_type && Name == "Equals")
4227 Parent.PartialContainer.Mark_HasEquals ();
4228 else if (Parameters.IsEmpty && Name == "GetHashCode")
4229 Parent.PartialContainer.Mark_HasGetHashCode ();
4232 if ((ModFlags & Modifiers.STATIC) == 0)
4233 return true;
4235 if (Parameters.HasExtensionMethodType) {
4236 if (Parent.PartialContainer.IsStaticClass && !Parent.IsGeneric) {
4237 if (!Parent.IsTopLevel)
4238 Report.Error (1109, Location, "`{0}': Extension methods cannot be defined in a nested class",
4239 GetSignatureForError ());
4241 PredefinedAttribute pa = PredefinedAttributes.Get.Extension;
4242 if (!pa.IsDefined) {
4243 Report.Error (1110, Location,
4244 "`{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",
4245 GetSignatureForError ());
4248 ModFlags |= Modifiers.METHOD_EXTENSION;
4249 Parent.PartialContainer.ModFlags |= Modifiers.METHOD_EXTENSION;
4250 CodeGen.Assembly.HasExtensionMethods = true;
4251 } else {
4252 Report.Error (1106, Location, "`{0}': Extension methods must be defined in a non-generic static class",
4253 GetSignatureForError ());
4258 // This is used to track the Entry Point,
4260 if (RootContext.NeedsEntryPoint &&
4261 Name == "Main" &&
4262 (RootContext.MainClass == null ||
4263 RootContext.MainClass == Parent.TypeBuilder.FullName)){
4264 if (IsEntryPoint ()) {
4266 if (RootContext.EntryPoint == null) {
4267 if (Parent.IsGeneric || MemberName.IsGeneric) {
4268 Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type",
4269 GetSignatureForError ());
4270 } else {
4271 SetMemberIsUsed ();
4272 RootContext.EntryPoint = this;
4274 } else {
4275 Error_DuplicateEntryPoint (RootContext.EntryPoint);
4276 Error_DuplicateEntryPoint (this);
4278 } else {
4279 Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point",
4280 GetSignatureForError ());
4284 return true;
4288 // Emits the code
4290 public override void Emit ()
4292 try {
4293 Report.Debug (64, "METHOD EMIT", this, MethodBuilder, Location, Block, MethodData);
4294 if (IsPartialDefinition) {
4296 // Do attribute checks only when partial implementation does not exist
4298 if (MethodBuilder == null)
4299 base.Emit ();
4301 return;
4304 if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.PartialDefinitionExists) == 0)
4305 Report.Error (759, Location, "A partial method `{0}' implementation is missing a partial method declaration",
4306 GetSignatureForError ());
4308 base.Emit ();
4310 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
4311 PredefinedAttributes.Get.Extension.EmitAttribute (MethodBuilder);
4312 } catch {
4313 Console.WriteLine ("Internal compiler error at {0}: exception caught while emitting {1}",
4314 Location, MethodBuilder);
4315 throw;
4319 public override bool EnableOverloadChecks (MemberCore overload)
4321 // TODO: It can be deleted when members will be defined in correct order
4322 if (overload is Operator)
4323 return overload.EnableOverloadChecks (this);
4325 if (overload is Indexer)
4326 return false;
4328 return base.EnableOverloadChecks (overload);
4331 public static void Error1599 (Location loc, Type t)
4333 Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t));
4336 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
4338 MethodInfo mi = (MethodInfo) Parent.PartialContainer.BaseCache.FindMemberToOverride (
4339 Parent.TypeBuilder, Name, Parameters, GenericMethod, false);
4341 if (mi == null)
4342 return null;
4344 if (mi.IsSpecialName)
4345 return null;
4347 base_ret_type = TypeManager.TypeToCoreType (mi.ReturnType);
4348 return mi;
4351 public void SetPartialDefinition (Method methodDefinition)
4353 caching_flags |= Flags.PartialDefinitionExists;
4354 methodDefinition.MethodBuilder = MethodBuilder;
4356 for (int i = 0; i < methodDefinition.Parameters.Count; ++i ) {
4357 Parameters [i].DefaultValue = methodDefinition.Parameters [i].DefaultValue;
4360 if (methodDefinition.attributes == null)
4361 return;
4363 if (attributes == null) {
4364 attributes = methodDefinition.attributes;
4365 attributes.AttachTo (this);
4366 } else {
4367 attributes.Attrs.AddRange (methodDefinition.attributes.Attrs);
4371 protected override bool VerifyClsCompliance ()
4373 if (!base.VerifyClsCompliance ())
4374 return false;
4376 if (!Parameters.IsEmpty) {
4377 ArrayList al = (ArrayList)Parent.PartialContainer.MemberCache.Members [Name];
4378 if (al.Count > 1)
4379 MemberCache.VerifyClsParameterConflict (al, this, MethodBuilder);
4382 return true;
4386 public abstract class ConstructorInitializer : ExpressionStatement
4388 Arguments argument_list;
4389 MethodGroupExpr base_constructor_group;
4391 public ConstructorInitializer (Arguments argument_list, Location loc)
4393 this.argument_list = argument_list;
4394 this.loc = loc;
4397 public Arguments Arguments {
4398 get {
4399 return argument_list;
4403 public override Expression CreateExpressionTree (EmitContext ec)
4405 throw new NotSupportedException ("ET");
4408 public ExpressionStatement Resolve (ConstructorBuilder caller_builder, EmitContext ec)
4410 if (argument_list != null) {
4411 bool dynamic;
4412 argument_list.Resolve (ec, out dynamic);
4413 if (dynamic) {
4414 SimpleName ctor = new SimpleName (ConstructorBuilder.ConstructorName, loc);
4415 return new DynamicInvocation (ctor, argument_list, loc).Resolve (ec) as ExpressionStatement;
4419 if (this is ConstructorBaseInitializer) {
4420 if (ec.ContainerType.BaseType == null)
4421 return this;
4423 type = ec.ContainerType.BaseType;
4424 if (TypeManager.IsStruct (ec.ContainerType)) {
4425 Report.Error (522, loc,
4426 "`{0}': Struct constructors cannot call base constructors", TypeManager.CSharpSignature (caller_builder));
4427 return this;
4429 } else {
4431 // It is legal to have "this" initializers that take no arguments
4432 // in structs, they are just no-ops.
4434 // struct D { public D (int a) : this () {}
4436 if (TypeManager.IsStruct (ec.ContainerType) && argument_list == null)
4437 return this;
4439 type = ec.ContainerType;
4442 base_constructor_group = MemberLookupFinal (
4443 ec, null, type, ConstructorBuilder.ConstructorName, MemberTypes.Constructor,
4444 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
4445 loc) as MethodGroupExpr;
4447 if (base_constructor_group == null)
4448 return this;
4450 base_constructor_group = base_constructor_group.OverloadResolve (
4451 ec, ref argument_list, false, loc);
4453 if (base_constructor_group == null)
4454 return this;
4456 ConstructorInfo base_ctor = (ConstructorInfo)base_constructor_group;
4458 if (base_ctor == caller_builder){
4459 Report.Error (516, loc, "Constructor `{0}' cannot call itself", TypeManager.CSharpSignature (caller_builder));
4462 return this;
4465 public override Expression DoResolve (EmitContext ec)
4467 throw new NotSupportedException ();
4470 public override void Emit (EmitContext ec)
4472 // It can be null for static initializers
4473 if (base_constructor_group == null)
4474 return;
4476 ec.Mark (loc);
4477 if (!ec.IsStatic)
4478 base_constructor_group.InstanceExpression = ec.GetThis (loc);
4480 base_constructor_group.EmitCall (ec, argument_list);
4483 public override void EmitStatement (EmitContext ec)
4485 Emit (ec);
4489 public class ConstructorBaseInitializer : ConstructorInitializer {
4490 public ConstructorBaseInitializer (Arguments argument_list, Location l) :
4491 base (argument_list, l)
4496 class GeneratedBaseInitializer: ConstructorBaseInitializer {
4497 public GeneratedBaseInitializer (Location loc):
4498 base (null, loc)
4503 public class ConstructorThisInitializer : ConstructorInitializer {
4504 public ConstructorThisInitializer (Arguments argument_list, Location l) :
4505 base (argument_list, l)
4510 public class Constructor : MethodCore, IMethodData {
4511 public ConstructorBuilder ConstructorBuilder;
4512 public ConstructorInitializer Initializer;
4513 ListDictionary declarative_security;
4514 bool has_compliant_args;
4516 // <summary>
4517 // Modifiers allowed for a constructor.
4518 // </summary>
4519 public const int AllowedModifiers =
4520 Modifiers.PUBLIC |
4521 Modifiers.PROTECTED |
4522 Modifiers.INTERNAL |
4523 Modifiers.STATIC |
4524 Modifiers.UNSAFE |
4525 Modifiers.EXTERN |
4526 Modifiers.PRIVATE;
4528 static readonly string[] attribute_targets = new string [] { "method" };
4531 // The spec claims that static is not permitted, but
4532 // my very own code has static constructors.
4534 public Constructor (DeclSpace parent, string name, int mod, Attributes attrs, ParametersCompiled args,
4535 ConstructorInitializer init, Location loc)
4536 : base (parent, null, null, mod, AllowedModifiers,
4537 new MemberName (name, loc), attrs, args)
4539 Initializer = init;
4542 public bool HasCompliantArgs {
4543 get { return has_compliant_args; }
4546 public override AttributeTargets AttributeTargets {
4547 get { return AttributeTargets.Constructor; }
4551 // Returns true if this is a default constructor
4553 public bool IsDefault ()
4555 if ((ModFlags & Modifiers.STATIC) != 0)
4556 return Parameters.IsEmpty;
4558 return Parameters.IsEmpty &&
4559 (Initializer is ConstructorBaseInitializer) &&
4560 (Initializer.Arguments == null);
4563 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
4565 if (a.IsValidSecurityAttribute ()) {
4566 if (declarative_security == null) {
4567 declarative_security = new ListDictionary ();
4569 a.ExtractSecurityPermissionSet (declarative_security);
4570 return;
4573 if (a.IsInternalMethodImplAttribute) {
4574 is_external_implementation = true;
4577 ConstructorBuilder.SetCustomAttribute (cb);
4580 protected override bool CheckBase ()
4582 if ((ModFlags & Modifiers.STATIC) != 0) {
4583 if (!Parameters.IsEmpty) {
4584 Report.Error (132, Location, "`{0}': The static constructor must be parameterless",
4585 GetSignatureForError ());
4586 return false;
4589 // the rest can be ignored
4590 return true;
4593 // Check whether arguments were correct.
4594 if (!DefineParameters (Parameters))
4595 return false;
4597 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
4598 Parent.MemberCache.CheckExistingMembersOverloads (this, ConstructorInfo.ConstructorName,
4599 Parameters);
4601 if (Parent.PartialContainer.Kind == Kind.Struct) {
4602 if (Parameters.Count == 0) {
4603 Report.Error (568, Location,
4604 "Structs cannot contain explicit parameterless constructors");
4605 return false;
4609 CheckProtectedModifier ();
4611 return true;
4615 // Creates the ConstructorBuilder
4617 public override bool Define ()
4619 if (ConstructorBuilder != null)
4620 return true;
4622 MethodAttributes ca = (MethodAttributes.RTSpecialName |
4623 MethodAttributes.SpecialName);
4625 if ((ModFlags & Modifiers.STATIC) != 0) {
4626 ca |= MethodAttributes.Static | MethodAttributes.Private;
4627 } else {
4628 ca |= MethodAttributes.HideBySig;
4630 if ((ModFlags & Modifiers.PUBLIC) != 0)
4631 ca |= MethodAttributes.Public;
4632 else if ((ModFlags & Modifiers.PROTECTED) != 0){
4633 if ((ModFlags & Modifiers.INTERNAL) != 0)
4634 ca |= MethodAttributes.FamORAssem;
4635 else
4636 ca |= MethodAttributes.Family;
4637 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
4638 ca |= MethodAttributes.Assembly;
4639 else
4640 ca |= MethodAttributes.Private;
4643 if (!CheckAbstractAndExtern (block != null))
4644 return false;
4646 // Check if arguments were correct.
4647 if (!CheckBase ())
4648 return false;
4650 ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
4651 ca, CallingConventions,
4652 Parameters.GetEmitTypes ());
4654 if (Parent.PartialContainer.IsComImport) {
4655 if (!IsDefault ()) {
4656 Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
4657 Parent.GetSignatureForError ());
4659 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
4662 Parent.MemberCache.AddMember (ConstructorBuilder, this);
4663 TypeManager.AddMethod (ConstructorBuilder, this);
4665 // It's here only to report an error
4666 if (block != null && block.IsIterator) {
4667 member_type = TypeManager.void_type;
4668 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
4671 return true;
4675 // Emits the code
4677 public override void Emit ()
4679 if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
4680 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (ConstructorBuilder);
4682 if (OptAttributes != null)
4683 OptAttributes.Emit ();
4685 base.Emit ();
4687 EmitContext ec = CreateEmitContext (null, null);
4690 // If we use a "this (...)" constructor initializer, then
4691 // do not emit field initializers, they are initialized in the other constructor
4693 bool emit_field_initializers = ((ModFlags & Modifiers.STATIC) != 0) ||
4694 !(Initializer is ConstructorThisInitializer);
4696 if (emit_field_initializers)
4697 Parent.PartialContainer.ResolveFieldInitializers (ec);
4699 if (block != null) {
4700 // If this is a non-static `struct' constructor and doesn't have any
4701 // initializer, it must initialize all of the struct's fields.
4702 if ((Parent.PartialContainer.Kind == Kind.Struct) &&
4703 ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
4704 block.AddThisVariable (Parent, Location);
4706 if (!block.ResolveMeta (ec, Parameters))
4707 block = null;
4709 if (block != null && (ModFlags & Modifiers.STATIC) == 0){
4710 if (Parent.PartialContainer.Kind == Kind.Class && Initializer == null)
4711 Initializer = new GeneratedBaseInitializer (Location);
4714 // Spec mandates that Initializers will not have `this' access
4716 if (Initializer != null) {
4717 ec.IsStatic = true;
4718 ExpressionStatement expr = Initializer.Resolve (ConstructorBuilder, ec);
4719 ec.IsStatic = false;
4720 block.AddScopeStatement (new StatementExpression (expr));
4725 Parameters.ApplyAttributes (ConstructorBuilder);
4727 SourceMethod source = null;
4728 if (block == null)
4729 ec.OmitDebuggingInfo = true;
4730 else
4731 source = SourceMethod.Create (Parent, ConstructorBuilder, block);
4733 bool unreachable = false;
4734 if (block != null) {
4735 if (!ec.ResolveTopBlock (null, block, Parameters, this, out unreachable))
4736 return;
4738 ec.EmitMeta (block);
4740 if (Report.Errors > 0)
4741 return;
4743 ec.EmitResolvedTopBlock (block, unreachable);
4746 if (source != null)
4747 source.CloseMethod ();
4749 if (declarative_security != null) {
4750 foreach (DictionaryEntry de in declarative_security) {
4751 ConstructorBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
4755 block = null;
4758 // Is never override
4759 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
4761 return null;
4764 public override string GetSignatureForError()
4766 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
4769 public override string[] ValidAttributeTargets {
4770 get {
4771 return attribute_targets;
4775 protected override bool VerifyClsCompliance ()
4777 if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
4778 return false;
4781 if (!Parameters.IsEmpty) {
4782 ArrayList al = (ArrayList)Parent.MemberCache.Members [ConstructorInfo.ConstructorName];
4783 if (al.Count > 2)
4784 MemberCache.VerifyClsParameterConflict (al, this, ConstructorBuilder);
4786 if (TypeManager.IsSubclassOf (Parent.TypeBuilder, TypeManager.attribute_type)) {
4787 foreach (Type param in Parameters.Types) {
4788 if (param.IsArray) {
4789 return true;
4794 has_compliant_args = true;
4795 return true;
4798 #region IMethodData Members
4800 public MemberName MethodName {
4801 get {
4802 return MemberName;
4806 public Type ReturnType {
4807 get {
4808 return MemberType;
4812 public EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
4814 ILGenerator ig_ = ConstructorBuilder.GetILGenerator ();
4815 EmitContext ec = new EmitContext (this, Parent, Location, ig_, TypeManager.void_type, ModFlags, true);
4816 ec.CurrentBlock = block;
4817 return ec;
4820 public bool IsExcluded()
4822 return false;
4825 GenericMethod IMethodData.GenericMethod {
4826 get {
4827 return null;
4831 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
4834 #endregion
4837 /// <summary>
4838 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
4839 /// </summary>
4840 public interface IMethodData
4842 CallingConventions CallingConventions { get; }
4843 Location Location { get; }
4844 MemberName MethodName { get; }
4845 Type ReturnType { get; }
4846 GenericMethod GenericMethod { get; }
4847 ParametersCompiled ParameterInfo { get; }
4849 Attributes OptAttributes { get; }
4850 ToplevelBlock Block { get; set; }
4852 EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig);
4853 ObsoleteAttribute GetObsoleteAttribute ();
4854 string GetSignatureForError ();
4855 bool IsExcluded ();
4856 bool IsClsComplianceRequired ();
4857 void SetMemberIsUsed ();
4858 void EmitExtraSymbolInfo (SourceMethod source);
4862 // Encapsulates most of the Method's state
4864 public class MethodData {
4865 static FieldInfo methodbuilder_attrs_field;
4866 public readonly IMethodData method;
4868 public readonly GenericMethod GenericMethod;
4871 // Are we implementing an interface ?
4873 public MethodInfo implementing;
4876 // Protected data.
4878 protected InterfaceMemberBase member;
4879 protected int modifiers;
4880 protected MethodAttributes flags;
4881 protected Type declaring_type;
4882 protected MethodInfo parent_method;
4884 MethodBuilder builder = null;
4885 public MethodBuilder MethodBuilder {
4886 get {
4887 return builder;
4891 public Type DeclaringType {
4892 get {
4893 return declaring_type;
4897 public MethodData (InterfaceMemberBase member,
4898 int modifiers, MethodAttributes flags, IMethodData method)
4900 this.member = member;
4901 this.modifiers = modifiers;
4902 this.flags = flags;
4904 this.method = method;
4907 public MethodData (InterfaceMemberBase member,
4908 int modifiers, MethodAttributes flags,
4909 IMethodData method, MethodBuilder builder,
4910 GenericMethod generic, MethodInfo parent_method)
4911 : this (member, modifiers, flags, method)
4913 this.builder = builder;
4914 this.GenericMethod = generic;
4915 this.parent_method = parent_method;
4918 public bool Define (DeclSpace parent, string method_full_name)
4920 string name = method.MethodName.Basename;
4922 TypeContainer container = parent.PartialContainer;
4924 PendingImplementation pending = container.PendingImplementations;
4925 if (pending != null){
4926 implementing = pending.IsInterfaceMethod (name, member.InterfaceType, this);
4928 if (member.InterfaceType != null){
4929 if (implementing == null){
4930 if (member is PropertyBase) {
4931 Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'",
4932 method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType),
4933 member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
4935 } else {
4936 Report.Error (539, method.Location,
4937 "`{0}.{1}' in explicit interface declaration is not a member of interface",
4938 TypeManager.CSharpName (member.InterfaceType), member.ShortName);
4940 return false;
4942 if (implementing.IsSpecialName && !(method is AbstractPropertyEventMethod)) {
4943 Report.SymbolRelatedToPreviousError (implementing);
4944 Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
4945 member.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
4946 return false;
4948 } else {
4949 if (implementing != null) {
4950 AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod;
4951 if (prop_method == null) {
4952 if (TypeManager.IsSpecialMethod (implementing)) {
4953 Report.SymbolRelatedToPreviousError (implementing);
4954 Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}.{2}'",
4955 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing),
4956 implementing.Name.StartsWith ("get_") ? "get" : "set");
4958 } else if (implementing.DeclaringType.IsInterface) {
4959 if (!implementing.IsSpecialName) {
4960 Report.SymbolRelatedToPreviousError (implementing);
4961 Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
4962 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
4963 return false;
4965 PropertyBase.PropertyMethod pm = prop_method as PropertyBase.PropertyMethod;
4966 if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
4967 Report.SymbolRelatedToPreviousError (implementing);
4968 Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'",
4969 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing, true));
4970 return false;
4978 // For implicit implementations, make sure we are public, for
4979 // explicit implementations, make sure we are private.
4981 if (implementing != null){
4983 // Setting null inside this block will trigger a more
4984 // verbose error reporting for missing interface implementations
4986 // The "candidate" function has been flagged already
4987 // but it wont get cleared
4989 if (member.IsExplicitImpl){
4990 if (method.ParameterInfo.HasParams && !TypeManager.GetParameterData (implementing).HasParams) {
4991 Report.SymbolRelatedToPreviousError (implementing);
4992 Report.Error (466, method.Location, "`{0}': the explicit interface implementation cannot introduce the params modifier",
4993 method.GetSignatureForError ());
4994 return false;
4996 } else {
4997 if (implementing.DeclaringType.IsInterface) {
4999 // If this is an interface method implementation,
5000 // check for public accessibility
5002 if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
5004 implementing = null;
5006 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
5007 // We may never be private.
5008 implementing = null;
5010 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
5012 // We may be protected if we're overriding something.
5014 implementing = null;
5019 // Static is not allowed
5021 if ((modifiers & Modifiers.STATIC) != 0){
5022 implementing = null;
5027 // If implementing is still valid, set flags
5029 if (implementing != null){
5031 // When implementing interface methods, set NewSlot
5032 // unless, we are overwriting a method.
5034 if (implementing.DeclaringType.IsInterface){
5035 if ((modifiers & Modifiers.OVERRIDE) == 0)
5036 flags |= MethodAttributes.NewSlot;
5038 flags |=
5039 MethodAttributes.Virtual |
5040 MethodAttributes.HideBySig;
5042 // Set Final unless we're virtual, abstract or already overriding a method.
5043 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
5044 flags |= MethodAttributes.Final;
5047 DefineMethodBuilder (container, method_full_name, method.ParameterInfo);
5049 if (builder == null)
5050 return false;
5052 if (container.CurrentType != null)
5053 declaring_type = container.CurrentType;
5054 else
5055 declaring_type = container.TypeBuilder;
5057 if (implementing != null && member.IsExplicitImpl) {
5058 container.TypeBuilder.DefineMethodOverride (builder, implementing);
5061 TypeManager.AddMethod (builder, method);
5063 if (GenericMethod != null) {
5064 bool is_override = member.IsExplicitImpl |
5065 ((modifiers & Modifiers.OVERRIDE) != 0);
5067 if (implementing != null)
5068 parent_method = implementing;
5070 EmitContext ec = method.CreateEmitContext (container, null);
5071 if (!GenericMethod.DefineType (ec, builder, parent_method, is_override))
5072 return false;
5075 return true;
5079 /// <summary>
5080 /// Create the MethodBuilder for the method
5081 /// </summary>
5082 void DefineMethodBuilder (TypeContainer container, string method_name, ParametersCompiled param)
5084 if (builder == null) {
5085 builder = container.TypeBuilder.DefineMethod (
5086 method_name, flags, method.CallingConventions,
5087 TypeManager.TypeToReflectionType (method.ReturnType),
5088 param.GetEmitTypes ());
5089 return;
5092 #if GMCS_SOURCE
5094 // Generic method has been already defined to resolve method parameters
5095 // correctly when they use type parameters
5097 builder.SetParameters (param.GetEmitTypes ());
5098 builder.SetReturnType (method.ReturnType);
5099 #endif
5100 if (builder.Attributes != flags) {
5101 try {
5102 if (methodbuilder_attrs_field == null)
5103 methodbuilder_attrs_field = typeof (MethodBuilder).GetField ("attrs", BindingFlags.NonPublic | BindingFlags.Instance);
5104 methodbuilder_attrs_field.SetValue (builder, flags);
5105 } catch {
5106 Report.RuntimeMissingSupport (method.Location, "Generic method MethodAttributes");
5112 // Emits the code
5114 public void Emit (DeclSpace parent)
5116 ToplevelBlock block = method.Block;
5118 EmitContext ec;
5119 if (block != null)
5120 ec = method.CreateEmitContext (parent, builder.GetILGenerator ());
5121 else
5122 ec = method.CreateEmitContext (parent, null);
5124 method.ParameterInfo.ApplyAttributes (MethodBuilder);
5126 if (GenericMethod != null)
5127 GenericMethod.EmitAttributes ();
5130 // clear the pending implementation flag
5132 if (implementing != null)
5133 parent.PartialContainer.PendingImplementations.ImplementMethod (method.MethodName.Basename,
5134 member.InterfaceType, this, member.IsExplicitImpl);
5136 SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
5138 ec.EmitTopBlock (method, block);
5140 if (source != null) {
5141 method.EmitExtraSymbolInfo (source);
5142 source.CloseMethod ();
5147 public class Destructor : MethodOrOperator
5149 const int AllowedModifiers =
5150 Modifiers.UNSAFE |
5151 Modifiers.EXTERN;
5153 static readonly string[] attribute_targets = new string [] { "method" };
5155 public static readonly string MetadataName = "Finalize";
5157 public Destructor (DeclSpace parent, int mod, ParametersCompiled parameters, Attributes attrs, Location l)
5158 : base (parent, null, TypeManager.system_void_expr, mod, AllowedModifiers,
5159 new MemberName (MetadataName, l), attrs, parameters)
5161 ModFlags &= ~Modifiers.PRIVATE;
5162 ModFlags |= Modifiers.PROTECTED;
5165 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
5167 if (a.Type == pa.Conditional) {
5168 Error_ConditionalAttributeIsNotValid ();
5169 return;
5172 base.ApplyAttributeBuilder (a, cb, pa);
5175 protected override bool CheckBase ()
5177 flags |= MethodAttributes.Virtual;
5179 if (!base.CheckBase ())
5180 return false;
5182 if (Parent.PartialContainer.BaseCache == null)
5183 return true;
5185 Type base_type = Parent.PartialContainer.BaseCache.Container.Type;
5186 if (base_type != null && Block != null) {
5187 MethodGroupExpr method_expr = Expression.MethodLookup (Parent.TypeBuilder, base_type, MetadataName, Location);
5188 if (method_expr == null)
5189 throw new NotImplementedException ();
5191 method_expr.IsBase = true;
5192 method_expr.InstanceExpression = new CompilerGeneratedThis (Parent.TypeBuilder, Location);
5194 ToplevelBlock new_block = new ToplevelBlock (Block.StartLocation);
5195 new_block.EndLocation = Block.EndLocation;
5197 Block finaly_block = new ExplicitBlock (new_block, Location, Location);
5198 Block try_block = new Block (new_block, block);
5201 // 0-size arguments to avoid CS0250 error
5202 // TODO: Should use AddScopeStatement or something else which emits correct
5203 // debugger scope
5205 finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0))));
5206 new_block.AddStatement (new TryFinally (try_block, finaly_block, Location));
5208 block = new_block;
5211 return true;
5214 public override string GetSignatureForError ()
5216 return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
5219 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
5221 return null;
5224 public override string[] ValidAttributeTargets {
5225 get {
5226 return attribute_targets;
5231 public abstract class MemberBase : MemberCore
5233 protected FullNamedExpression type_name;
5234 protected Type member_type;
5236 public readonly DeclSpace ds;
5237 public readonly GenericMethod GenericMethod;
5239 protected MemberBase (DeclSpace parent, GenericMethod generic,
5240 FullNamedExpression type, int mod, int allowed_mod, int def_mod,
5241 MemberName name, Attributes attrs)
5242 : base (parent, name, attrs)
5244 this.ds = generic != null ? generic : (DeclSpace) parent;
5245 this.type_name = type;
5246 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, Location);
5247 GenericMethod = generic;
5248 if (GenericMethod != null)
5249 GenericMethod.ModFlags = ModFlags;
5253 // Main member define entry
5255 public override bool Define ()
5257 DoMemberTypeIndependentChecks ();
5260 // Returns false only when type resolution failed
5262 if (!ResolveMemberType ())
5263 return false;
5265 DoMemberTypeDependentChecks ();
5266 return true;
5270 // Any type_name independent checks
5272 protected virtual void DoMemberTypeIndependentChecks ()
5274 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
5275 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
5276 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
5277 GetSignatureForError (), Parent.GetSignatureForError ());
5282 // Any type_name dependent checks
5284 protected virtual void DoMemberTypeDependentChecks ()
5286 // verify accessibility
5287 if (!IsAccessibleAs (MemberType)) {
5288 Report.SymbolRelatedToPreviousError (MemberType);
5289 if (this is Property)
5290 Report.Error (53, Location,
5291 "Inconsistent accessibility: property type `" +
5292 TypeManager.CSharpName (MemberType) + "' is less " +
5293 "accessible than property `" + GetSignatureForError () + "'");
5294 else if (this is Indexer)
5295 Report.Error (54, Location,
5296 "Inconsistent accessibility: indexer return type `" +
5297 TypeManager.CSharpName (MemberType) + "' is less " +
5298 "accessible than indexer `" + GetSignatureForError () + "'");
5299 else if (this is MethodCore) {
5300 if (this is Operator)
5301 Report.Error (56, Location,
5302 "Inconsistent accessibility: return type `" +
5303 TypeManager.CSharpName (MemberType) + "' is less " +
5304 "accessible than operator `" + GetSignatureForError () + "'");
5305 else
5306 Report.Error (50, Location,
5307 "Inconsistent accessibility: return type `" +
5308 TypeManager.CSharpName (MemberType) + "' is less " +
5309 "accessible than method `" + GetSignatureForError () + "'");
5310 } else {
5311 Report.Error (52, Location,
5312 "Inconsistent accessibility: field type `" +
5313 TypeManager.CSharpName (MemberType) + "' is less " +
5314 "accessible than field `" + GetSignatureForError () + "'");
5318 Variance variance = this is Event ? Variance.Contravariant : Variance.Covariant;
5319 TypeManager.CheckTypeVariance (MemberType, variance, this);
5322 protected bool IsTypePermitted ()
5324 if (TypeManager.IsSpecialType (MemberType)) {
5325 Report.Error (610, Location, "Field or property cannot be of type `{0}'", TypeManager.CSharpName (MemberType));
5326 return false;
5328 return true;
5331 protected virtual bool CheckBase ()
5333 CheckProtectedModifier ();
5335 return true;
5338 public Type MemberType {
5339 get { return member_type; }
5342 protected virtual bool ResolveMemberType ()
5344 if (member_type != null)
5345 throw new InternalErrorException ("Multi-resolve");
5347 IResolveContext rc = GenericMethod == null ? this : (IResolveContext) ds;
5348 TypeExpr te = type_name.ResolveAsTypeTerminal (rc, false);
5349 if (te == null)
5350 return false;
5353 // Replace original type name, error reporting can use fully resolved name
5355 type_name = te;
5357 member_type = te.Type;
5358 return true;
5363 // Abstract class for all fields
5365 abstract public class FieldBase : MemberBase {
5366 public FieldBuilder FieldBuilder;
5367 public Status status;
5368 protected Expression initializer;
5370 [Flags]
5371 public enum Status : byte {
5372 HAS_OFFSET = 4 // Used by FieldMember.
5375 static readonly string[] attribute_targets = new string [] { "field" };
5377 protected FieldBase (DeclSpace parent, FullNamedExpression type, int mod,
5378 int allowed_mod, MemberName name, Attributes attrs)
5379 : base (parent, null, type, mod, allowed_mod | Modifiers.ABSTRACT, Modifiers.PRIVATE,
5380 name, attrs)
5382 if ((mod & Modifiers.ABSTRACT) != 0)
5383 Report.Error (681, Location, "The modifier 'abstract' is not valid on fields. Try using a property instead");
5386 public override AttributeTargets AttributeTargets {
5387 get {
5388 return AttributeTargets.Field;
5392 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
5394 if (a.Type == pa.FieldOffset) {
5395 status |= Status.HAS_OFFSET;
5397 if (!Parent.PartialContainer.HasExplicitLayout) {
5398 Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)");
5399 return;
5402 if ((ModFlags & Modifiers.STATIC) != 0 || this is Const) {
5403 Report.Error (637, Location, "The FieldOffset attribute is not allowed on static or const fields");
5404 return;
5408 #if NET_2_0
5409 if (a.Type == pa.FixedBuffer) {
5410 Report.Error (1716, Location, "Do not use 'System.Runtime.CompilerServices.FixedBuffer' attribute. Use the 'fixed' field modifier instead");
5411 return;
5413 #endif
5415 #if !NET_2_0
5416 if (a.Type == pa.MarshalAs) {
5417 UnmanagedMarshal marshal = a.GetMarshal (this);
5418 if (marshal != null) {
5419 FieldBuilder.SetMarshal (marshal);
5421 return;
5423 #endif
5424 if ((a.HasSecurityAttribute)) {
5425 a.Error_InvalidSecurityParent ();
5426 return;
5429 FieldBuilder.SetCustomAttribute (cb);
5432 protected override bool CheckBase ()
5434 if (!base.CheckBase ())
5435 return false;
5437 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Name, false);
5438 if (conflict_symbol == null) {
5439 if ((ModFlags & Modifiers.NEW) != 0) {
5440 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
5442 return true;
5445 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE | Modifiers.BACKING_FIELD)) == 0) {
5446 Report.SymbolRelatedToPreviousError (conflict_symbol);
5447 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
5448 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
5451 return true;
5454 protected override void DoMemberTypeDependentChecks ()
5456 base.DoMemberTypeDependentChecks ();
5458 if (TypeManager.IsGenericParameter (MemberType))
5459 return;
5461 if (MemberType.IsSealed && MemberType.IsAbstract) {
5462 Error_VariableOfStaticClass (Location, GetSignatureForError (), MemberType);
5465 CheckBase ();
5466 IsTypePermitted ();
5470 // Represents header string for documentation comment.
5472 public override string DocCommentHeader {
5473 get { return "F:"; }
5476 public override void Emit ()
5478 if (TypeManager.IsDynamicType (member_type))
5479 PredefinedAttributes.Get.Dynamic.EmitAttribute (FieldBuilder);
5481 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
5482 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (FieldBuilder);
5484 if (OptAttributes != null) {
5485 OptAttributes.Emit ();
5488 if (((status & Status.HAS_OFFSET) == 0) && (ModFlags & (Modifiers.STATIC | Modifiers.BACKING_FIELD)) == 0 && Parent.PartialContainer.HasExplicitLayout) {
5489 Report.Error (625, Location, "`{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute", GetSignatureForError ());
5492 base.Emit ();
5495 public static void Error_VariableOfStaticClass (Location loc, string variable_name, Type static_class)
5497 Report.SymbolRelatedToPreviousError (static_class);
5498 Report.Error (723, loc, "`{0}': cannot declare variables of static types",
5499 variable_name);
5502 public Expression Initializer {
5503 set {
5504 if (value != null) {
5505 this.initializer = value;
5510 protected virtual bool IsFieldClsCompliant {
5511 get {
5512 if (FieldBuilder == null)
5513 return true;
5515 return AttributeTester.IsClsCompliant (FieldBuilder.FieldType);
5519 public override string[] ValidAttributeTargets
5521 get {
5522 return attribute_targets;
5526 protected override bool VerifyClsCompliance ()
5528 if (!base.VerifyClsCompliance ())
5529 return false;
5531 if (!IsFieldClsCompliant) {
5532 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
5533 GetSignatureForError ());
5535 return true;
5538 public void SetAssigned ()
5540 caching_flags |= Flags.IsAssigned;
5544 interface IFixedBuffer
5546 FieldInfo Element { get; }
5547 Type ElementType { get; }
5550 public class FixedFieldExternal: IFixedBuffer
5552 FieldInfo element_field;
5554 public FixedFieldExternal (FieldInfo fi)
5556 element_field = fi.FieldType.GetField (FixedField.FixedElementName);
5559 #region IFixedField Members
5561 public FieldInfo Element {
5562 get {
5563 return element_field;
5567 public Type ElementType {
5568 get {
5569 return element_field.FieldType;
5573 #endregion
5576 /// <summary>
5577 /// Fixed buffer implementation
5578 /// </summary>
5579 public class FixedField : FieldBase, IFixedBuffer
5581 public const string FixedElementName = "FixedElementField";
5582 static int GlobalCounter = 0;
5583 static object[] ctor_args = new object[] { (short)LayoutKind.Sequential };
5584 static FieldInfo[] fi;
5586 TypeBuilder fixed_buffer_type;
5587 FieldBuilder element;
5588 Expression size_expr;
5590 const int AllowedModifiers =
5591 Modifiers.NEW |
5592 Modifiers.PUBLIC |
5593 Modifiers.PROTECTED |
5594 Modifiers.INTERNAL |
5595 Modifiers.PRIVATE;
5597 public FixedField (DeclSpace parent, FullNamedExpression type, int mod, string name,
5598 Expression size_expr, Attributes attrs, Location loc):
5599 base (parent, type, mod, AllowedModifiers, new MemberName (name, loc), attrs)
5601 if (RootContext.Version < LanguageVersion.ISO_2)
5602 Report.FeatureIsNotAvailable (loc, "fixed size buffers");
5604 this.size_expr = size_expr;
5607 public override bool Define()
5609 if (!base.Define ())
5610 return false;
5612 if (!TypeManager.IsPrimitiveType (MemberType)) {
5613 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",
5614 GetSignatureForError ());
5617 // Create nested fixed buffer container
5618 string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++);
5619 fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name, Parent.Module.DefaultCharSetType |
5620 TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, TypeManager.value_type);
5622 element = fixed_buffer_type.DefineField (FixedElementName, MemberType, FieldAttributes.Public);
5623 RootContext.RegisterCompilerGeneratedType (fixed_buffer_type);
5625 FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, Modifiers.FieldAttr (ModFlags));
5626 Parent.MemberCache.AddMember (FieldBuilder, this);
5627 TypeManager.RegisterFieldBase (FieldBuilder, this);
5629 return true;
5632 protected override void DoMemberTypeIndependentChecks ()
5634 base.DoMemberTypeIndependentChecks ();
5636 if (!Parent.IsInUnsafeScope)
5637 Expression.UnsafeError (Location);
5639 if (Parent.PartialContainer.Kind != Kind.Struct) {
5640 Report.Error (1642, Location, "`{0}': Fixed size buffer fields may only be members of structs",
5641 GetSignatureForError ());
5645 public override void Emit()
5647 EmitContext ec = new EmitContext (this, Parent, Location, null, TypeManager.void_type, ModFlags);
5648 Constant c = size_expr.ResolveAsConstant (ec, this);
5649 if (c == null)
5650 return;
5652 IntConstant buffer_size_const = c.ImplicitConversionRequired (ec, TypeManager.int32_type, Location) as IntConstant;
5653 if (buffer_size_const == null)
5654 return;
5656 int buffer_size = buffer_size_const.Value;
5658 if (buffer_size <= 0) {
5659 Report.Error (1665, Location, "`{0}': Fixed size buffers must have a length greater than zero", GetSignatureForError ());
5660 return;
5663 int type_size = Expression.GetTypeSize (MemberType);
5665 if (buffer_size > int.MaxValue / type_size) {
5666 Report.Error (1664, Location, "Fixed size buffer `{0}' of length `{1}' and type `{2}' exceeded 2^31 limit",
5667 GetSignatureForError (), buffer_size.ToString (), TypeManager.CSharpName (MemberType));
5668 return;
5671 buffer_size *= type_size;
5672 EmitFieldSize (buffer_size);
5674 PredefinedAttributes.Get.UnsafeValueType.EmitAttribute (fixed_buffer_type);
5676 base.Emit ();
5679 void EmitFieldSize (int buffer_size)
5681 CustomAttributeBuilder cab;
5682 PredefinedAttribute pa;
5684 pa = PredefinedAttributes.Get.StructLayout;
5685 if (pa.Constructor == null &&
5686 !pa.ResolveConstructor (Location, TypeManager.short_type))
5687 return;
5689 // TODO: It's not cleared
5690 if (fi == null)
5691 fi = new FieldInfo[] { pa.Type.GetField ("Size") };
5693 object[] fi_val = new object[] { buffer_size };
5694 cab = new CustomAttributeBuilder (pa.Constructor,
5695 ctor_args, fi, fi_val);
5696 fixed_buffer_type.SetCustomAttribute (cab);
5699 // Don't emit FixedBufferAttribute attribute for private types
5701 if ((ModFlags & Modifiers.PRIVATE) != 0)
5702 return;
5704 pa = PredefinedAttributes.Get.FixedBuffer;
5705 if (pa.Constructor == null &&
5706 !pa.ResolveConstructor (Location, TypeManager.type_type, TypeManager.int32_type))
5707 return;
5709 cab = new CustomAttributeBuilder (pa.Constructor, new object[] { MemberType, buffer_size });
5710 FieldBuilder.SetCustomAttribute (cab);
5713 protected override bool IsFieldClsCompliant {
5714 get {
5715 return false;
5719 public void SetCharSet (TypeAttributes ta)
5721 TypeAttributes cta = fixed_buffer_type.Attributes;
5722 if ((cta & TypeAttributes.UnicodeClass) != (ta & TypeAttributes.UnicodeClass))
5723 SetTypeBuilderCharSet ((cta & ~TypeAttributes.AutoClass) | TypeAttributes.UnicodeClass);
5724 else if ((cta & TypeAttributes.AutoClass) != (ta & TypeAttributes.AutoClass))
5725 SetTypeBuilderCharSet ((cta & ~TypeAttributes.UnicodeClass) | TypeAttributes.AutoClass);
5726 else if (cta == 0 && ta != 0)
5727 SetTypeBuilderCharSet (cta & ~(TypeAttributes.UnicodeClass | TypeAttributes.AutoClass));
5730 void SetTypeBuilderCharSet (TypeAttributes ta)
5732 MethodInfo mi = typeof (TypeBuilder).GetMethod ("SetCharSet", BindingFlags.Instance | BindingFlags.NonPublic);
5733 if (mi == null) {
5734 Report.RuntimeMissingSupport (Location, "TypeBuilder::SetCharSet");
5735 } else {
5736 mi.Invoke (fixed_buffer_type, new object [] { ta });
5740 #region IFixedField Members
5742 public FieldInfo Element {
5743 get {
5744 return element;
5748 public Type ElementType {
5749 get {
5750 return MemberType;
5754 #endregion
5758 // The Field class is used to represents class/struct fields during parsing.
5760 public class Field : FieldBase {
5761 // <summary>
5762 // Modifiers allowed in a class declaration
5763 // </summary>
5764 const int AllowedModifiers =
5765 Modifiers.NEW |
5766 Modifiers.PUBLIC |
5767 Modifiers.PROTECTED |
5768 Modifiers.INTERNAL |
5769 Modifiers.PRIVATE |
5770 Modifiers.STATIC |
5771 Modifiers.VOLATILE |
5772 Modifiers.UNSAFE |
5773 Modifiers.READONLY;
5775 public Field (DeclSpace parent, FullNamedExpression type, int mod, MemberName name,
5776 Attributes attrs)
5777 : base (parent, type, mod, AllowedModifiers, name, attrs)
5781 bool CanBeVolatile ()
5783 if (TypeManager.IsReferenceType (MemberType))
5784 return true;
5786 if (MemberType == TypeManager.bool_type || MemberType == TypeManager.char_type ||
5787 MemberType == TypeManager.sbyte_type || MemberType == TypeManager.byte_type ||
5788 MemberType == TypeManager.short_type || MemberType == TypeManager.ushort_type ||
5789 MemberType == TypeManager.int32_type || MemberType == TypeManager.uint32_type ||
5790 MemberType == TypeManager.float_type ||
5791 MemberType == TypeManager.intptr_type || MemberType == TypeManager.uintptr_type)
5792 return true;
5794 if (TypeManager.IsEnumType (MemberType))
5795 return true;
5797 return false;
5800 bool CheckStructLayout (Type type, bool isStatic)
5802 if (TypeManager.IsBuiltinType (type))
5803 return true;
5805 if (isStatic) {
5806 if (!TypeManager.IsValueType (type) || TypeManager.IsEqual (type, Parent.TypeBuilder))
5807 return true;
5810 if (!TypeManager.IsEqual (TypeManager.DropGenericTypeArguments (type), Parent.TypeBuilder)) {
5811 if (!TypeManager.IsGenericType (type))
5812 return true;
5814 foreach (Type t in TypeManager.GetTypeArguments (type)) {
5815 if (!CheckStructLayout (t, false))
5816 return false;
5818 return true;
5821 Report.Error (523, Location,
5822 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
5823 GetSignatureForError (), TypeManager.CSharpName (MemberType));
5824 return false;
5827 public override bool Define ()
5829 if (!base.Define ())
5830 return false;
5832 try {
5833 #if GMCS_SOURCE
5834 Type[] required_modifier = null;
5835 if ((ModFlags & Modifiers.VOLATILE) != 0) {
5836 if (TypeManager.isvolatile_type == null)
5837 TypeManager.isvolatile_type = TypeManager.CoreLookupType (
5838 "System.Runtime.CompilerServices", "IsVolatile", Kind.Class, true);
5840 if (TypeManager.isvolatile_type != null)
5841 required_modifier = new Type [] { TypeManager.isvolatile_type };
5844 FieldBuilder = Parent.TypeBuilder.DefineField (
5845 Name, MemberType, required_modifier, null, Modifiers.FieldAttr (ModFlags));
5846 #else
5847 FieldBuilder = Parent.TypeBuilder.DefineField (
5848 Name, MemberType, Modifiers.FieldAttr (ModFlags));
5849 #endif
5850 // Don't cache inaccessible fields
5851 if ((ModFlags & Modifiers.BACKING_FIELD) == 0) {
5852 Parent.MemberCache.AddMember (FieldBuilder, this);
5855 TypeManager.RegisterFieldBase (FieldBuilder, this);
5857 catch (ArgumentException) {
5858 Report.RuntimeMissingSupport (Location, "`void' or `void*' field type");
5859 return false;
5862 if (initializer != null) {
5863 ((TypeContainer) Parent).RegisterFieldForInitialization (this,
5864 new FieldInitializer (FieldBuilder, initializer, this));
5865 } else {
5866 if (Parent.PartialContainer.Kind == Kind.Struct)
5867 CheckStructLayout (member_type, (ModFlags & Modifiers.STATIC) != 0);
5870 return true;
5873 protected override void DoMemberTypeDependentChecks ()
5875 base.DoMemberTypeDependentChecks ();
5877 if ((ModFlags & Modifiers.VOLATILE) != 0) {
5878 if (!CanBeVolatile ()) {
5879 Report.Error (677, Location, "`{0}': A volatile field cannot be of the type `{1}'",
5880 GetSignatureForError (), TypeManager.CSharpName (MemberType));
5883 if ((ModFlags & Modifiers.READONLY) != 0) {
5884 Report.Error (678, Location, "`{0}': A field cannot be both volatile and readonly",
5885 GetSignatureForError ());
5890 protected override bool VerifyClsCompliance ()
5892 if (!base.VerifyClsCompliance ())
5893 return false;
5895 if ((ModFlags & Modifiers.VOLATILE) != 0) {
5896 Report.Warning (3026, 1, Location, "CLS-compliant field `{0}' cannot be volatile", GetSignatureForError ());
5899 return true;
5904 // `set' and `get' accessors are represented with an Accessor.
5906 public class Accessor {
5908 // Null if the accessor is empty, or a Block if not
5910 public const int AllowedModifiers =
5911 Modifiers.PUBLIC |
5912 Modifiers.PROTECTED |
5913 Modifiers.INTERNAL |
5914 Modifiers.PRIVATE;
5916 public ToplevelBlock Block;
5917 public Attributes Attributes;
5918 public Location Location;
5919 public int ModFlags;
5920 public ParametersCompiled Parameters;
5922 public Accessor (ToplevelBlock b, int mod, Attributes attrs, ParametersCompiled p, Location loc)
5924 Block = b;
5925 Attributes = attrs;
5926 Location = loc;
5927 Parameters = p;
5928 ModFlags = Modifiers.Check (AllowedModifiers, mod, 0, loc);
5932 // Ooouh Martin, templates are missing here.
5933 // When it will be possible move here a lot of child code and template method type.
5934 public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData {
5935 protected MethodData method_data;
5936 protected ToplevelBlock block;
5937 protected ListDictionary declarative_security;
5939 // The accessor are created even if they are not wanted.
5940 // But we need them because their names are reserved.
5941 // Field says whether accessor will be emited or not
5942 public readonly bool IsDummy;
5944 protected readonly string prefix;
5946 ReturnParameter return_attributes;
5948 public AbstractPropertyEventMethod (PropertyBasedMember member, string prefix)
5949 : base (member.Parent, SetupName (prefix, member, member.Location), null)
5951 this.prefix = prefix;
5952 IsDummy = true;
5955 public AbstractPropertyEventMethod (InterfaceMemberBase member, Accessor accessor,
5956 string prefix)
5957 : base (member.Parent, SetupName (prefix, member, accessor.Location),
5958 accessor.Attributes)
5960 this.prefix = prefix;
5961 this.block = accessor.Block;
5964 static MemberName SetupName (string prefix, InterfaceMemberBase member, Location loc)
5966 return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc);
5969 public void UpdateName (InterfaceMemberBase member)
5971 SetMemberName (SetupName (prefix, member, Location));
5974 #region IMethodData Members
5976 public ToplevelBlock Block {
5977 get {
5978 return block;
5981 set {
5982 block = value;
5986 public CallingConventions CallingConventions {
5987 get {
5988 return CallingConventions.Standard;
5992 public bool IsExcluded ()
5994 return false;
5997 GenericMethod IMethodData.GenericMethod {
5998 get {
5999 return null;
6003 public MemberName MethodName {
6004 get {
6005 return MemberName;
6009 public Type[] ParameterTypes {
6010 get {
6011 return ParameterInfo.Types;
6015 public abstract ParametersCompiled ParameterInfo { get ; }
6016 public abstract Type ReturnType { get; }
6017 public abstract EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig);
6019 #endregion
6021 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6023 if (a.Type == pa.CLSCompliant || a.Type == pa.Obsolete || a.Type == pa.Conditional) {
6024 Report.Error (1667, a.Location,
6025 "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
6026 TypeManager.CSharpName (a.Type), a.GetValidTargets ());
6027 return;
6030 if (a.IsValidSecurityAttribute ()) {
6031 if (declarative_security == null)
6032 declarative_security = new ListDictionary ();
6033 a.ExtractSecurityPermissionSet (declarative_security);
6034 return;
6037 if (a.Target == AttributeTargets.Method) {
6038 method_data.MethodBuilder.SetCustomAttribute (cb);
6039 return;
6042 if (a.Target == AttributeTargets.ReturnValue) {
6043 if (return_attributes == null)
6044 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
6046 return_attributes.ApplyAttributeBuilder (a, cb, pa);
6047 return;
6050 ApplyToExtraTarget (a, cb, pa);
6053 protected virtual void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6055 throw new NotSupportedException ("You forgot to define special attribute target handling");
6058 // It is not supported for the accessors
6059 public sealed override bool Define()
6061 throw new NotSupportedException ();
6064 public virtual void Emit (DeclSpace parent)
6066 method_data.Emit (parent);
6068 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
6069 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (method_data.MethodBuilder);
6070 if (((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0))
6071 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (method_data.MethodBuilder);
6073 if (TypeManager.IsDynamicType (ReturnType)) {
6074 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
6075 return_attributes.EmitPredefined (PredefinedAttributes.Get.Dynamic, Location);
6078 if (OptAttributes != null)
6079 OptAttributes.Emit ();
6081 if (declarative_security != null) {
6082 foreach (DictionaryEntry de in declarative_security) {
6083 method_data.MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
6087 block = null;
6090 public override bool EnableOverloadChecks (MemberCore overload)
6092 // This can only happen with indexers and it will
6093 // be catched as indexer difference
6094 if (overload is AbstractPropertyEventMethod)
6095 return true;
6097 if (overload is MethodCore) {
6098 caching_flags |= Flags.MethodOverloadsExist;
6099 return true;
6101 return false;
6104 public override bool IsClsComplianceRequired()
6106 return false;
6109 public bool IsDuplicateImplementation (MethodCore method)
6111 if (!MemberName.Equals (method.MemberName))
6112 return false;
6114 Type[] param_types = method.ParameterTypes;
6116 if (param_types == null || param_types.Length != ParameterTypes.Length)
6117 return false;
6119 for (int i = 0; i < param_types.Length; i++)
6120 if (param_types [i] != ParameterTypes [i])
6121 return false;
6123 Report.SymbolRelatedToPreviousError (method);
6124 Report.Error (82, Location, "A member `{0}' is already reserved",
6125 method.GetSignatureForError ());
6126 return true;
6129 public override bool IsUsed
6131 get {
6132 if (IsDummy)
6133 return false;
6135 return base.IsUsed;
6140 // Represents header string for documentation comment.
6142 public override string DocCommentHeader {
6143 get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
6146 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
6151 // Properties and Indexers both generate PropertyBuilders, we use this to share
6152 // their common bits.
6154 abstract public class PropertyBase : PropertyBasedMember {
6156 public class GetMethod : PropertyMethod
6158 static string[] attribute_targets = new string [] { "method", "return" };
6160 public GetMethod (PropertyBase method):
6161 base (method, "get_")
6165 public GetMethod (PropertyBase method, Accessor accessor):
6166 base (method, accessor, "get_")
6170 public override MethodBuilder Define (DeclSpace parent)
6172 base.Define (parent);
6174 if (IsDummy)
6175 return null;
6177 method_data = new MethodData (method, ModFlags, flags, this);
6179 if (!method_data.Define (parent, method.GetFullName (MemberName)))
6180 return null;
6182 return method_data.MethodBuilder;
6185 public override Type ReturnType {
6186 get {
6187 return method.MemberType;
6191 public override ParametersCompiled ParameterInfo {
6192 get {
6193 return ParametersCompiled.EmptyReadOnlyParameters;
6197 public override string[] ValidAttributeTargets {
6198 get {
6199 return attribute_targets;
6204 public class SetMethod : PropertyMethod {
6206 static string[] attribute_targets = new string [] { "method", "param", "return" };
6207 ImplicitParameter param_attr;
6208 protected ParametersCompiled parameters;
6210 public SetMethod (PropertyBase method) :
6211 base (method, "set_")
6213 parameters = new ParametersCompiled (
6214 new Parameter (method.type_name, "value", Parameter.Modifier.NONE, null, Location));
6217 public SetMethod (PropertyBase method, Accessor accessor):
6218 base (method, accessor, "set_")
6220 this.parameters = accessor.Parameters;
6223 protected override void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6225 if (a.Target == AttributeTargets.Parameter) {
6226 if (param_attr == null)
6227 param_attr = new ImplicitParameter (method_data.MethodBuilder);
6229 param_attr.ApplyAttributeBuilder (a, cb, pa);
6230 return;
6233 base.ApplyAttributeBuilder (a, cb, pa);
6236 public override ParametersCompiled ParameterInfo {
6237 get {
6238 return parameters;
6242 public override MethodBuilder Define (DeclSpace parent)
6244 parameters.Resolve (ResolveContext);
6246 base.Define (parent);
6248 if (IsDummy)
6249 return null;
6251 method_data = new MethodData (method, ModFlags, flags, this);
6253 if (!method_data.Define (parent, method.GetFullName (MemberName)))
6254 return null;
6256 return method_data.MethodBuilder;
6259 public override Type ReturnType {
6260 get {
6261 return TypeManager.void_type;
6265 public override string[] ValidAttributeTargets {
6266 get {
6267 return attribute_targets;
6272 static string[] attribute_targets = new string [] { "property" };
6274 public abstract class PropertyMethod : AbstractPropertyEventMethod
6276 protected readonly PropertyBase method;
6277 protected MethodAttributes flags;
6279 public PropertyMethod (PropertyBase method, string prefix)
6280 : base (method, prefix)
6282 this.method = method;
6283 this.ModFlags = method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE);
6286 public PropertyMethod (PropertyBase method, Accessor accessor,
6287 string prefix)
6288 : base (method, accessor, prefix)
6290 this.method = method;
6291 this.ModFlags = accessor.ModFlags | (method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE));
6293 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
6294 Report.FeatureIsNotAvailable (Location, "access modifiers on properties");
6298 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6300 if (a.IsInternalMethodImplAttribute) {
6301 method.is_external_implementation = true;
6304 base.ApplyAttributeBuilder (a, cb, pa);
6307 public override AttributeTargets AttributeTargets {
6308 get {
6309 return AttributeTargets.Method;
6313 public override bool IsClsComplianceRequired ()
6315 return method.IsClsComplianceRequired ();
6318 public virtual MethodBuilder Define (DeclSpace parent)
6320 CheckForDuplications ();
6322 if (IsDummy) {
6323 if (method.InterfaceType != null && parent.PartialContainer.PendingImplementations != null) {
6324 MethodInfo mi = parent.PartialContainer.PendingImplementations.IsInterfaceMethod (
6325 MethodName.Name, method.InterfaceType, new MethodData (method, ModFlags, flags, this));
6326 if (mi != null) {
6327 Report.SymbolRelatedToPreviousError (mi);
6328 Report.Error (551, Location, "Explicit interface implementation `{0}' is missing accessor `{1}'",
6329 method.GetSignatureForError (), TypeManager.CSharpSignature (mi, true));
6332 return null;
6335 TypeContainer container = parent.PartialContainer;
6338 // Check for custom access modifier
6340 if ((ModFlags & Modifiers.Accessibility) == 0) {
6341 ModFlags |= method.ModFlags;
6342 flags = method.flags;
6343 } else {
6344 if (container.Kind == Kind.Interface)
6345 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
6346 GetSignatureForError ());
6348 if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
6349 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
6352 CheckModifiers (ModFlags);
6353 ModFlags |= (method.ModFlags & (~Modifiers.Accessibility));
6354 ModFlags |= Modifiers.PROPERTY_CUSTOM;
6355 flags = Modifiers.MethodAttr (ModFlags);
6356 flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
6359 CheckAbstractAndExtern (block != null);
6361 if (block != null && block.IsIterator)
6362 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
6364 return null;
6367 public bool HasCustomAccessModifier {
6368 get {
6369 return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
6373 public PropertyBase Property {
6374 get {
6375 return method;
6379 public override EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
6381 return new EmitContext (this,
6382 ds, method.ds, method.Location, ig, ReturnType,
6383 method.ModFlags, false);
6386 public override ObsoleteAttribute GetObsoleteAttribute ()
6388 return method.GetObsoleteAttribute ();
6391 public override string GetSignatureForError()
6393 return method.GetSignatureForError () + '.' + prefix.Substring (0, 3);
6396 void CheckModifiers (int modflags)
6398 modflags &= Modifiers.Accessibility;
6399 int flags = 0;
6400 int mflags = method.ModFlags & Modifiers.Accessibility;
6402 if ((mflags & Modifiers.PUBLIC) != 0) {
6403 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
6405 else if ((mflags & Modifiers.PROTECTED) != 0) {
6406 if ((mflags & Modifiers.INTERNAL) != 0)
6407 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL;
6409 flags |= Modifiers.PRIVATE;
6411 else if ((mflags & Modifiers.INTERNAL) != 0)
6412 flags |= Modifiers.PRIVATE;
6414 if ((mflags == modflags) || (modflags & (~flags)) != 0) {
6415 Report.Error (273, Location,
6416 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
6417 GetSignatureForError (), method.GetSignatureForError ());
6421 protected bool CheckForDuplications ()
6423 if ((caching_flags & Flags.MethodOverloadsExist) == 0)
6424 return true;
6426 return Parent.MemberCache.CheckExistingMembersOverloads (this, Name, ParameterInfo);
6430 public PropertyMethod Get, Set;
6431 public PropertyBuilder PropertyBuilder;
6432 public MethodBuilder GetBuilder, SetBuilder;
6434 protected bool define_set_first = false;
6436 public PropertyBase (DeclSpace parent, FullNamedExpression type, int mod_flags,
6437 int allowed_mod, MemberName name,
6438 Attributes attrs, bool define_set_first)
6439 : base (parent, null, type, mod_flags, allowed_mod, name, attrs)
6441 this.define_set_first = define_set_first;
6444 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6446 if (a.HasSecurityAttribute) {
6447 a.Error_InvalidSecurityParent ();
6448 return;
6451 PropertyBuilder.SetCustomAttribute (cb);
6454 public override AttributeTargets AttributeTargets {
6455 get {
6456 return AttributeTargets.Property;
6460 protected override void DoMemberTypeDependentChecks ()
6462 base.DoMemberTypeDependentChecks ();
6464 IsTypePermitted ();
6465 #if MS_COMPATIBLE
6466 if (MemberType.IsGenericParameter)
6467 return;
6468 #endif
6470 if ((MemberType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
6471 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
6475 protected override void DoMemberTypeIndependentChecks ()
6477 base.DoMemberTypeIndependentChecks ();
6480 // Accessors modifiers check
6482 if ((Get.ModFlags & Modifiers.Accessibility) != 0 &&
6483 (Set.ModFlags & Modifiers.Accessibility) != 0) {
6484 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
6485 GetSignatureForError ());
6488 if ((ModFlags & Modifiers.OVERRIDE) == 0 &&
6489 (Get.IsDummy && (Set.ModFlags & Modifiers.Accessibility) != 0) ||
6490 (Set.IsDummy && (Get.ModFlags & Modifiers.Accessibility) != 0)) {
6491 Report.Error (276, Location,
6492 "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
6493 GetSignatureForError ());
6497 bool DefineGet ()
6499 GetBuilder = Get.Define (Parent);
6500 return (Get.IsDummy) ? true : GetBuilder != null;
6503 bool DefineSet (bool define)
6505 if (!define)
6506 return true;
6508 SetBuilder = Set.Define (Parent);
6509 return (Set.IsDummy) ? true : SetBuilder != null;
6512 protected bool DefineAccessors ()
6514 return DefineSet (define_set_first) &&
6515 DefineGet () &&
6516 DefineSet (!define_set_first);
6519 protected abstract PropertyInfo ResolveBaseProperty ();
6521 // TODO: rename to Resolve......
6522 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
6524 PropertyInfo base_property = ResolveBaseProperty ();
6525 if (base_property == null)
6526 return null;
6528 base_ret_type = base_property.PropertyType;
6529 MethodInfo get_accessor = base_property.GetGetMethod (true);
6530 MethodInfo set_accessor = base_property.GetSetMethod (true);
6531 MethodAttributes get_accessor_access = 0, set_accessor_access = 0;
6534 // Check base property accessors conflict
6536 if ((ModFlags & (Modifiers.OVERRIDE | Modifiers.NEW)) == Modifiers.OVERRIDE) {
6537 if (get_accessor == null) {
6538 if (Get != null && !Get.IsDummy) {
6539 Report.SymbolRelatedToPreviousError (base_property);
6540 Report.Error (545, Location,
6541 "`{0}.get': cannot override because `{1}' does not have an overridable get accessor",
6542 GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6544 } else {
6545 get_accessor_access = get_accessor.Attributes & MethodAttributes.MemberAccessMask;
6547 if (!Get.IsDummy && !CheckAccessModifiers (
6548 Modifiers.MethodAttr (Get.ModFlags) & MethodAttributes.MemberAccessMask, get_accessor_access, get_accessor))
6549 Error_CannotChangeAccessModifiers (Get.Location, get_accessor, get_accessor_access, ".get");
6552 if (set_accessor == null) {
6553 if (Set != null && !Set.IsDummy) {
6554 Report.SymbolRelatedToPreviousError (base_property);
6555 Report.Error (546, Location,
6556 "`{0}.set': cannot override because `{1}' does not have an overridable set accessor",
6557 GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6559 } else {
6560 set_accessor_access = set_accessor.Attributes & MethodAttributes.MemberAccessMask;
6562 if (!Set.IsDummy && !CheckAccessModifiers (
6563 Modifiers.MethodAttr (Set.ModFlags) & MethodAttributes.MemberAccessMask, set_accessor_access, set_accessor))
6564 Error_CannotChangeAccessModifiers (Set.Location, set_accessor, set_accessor_access, ".set");
6568 // When one accessor does not exist and property hides base one
6569 // we need to propagate this upwards
6570 if (set_accessor == null)
6571 set_accessor = get_accessor;
6574 // Get the less restrictive access
6576 return get_accessor_access > set_accessor_access ? get_accessor : set_accessor;
6579 public override void Emit ()
6582 // The PropertyBuilder can be null for explicit implementations, in that
6583 // case, we do not actually emit the ".property", so there is nowhere to
6584 // put the attribute
6586 if (PropertyBuilder != null) {
6587 if (OptAttributes != null)
6588 OptAttributes.Emit ();
6590 if (TypeManager.IsDynamicType (member_type))
6591 PredefinedAttributes.Get.Dynamic.EmitAttribute (PropertyBuilder);
6594 if (!Get.IsDummy)
6595 Get.Emit (Parent);
6597 if (!Set.IsDummy)
6598 Set.Emit (Parent);
6600 base.Emit ();
6603 /// <summary>
6604 /// Tests whether accessors are not in collision with some method (CS0111)
6605 /// </summary>
6606 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6608 return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
6611 public override bool IsUsed
6613 get {
6614 if (IsExplicitImpl)
6615 return true;
6617 return Get.IsUsed | Set.IsUsed;
6621 protected override void SetMemberName (MemberName new_name)
6623 base.SetMemberName (new_name);
6625 Get.UpdateName (this);
6626 Set.UpdateName (this);
6629 public override string[] ValidAttributeTargets {
6630 get {
6631 return attribute_targets;
6636 // Represents header string for documentation comment.
6638 public override string DocCommentHeader {
6639 get { return "P:"; }
6643 public class Property : PropertyBase
6645 public sealed class BackingField : Field
6647 readonly Property property;
6649 public BackingField (Property p)
6650 : base (p.Parent, p.type_name,
6651 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
6652 new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
6654 this.property = p;
6657 public override string GetSignatureForError ()
6659 return property.GetSignatureForError ();
6663 const int AllowedModifiers =
6664 Modifiers.NEW |
6665 Modifiers.PUBLIC |
6666 Modifiers.PROTECTED |
6667 Modifiers.INTERNAL |
6668 Modifiers.PRIVATE |
6669 Modifiers.STATIC |
6670 Modifiers.SEALED |
6671 Modifiers.OVERRIDE |
6672 Modifiers.ABSTRACT |
6673 Modifiers.UNSAFE |
6674 Modifiers.EXTERN |
6675 Modifiers.VIRTUAL;
6677 const int AllowedInterfaceModifiers =
6678 Modifiers.NEW;
6680 public Property (DeclSpace parent, FullNamedExpression type, int mod,
6681 MemberName name, Attributes attrs, Accessor get_block,
6682 Accessor set_block, bool define_set_first)
6683 : this (parent, type, mod, name, attrs, get_block, set_block,
6684 define_set_first, null)
6688 public Property (DeclSpace parent, FullNamedExpression type, int mod,
6689 MemberName name, Attributes attrs, Accessor get_block,
6690 Accessor set_block, bool define_set_first, Block current_block)
6691 : base (parent, type, mod,
6692 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
6693 name, attrs, define_set_first)
6695 if (get_block == null)
6696 Get = new GetMethod (this);
6697 else
6698 Get = new GetMethod (this, get_block);
6700 if (set_block == null)
6701 Set = new SetMethod (this);
6702 else
6703 Set = new SetMethod (this, set_block);
6705 if (!IsInterface && (mod & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
6706 get_block != null && get_block.Block == null &&
6707 set_block != null && set_block.Block == null) {
6708 if (RootContext.Version <= LanguageVersion.ISO_2)
6709 Report.FeatureIsNotAvailable (Location, "automatically implemented properties");
6711 Get.ModFlags |= Modifiers.COMPILER_GENERATED;
6712 Set.ModFlags |= Modifiers.COMPILER_GENERATED;
6716 void CreateAutomaticProperty ()
6718 // Create backing field
6719 Field field = new BackingField (this);
6720 if (!field.Define ())
6721 return;
6723 Parent.PartialContainer.AddField (field);
6725 FieldExpr fe = new FieldExpr (field.FieldBuilder, Location);
6726 if ((field.ModFlags & Modifiers.STATIC) == 0)
6727 fe.InstanceExpression = new CompilerGeneratedThis (fe.Type, Location);
6729 // Create get block
6730 Get.Block = new ToplevelBlock (ParametersCompiled.EmptyReadOnlyParameters, Location);
6731 Return r = new Return (fe, Location);
6732 Get.Block.AddStatement (r);
6734 // Create set block
6735 Set.Block = new ToplevelBlock (Set.ParameterInfo, Location);
6736 Assign a = new SimpleAssign (fe, new SimpleName ("value", Location));
6737 Set.Block.AddStatement (new StatementExpression (a));
6740 public override bool Define ()
6742 if (!base.Define ())
6743 return false;
6745 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6747 if ((Get.ModFlags & Modifiers.COMPILER_GENERATED) != 0)
6748 CreateAutomaticProperty ();
6750 if (!DefineAccessors ())
6751 return false;
6753 if (!CheckBase ())
6754 return false;
6756 // FIXME - PropertyAttributes.HasDefault ?
6758 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6759 GetFullName (MemberName), PropertyAttributes.None, MemberType, null);
6761 if (!Get.IsDummy) {
6762 PropertyBuilder.SetGetMethod (GetBuilder);
6763 Parent.MemberCache.AddMember (GetBuilder, Get);
6766 if (!Set.IsDummy) {
6767 PropertyBuilder.SetSetMethod (SetBuilder);
6768 Parent.MemberCache.AddMember (SetBuilder, Set);
6771 TypeManager.RegisterProperty (PropertyBuilder, this);
6772 Parent.MemberCache.AddMember (PropertyBuilder, this);
6773 return true;
6776 public override void Emit ()
6778 if (((Set.ModFlags | Get.ModFlags) & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) {
6779 Report.Error (842, Location,
6780 "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
6781 GetSignatureForError ());
6784 base.Emit ();
6787 protected override PropertyInfo ResolveBaseProperty ()
6789 return Parent.PartialContainer.BaseCache.FindMemberToOverride (
6790 Parent.TypeBuilder, Name, ParametersCompiled.EmptyReadOnlyParameters, null, true) as PropertyInfo;
6794 /// </summary>
6795 /// Gigantic workaround for lameness in SRE follows :
6796 /// This class derives from EventInfo and attempts to basically
6797 /// wrap around the EventBuilder so that FindMembers can quickly
6798 /// return this in it search for members
6799 /// </summary>
6800 public class MyEventBuilder : EventInfo {
6803 // We use this to "point" to our Builder which is
6804 // not really a MemberInfo
6806 EventBuilder MyBuilder;
6809 // We "catch" and wrap these methods
6811 MethodInfo raise, remove, add;
6813 EventAttributes attributes;
6814 Type declaring_type, reflected_type, event_type;
6815 string name;
6817 Event my_event;
6819 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
6821 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
6823 // And now store the values in our own fields.
6825 declaring_type = type_builder;
6827 reflected_type = type_builder;
6829 attributes = event_attr;
6830 this.name = name;
6831 my_event = ev;
6832 this.event_type = event_type;
6836 // Methods that you have to override. Note that you only need
6837 // to "implement" the variants that take the argument (those are
6838 // the "abstract" methods, the others (GetAddMethod()) are
6839 // regular.
6841 public override MethodInfo GetAddMethod (bool nonPublic)
6843 return add;
6846 public override MethodInfo GetRemoveMethod (bool nonPublic)
6848 return remove;
6851 public override MethodInfo GetRaiseMethod (bool nonPublic)
6853 return raise;
6857 // These methods make "MyEventInfo" look like a Builder
6859 public void SetRaiseMethod (MethodBuilder raiseMethod)
6861 raise = raiseMethod;
6862 MyBuilder.SetRaiseMethod (raiseMethod);
6865 public void SetRemoveOnMethod (MethodBuilder removeMethod)
6867 remove = removeMethod;
6868 MyBuilder.SetRemoveOnMethod (removeMethod);
6871 public void SetAddOnMethod (MethodBuilder addMethod)
6873 add = addMethod;
6874 MyBuilder.SetAddOnMethod (addMethod);
6877 public void SetCustomAttribute (CustomAttributeBuilder cb)
6879 MyBuilder.SetCustomAttribute (cb);
6882 public override object [] GetCustomAttributes (bool inherit)
6884 // FIXME : There's nothing which can be seemingly done here because
6885 // we have no way of getting at the custom attribute objects of the
6886 // EventBuilder !
6887 return null;
6890 public override object [] GetCustomAttributes (Type t, bool inherit)
6892 // FIXME : Same here !
6893 return null;
6896 public override bool IsDefined (Type t, bool b)
6898 return true;
6901 public override EventAttributes Attributes {
6902 get {
6903 return attributes;
6907 public override string Name {
6908 get {
6909 return name;
6913 public override Type DeclaringType {
6914 get {
6915 return declaring_type;
6919 public override Type ReflectedType {
6920 get {
6921 return reflected_type;
6925 public Type EventType {
6926 get {
6927 return event_type;
6931 public void SetUsed ()
6933 if (my_event != null) {
6934 // my_event.SetAssigned ();
6935 my_event.SetMemberIsUsed ();
6940 /// <summary>
6941 /// For case when event is declared like property (with add and remove accessors).
6942 /// </summary>
6943 public class EventProperty: Event {
6944 abstract class AEventPropertyAccessor : AEventAccessor
6946 protected AEventPropertyAccessor (Event method, Accessor accessor, string prefix):
6947 base (method, accessor, prefix)
6951 public override MethodBuilder Define (DeclSpace ds)
6953 CheckAbstractAndExtern (block != null);
6954 return base.Define (ds);
6957 public override string GetSignatureForError ()
6959 return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1);
6963 sealed class AddDelegateMethod: AEventPropertyAccessor
6965 public AddDelegateMethod (Event method, Accessor accessor):
6966 base (method, accessor, AddPrefix)
6971 sealed class RemoveDelegateMethod: AEventPropertyAccessor
6973 public RemoveDelegateMethod (Event method, Accessor accessor):
6974 base (method, accessor, RemovePrefix)
6980 static readonly string[] attribute_targets = new string [] { "event" }; // "property" target was disabled for 2.0 version
6982 public EventProperty (DeclSpace parent, FullNamedExpression type, int mod_flags,
6983 MemberName name,
6984 Attributes attrs, Accessor add, Accessor remove)
6985 : base (parent, type, mod_flags, name, attrs)
6987 Add = new AddDelegateMethod (this, add);
6988 Remove = new RemoveDelegateMethod (this, remove);
6991 public override bool Define()
6993 if (!base.Define ())
6994 return false;
6996 SetMemberIsUsed ();
6997 return true;
7000 public override string[] ValidAttributeTargets {
7001 get {
7002 return attribute_targets;
7007 /// <summary>
7008 /// Event is declared like field.
7009 /// </summary>
7010 public class EventField : Event {
7011 abstract class EventFieldAccessor : AEventAccessor
7013 protected EventFieldAccessor (Event method, string prefix)
7014 : base (method, prefix)
7018 public override void Emit (DeclSpace parent)
7020 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
7021 if (parent is Class) {
7022 MethodBuilder mb = method_data.MethodBuilder;
7023 mb.SetImplementationFlags (mb.GetMethodImplementationFlags () | MethodImplAttributes.Synchronized);
7026 // TODO: because we cannot use generics yet
7027 FieldInfo field_info = ((EventField) method).BackingField.FieldBuilder;
7028 FieldExpr f_expr = new FieldExpr (field_info, Location);
7029 if ((method.ModFlags & Modifiers.STATIC) == 0)
7030 f_expr.InstanceExpression = new CompilerGeneratedThis (field_info.FieldType, Location);
7032 block = new ToplevelBlock (ParameterInfo, Location);
7033 block.AddStatement (new StatementExpression (
7034 new CompoundAssign (Operation,
7035 f_expr,
7036 block.GetParameterReference (ParameterInfo[0].Name, Location))));
7039 base.Emit (parent);
7042 protected abstract Binary.Operator Operation { get; }
7045 sealed class AddDelegateMethod: EventFieldAccessor
7047 public AddDelegateMethod (Event method):
7048 base (method, AddPrefix)
7052 protected override Binary.Operator Operation {
7053 get { return Binary.Operator.Addition; }
7057 sealed class RemoveDelegateMethod: EventFieldAccessor
7059 public RemoveDelegateMethod (Event method):
7060 base (method, RemovePrefix)
7064 protected override Binary.Operator Operation {
7065 get { return Binary.Operator.Subtraction; }
7070 static readonly string[] attribute_targets = new string [] { "event", "field", "method" };
7071 static readonly string[] attribute_targets_interface = new string[] { "event", "method" };
7073 public Field BackingField;
7074 public Expression Initializer;
7076 public EventField (DeclSpace parent, FullNamedExpression type, int mod_flags, MemberName name, Attributes attrs)
7077 : base (parent, type, mod_flags, name, attrs)
7079 Add = new AddDelegateMethod (this);
7080 Remove = new RemoveDelegateMethod (this);
7083 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
7085 if (a.Target == AttributeTargets.Field) {
7086 BackingField.ApplyAttributeBuilder (a, cb, pa);
7087 return;
7090 if (a.Target == AttributeTargets.Method) {
7091 int errors = Report.Errors;
7092 Add.ApplyAttributeBuilder (a, cb, pa);
7093 if (errors == Report.Errors)
7094 Remove.ApplyAttributeBuilder (a, cb, pa);
7095 return;
7098 base.ApplyAttributeBuilder (a, cb, pa);
7101 public override bool Define()
7103 if (!base.Define ())
7104 return false;
7106 if (Initializer != null && (ModFlags & Modifiers.ABSTRACT) != 0) {
7107 Report.Error (74, Location, "`{0}': abstract event cannot have an initializer",
7108 GetSignatureForError ());
7111 if (!HasBackingField) {
7112 SetMemberIsUsed ();
7113 return true;
7116 // FIXME: We are unable to detect whether generic event is used because
7117 // we are using FieldExpr instead of EventExpr for event access in that
7118 // case. When this issue will be fixed this hack can be removed.
7119 if (TypeManager.IsGenericType (MemberType))
7120 SetMemberIsUsed ();
7122 if (Add.IsInterfaceImplementation)
7123 SetMemberIsUsed ();
7125 TypeManager.RegisterEventField (EventBuilder, this);
7127 BackingField = new Field (Parent,
7128 new TypeExpression (MemberType, Location),
7129 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
7130 MemberName, null);
7132 Parent.PartialContainer.AddField (BackingField);
7133 BackingField.Initializer = Initializer;
7134 BackingField.ModFlags &= ~Modifiers.COMPILER_GENERATED;
7136 // Call define because we passed fields definition
7137 return BackingField.Define ();
7140 bool HasBackingField {
7141 get {
7142 return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0;
7146 public override string[] ValidAttributeTargets
7148 get {
7149 return HasBackingField ? attribute_targets : attribute_targets_interface;
7154 public abstract class Event : PropertyBasedMember {
7155 public abstract class AEventAccessor : AbstractPropertyEventMethod
7157 protected readonly Event method;
7158 ImplicitParameter param_attr;
7160 static readonly string[] attribute_targets = new string [] { "method", "param", "return" };
7162 public const string AddPrefix = "add_";
7163 public const string RemovePrefix = "remove_";
7165 protected AEventAccessor (Event method, string prefix)
7166 : base (method, prefix)
7168 this.method = method;
7169 this.ModFlags = method.ModFlags;
7172 protected AEventAccessor (Event method, Accessor accessor, string prefix)
7173 : base (method, accessor, prefix)
7175 this.method = method;
7176 this.ModFlags = method.ModFlags;
7179 public bool IsInterfaceImplementation {
7180 get { return method_data.implementing != null; }
7183 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
7185 if (a.IsInternalMethodImplAttribute) {
7186 method.is_external_implementation = true;
7189 base.ApplyAttributeBuilder (a, cb, pa);
7192 protected override void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
7194 if (a.Target == AttributeTargets.Parameter) {
7195 if (param_attr == null)
7196 param_attr = new ImplicitParameter (method_data.MethodBuilder);
7198 param_attr.ApplyAttributeBuilder (a, cb, pa);
7199 return;
7202 base.ApplyAttributeBuilder (a, cb, pa);
7205 public override AttributeTargets AttributeTargets {
7206 get {
7207 return AttributeTargets.Method;
7211 public override bool IsClsComplianceRequired ()
7213 return method.IsClsComplianceRequired ();
7216 public virtual MethodBuilder Define (DeclSpace parent)
7218 method_data = new MethodData (method, method.ModFlags,
7219 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
7221 if (!method_data.Define (parent, method.GetFullName (MemberName)))
7222 return null;
7224 MethodBuilder mb = method_data.MethodBuilder;
7225 ParameterInfo.ApplyAttributes (mb);
7226 return mb;
7229 public override Type ReturnType {
7230 get {
7231 return TypeManager.void_type;
7235 public override EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
7237 return new EmitContext (
7238 this, method.Parent, Location, ig, ReturnType,
7239 method.ModFlags, false);
7242 public override ObsoleteAttribute GetObsoleteAttribute ()
7244 return method.GetObsoleteAttribute ();
7247 public override string[] ValidAttributeTargets {
7248 get {
7249 return attribute_targets;
7253 public override ParametersCompiled ParameterInfo {
7254 get {
7255 return method.parameters;
7261 const int AllowedModifiers =
7262 Modifiers.NEW |
7263 Modifiers.PUBLIC |
7264 Modifiers.PROTECTED |
7265 Modifiers.INTERNAL |
7266 Modifiers.PRIVATE |
7267 Modifiers.STATIC |
7268 Modifiers.VIRTUAL |
7269 Modifiers.SEALED |
7270 Modifiers.OVERRIDE |
7271 Modifiers.UNSAFE |
7272 Modifiers.ABSTRACT |
7273 Modifiers.EXTERN;
7275 const int AllowedInterfaceModifiers =
7276 Modifiers.NEW;
7278 public AEventAccessor Add, Remove;
7279 public MyEventBuilder EventBuilder;
7280 public MethodBuilder AddBuilder, RemoveBuilder;
7282 ParametersCompiled parameters;
7284 protected Event (DeclSpace parent, FullNamedExpression type, int mod_flags, MemberName name, Attributes attrs)
7285 : base (parent, null, type, mod_flags,
7286 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
7287 name, attrs)
7291 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
7293 if ((a.HasSecurityAttribute)) {
7294 a.Error_InvalidSecurityParent ();
7295 return;
7298 EventBuilder.SetCustomAttribute (cb);
7301 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
7303 return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
7306 public override AttributeTargets AttributeTargets {
7307 get {
7308 return AttributeTargets.Event;
7312 public override bool Define ()
7314 if (!base.Define ())
7315 return false;
7317 if (!TypeManager.IsDelegateType (MemberType)) {
7318 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
7321 parameters = ParametersCompiled.CreateFullyResolved (
7322 new Parameter (null, "value", Parameter.Modifier.NONE, null, Location), MemberType);
7324 if (!CheckBase ())
7325 return false;
7327 if (TypeManager.delegate_combine_delegate_delegate == null) {
7328 TypeManager.delegate_combine_delegate_delegate = TypeManager.GetPredefinedMethod (
7329 TypeManager.delegate_type, "Combine", Location,
7330 TypeManager.delegate_type, TypeManager.delegate_type);
7332 if (TypeManager.delegate_remove_delegate_delegate == null) {
7333 TypeManager.delegate_remove_delegate_delegate = TypeManager.GetPredefinedMethod (
7334 TypeManager.delegate_type, "Remove", Location,
7335 TypeManager.delegate_type, TypeManager.delegate_type);
7339 // Now define the accessors
7342 AddBuilder = Add.Define (Parent);
7343 if (AddBuilder == null)
7344 return false;
7346 RemoveBuilder = Remove.Define (Parent);
7347 if (RemoveBuilder == null)
7348 return false;
7350 EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, EventAttributes.None, MemberType);
7351 EventBuilder.SetAddOnMethod (AddBuilder);
7352 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
7354 Parent.MemberCache.AddMember (EventBuilder, this);
7355 Parent.MemberCache.AddMember (AddBuilder, Add);
7356 Parent.MemberCache.AddMember (RemoveBuilder, Remove);
7358 return true;
7361 public override void Emit ()
7363 if (OptAttributes != null) {
7364 OptAttributes.Emit ();
7367 Add.Emit (Parent);
7368 Remove.Emit (Parent);
7370 base.Emit ();
7373 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
7375 MethodInfo mi = (MethodInfo) Parent.PartialContainer.BaseCache.FindBaseEvent (
7376 Parent.TypeBuilder, Name);
7378 if (mi == null)
7379 return null;
7381 AParametersCollection pd = TypeManager.GetParameterData (mi);
7382 base_ret_type = pd.Types [0];
7383 return mi;
7387 // Represents header string for documentation comment.
7389 public override string DocCommentHeader {
7390 get { return "E:"; }
7395 public class Indexer : PropertyBase
7397 public class GetIndexerMethod : GetMethod
7399 ParametersCompiled parameters;
7401 public GetIndexerMethod (Indexer method):
7402 base (method)
7404 this.parameters = method.parameters;
7407 public GetIndexerMethod (PropertyBase method, Accessor accessor):
7408 base (method, accessor)
7410 parameters = accessor.Parameters;
7413 public override MethodBuilder Define (DeclSpace parent)
7415 parameters.Resolve (ResolveContext);
7416 return base.Define (parent);
7419 public override bool EnableOverloadChecks (MemberCore overload)
7421 if (base.EnableOverloadChecks (overload)) {
7422 overload.caching_flags |= Flags.MethodOverloadsExist;
7423 return true;
7426 return false;
7429 public override ParametersCompiled ParameterInfo {
7430 get {
7431 return parameters;
7436 public class SetIndexerMethod: SetMethod
7438 public SetIndexerMethod (Indexer method):
7439 base (method)
7441 parameters = ParametersCompiled.MergeGenerated (method.parameters, false, parameters [0], null);
7444 public SetIndexerMethod (PropertyBase method, Accessor accessor):
7445 base (method, accessor)
7447 parameters = method.Get.IsDummy ? accessor.Parameters : accessor.Parameters.Clone ();
7450 public override bool EnableOverloadChecks (MemberCore overload)
7452 if (base.EnableOverloadChecks (overload)) {
7453 overload.caching_flags |= Flags.MethodOverloadsExist;
7454 return true;
7457 return false;
7461 const int AllowedModifiers =
7462 Modifiers.NEW |
7463 Modifiers.PUBLIC |
7464 Modifiers.PROTECTED |
7465 Modifiers.INTERNAL |
7466 Modifiers.PRIVATE |
7467 Modifiers.VIRTUAL |
7468 Modifiers.SEALED |
7469 Modifiers.OVERRIDE |
7470 Modifiers.UNSAFE |
7471 Modifiers.EXTERN |
7472 Modifiers.ABSTRACT;
7474 const int AllowedInterfaceModifiers =
7475 Modifiers.NEW;
7477 public readonly ParametersCompiled parameters;
7479 public Indexer (DeclSpace parent, FullNamedExpression type, MemberName name, int mod,
7480 ParametersCompiled parameters, Attributes attrs,
7481 Accessor get_block, Accessor set_block, bool define_set_first)
7482 : base (parent, type, mod,
7483 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
7484 name, attrs, define_set_first)
7486 this.parameters = parameters;
7488 if (get_block == null)
7489 Get = new GetIndexerMethod (this);
7490 else
7491 Get = new GetIndexerMethod (this, get_block);
7493 if (set_block == null)
7494 Set = new SetIndexerMethod (this);
7495 else
7496 Set = new SetIndexerMethod (this, set_block);
7499 protected override bool CheckForDuplications ()
7501 return Parent.MemberCache.CheckExistingMembersOverloads (this, GetFullName (MemberName), parameters);
7504 public override bool Define ()
7506 if (!base.Define ())
7507 return false;
7509 if (!DefineParameters (parameters))
7510 return false;
7512 if (OptAttributes != null) {
7513 Attribute indexer_attr = OptAttributes.Search (PredefinedAttributes.Get.IndexerName);
7514 if (indexer_attr != null) {
7515 // Remove the attribute from the list because it is not emitted
7516 OptAttributes.Attrs.Remove (indexer_attr);
7518 string name = indexer_attr.GetIndexerAttributeValue ();
7519 if (name == null)
7520 return false;
7522 ShortName = name;
7524 if (IsExplicitImpl) {
7525 Report.Error (415, indexer_attr.Location,
7526 "The `IndexerName' attribute is valid only on an " +
7527 "indexer that is not an explicit interface member declaration");
7528 return false;
7531 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
7532 Report.Error (609, indexer_attr.Location,
7533 "Cannot set the `IndexerName' attribute on an indexer marked override");
7534 return false;
7539 if (InterfaceType != null) {
7540 string base_IndexerName = TypeManager.IndexerPropertyName (InterfaceType);
7541 if (base_IndexerName != Name)
7542 ShortName = base_IndexerName;
7545 if (!Parent.PartialContainer.AddMember (this) ||
7546 !Parent.PartialContainer.AddMember (Get) || !Parent.PartialContainer.AddMember (Set))
7547 return false;
7549 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
7551 if (!DefineAccessors ())
7552 return false;
7554 if (!CheckBase ())
7555 return false;
7558 // Now name the parameters
7560 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
7561 GetFullName (MemberName), PropertyAttributes.None, MemberType, parameters.GetEmitTypes ());
7563 if (!Get.IsDummy) {
7564 PropertyBuilder.SetGetMethod (GetBuilder);
7565 Parent.MemberCache.AddMember (GetBuilder, Get);
7568 if (!Set.IsDummy) {
7569 PropertyBuilder.SetSetMethod (SetBuilder);
7570 Parent.MemberCache.AddMember (SetBuilder, Set);
7573 TypeManager.RegisterIndexer (PropertyBuilder, parameters);
7574 Parent.MemberCache.AddMember (PropertyBuilder, this);
7575 return true;
7578 public override bool EnableOverloadChecks (MemberCore overload)
7580 if (overload is Indexer) {
7581 caching_flags |= Flags.MethodOverloadsExist;
7582 return true;
7585 return base.EnableOverloadChecks (overload);
7588 public override string GetDocCommentName (DeclSpace ds)
7590 return DocUtil.GetMethodDocCommentName (this, parameters, ds);
7593 public override string GetSignatureForError ()
7595 StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
7596 if (MemberName.Left != null) {
7597 sb.Append ('.');
7598 sb.Append (MemberName.Left.GetSignatureForError ());
7601 sb.Append (".this");
7602 sb.Append (parameters.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
7603 return sb.ToString ();
7606 protected override PropertyInfo ResolveBaseProperty ()
7608 return Parent.PartialContainer.BaseCache.FindMemberToOverride (
7609 Parent.TypeBuilder, Name, parameters, null, true) as PropertyInfo;
7612 protected override bool VerifyClsCompliance ()
7614 if (!base.VerifyClsCompliance ())
7615 return false;
7617 parameters.VerifyClsCompliance ();
7618 return true;
7622 public class Operator : MethodOrOperator {
7624 const int AllowedModifiers =
7625 Modifiers.PUBLIC |
7626 Modifiers.UNSAFE |
7627 Modifiers.EXTERN |
7628 Modifiers.STATIC;
7630 public enum OpType : byte {
7632 // Unary operators
7633 LogicalNot,
7634 OnesComplement,
7635 Increment,
7636 Decrement,
7637 True,
7638 False,
7640 // Unary and Binary operators
7641 Addition,
7642 Subtraction,
7644 UnaryPlus,
7645 UnaryNegation,
7647 // Binary operators
7648 Multiply,
7649 Division,
7650 Modulus,
7651 BitwiseAnd,
7652 BitwiseOr,
7653 ExclusiveOr,
7654 LeftShift,
7655 RightShift,
7656 Equality,
7657 Inequality,
7658 GreaterThan,
7659 LessThan,
7660 GreaterThanOrEqual,
7661 LessThanOrEqual,
7663 // Implicit and Explicit
7664 Implicit,
7665 Explicit,
7667 // Just because of enum
7671 public readonly OpType OperatorType;
7673 static readonly string [] [] names;
7675 static Operator ()
7677 names = new string[(int)OpType.TOP][];
7678 names [(int) OpType.LogicalNot] = new string [] { "!", "op_LogicalNot" };
7679 names [(int) OpType.OnesComplement] = new string [] { "~", "op_OnesComplement" };
7680 names [(int) OpType.Increment] = new string [] { "++", "op_Increment" };
7681 names [(int) OpType.Decrement] = new string [] { "--", "op_Decrement" };
7682 names [(int) OpType.True] = new string [] { "true", "op_True" };
7683 names [(int) OpType.False] = new string [] { "false", "op_False" };
7684 names [(int) OpType.Addition] = new string [] { "+", "op_Addition" };
7685 names [(int) OpType.Subtraction] = new string [] { "-", "op_Subtraction" };
7686 names [(int) OpType.UnaryPlus] = new string [] { "+", "op_UnaryPlus" };
7687 names [(int) OpType.UnaryNegation] = new string [] { "-", "op_UnaryNegation" };
7688 names [(int) OpType.Multiply] = new string [] { "*", "op_Multiply" };
7689 names [(int) OpType.Division] = new string [] { "/", "op_Division" };
7690 names [(int) OpType.Modulus] = new string [] { "%", "op_Modulus" };
7691 names [(int) OpType.BitwiseAnd] = new string [] { "&", "op_BitwiseAnd" };
7692 names [(int) OpType.BitwiseOr] = new string [] { "|", "op_BitwiseOr" };
7693 names [(int) OpType.ExclusiveOr] = new string [] { "^", "op_ExclusiveOr" };
7694 names [(int) OpType.LeftShift] = new string [] { "<<", "op_LeftShift" };
7695 names [(int) OpType.RightShift] = new string [] { ">>", "op_RightShift" };
7696 names [(int) OpType.Equality] = new string [] { "==", "op_Equality" };
7697 names [(int) OpType.Inequality] = new string [] { "!=", "op_Inequality" };
7698 names [(int) OpType.GreaterThan] = new string [] { ">", "op_GreaterThan" };
7699 names [(int) OpType.LessThan] = new string [] { "<", "op_LessThan" };
7700 names [(int) OpType.GreaterThanOrEqual] = new string [] { ">=", "op_GreaterThanOrEqual" };
7701 names [(int) OpType.LessThanOrEqual] = new string [] { "<=", "op_LessThanOrEqual" };
7702 names [(int) OpType.Implicit] = new string [] { "implicit", "op_Implicit" };
7703 names [(int) OpType.Explicit] = new string [] { "explicit", "op_Explicit" };
7706 public Operator (DeclSpace parent, OpType type, FullNamedExpression ret_type,
7707 int mod_flags, ParametersCompiled parameters,
7708 ToplevelBlock block, Attributes attrs, Location loc)
7709 : base (parent, null, ret_type, mod_flags, AllowedModifiers,
7710 new MemberName (GetMetadataName (type), loc), attrs, parameters)
7712 OperatorType = type;
7713 Block = block;
7716 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
7718 if (a.Type == pa.Conditional) {
7719 Error_ConditionalAttributeIsNotValid ();
7720 return;
7723 base.ApplyAttributeBuilder (a, cb, pa);
7726 public override bool Define ()
7728 const int RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
7729 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
7730 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
7733 if (!base.Define ())
7734 return false;
7736 // imlicit and explicit operator of same types are not allowed
7737 if (OperatorType == OpType.Explicit)
7738 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Implicit), Parameters);
7739 else if (OperatorType == OpType.Implicit)
7740 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Explicit), Parameters);
7742 Type declaring_type = MethodData.DeclaringType;
7743 Type return_type = MemberType;
7744 Type first_arg_type = ParameterTypes [0];
7746 Type first_arg_type_unwrap = first_arg_type;
7747 if (TypeManager.IsNullableType (first_arg_type))
7748 first_arg_type_unwrap = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (first_arg_type) [0]);
7750 Type return_type_unwrap = return_type;
7751 if (TypeManager.IsNullableType (return_type))
7752 return_type_unwrap = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (return_type) [0]);
7754 if (TypeManager.IsDynamicType (return_type) || TypeManager.IsDynamicType (first_arg_type)) {
7755 Report.Error (1964, Location,
7756 "User-defined operator `{0}' cannot convert to or from the dynamic type",
7757 GetSignatureForError ());
7759 return false;
7763 // Rules for conversion operators
7765 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7766 if (first_arg_type_unwrap == return_type_unwrap && first_arg_type_unwrap == declaring_type){
7767 Report.Error (555, Location,
7768 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
7769 return false;
7772 Type conv_type;
7773 if (TypeManager.IsEqual (declaring_type, return_type) || declaring_type == return_type_unwrap) {
7774 conv_type = first_arg_type;
7775 } else if (TypeManager.IsEqual (declaring_type, first_arg_type) || declaring_type == first_arg_type_unwrap) {
7776 conv_type = return_type;
7777 } else {
7778 Report.Error (556, Location,
7779 "User-defined conversion must convert to or from the enclosing type");
7780 return false;
7784 // Because IsInterface and IsClass are not supported
7786 if (!TypeManager.IsGenericParameter (conv_type)) {
7787 if (conv_type.IsInterface) {
7788 Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
7789 GetSignatureForError ());
7790 return false;
7793 if (conv_type.IsClass) {
7794 if (TypeManager.IsSubclassOf (declaring_type, conv_type)) {
7795 Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from a base class",
7796 GetSignatureForError ());
7797 return false;
7800 if (TypeManager.IsSubclassOf (conv_type, declaring_type)) {
7801 Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from a derived class",
7802 GetSignatureForError ());
7803 return false;
7807 } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
7808 if (first_arg_type != declaring_type || Parameters.Types [1] != TypeManager.int32_type) {
7809 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");
7810 return false;
7812 } else if (Parameters.Count == 1) {
7813 // Checks for Unary operators
7815 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
7816 if (return_type != declaring_type && !TypeManager.IsSubclassOf (return_type, declaring_type)) {
7817 Report.Error (448, Location,
7818 "The return type for ++ or -- operator must be the containing type or derived from the containing type");
7819 return false;
7821 if (first_arg_type != declaring_type) {
7822 Report.Error (
7823 559, Location, "The parameter type for ++ or -- operator must be the containing type");
7824 return false;
7828 if (!TypeManager.IsEqual (first_arg_type_unwrap, declaring_type)){
7829 Report.Error (562, Location,
7830 "The parameter type of a unary operator must be the containing type");
7831 return false;
7834 if (OperatorType == OpType.True || OperatorType == OpType.False) {
7835 if (return_type != TypeManager.bool_type){
7836 Report.Error (
7837 215, Location,
7838 "The return type of operator True or False " +
7839 "must be bool");
7840 return false;
7844 } else {
7845 // Checks for Binary operators
7847 if (first_arg_type != declaring_type &&
7848 Parameters.Types [1] != declaring_type){
7849 Report.Error (
7850 563, Location,
7851 "One of the parameters of a binary operator must " +
7852 "be the containing type");
7853 return false;
7857 return true;
7860 protected override bool ResolveMemberType ()
7862 if (!base.ResolveMemberType ())
7863 return false;
7865 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
7866 return true;
7869 // Operator cannot be override
7870 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
7872 return null;
7875 public static string GetName (OpType ot)
7877 return names [(int) ot] [0];
7880 public static string GetName (string metadata_name)
7882 for (int i = 0; i < names.Length; ++i) {
7883 if (names [i] [1] == metadata_name)
7884 return names [i] [0];
7886 return null;
7889 public static string GetMetadataName (OpType ot)
7891 return names [(int) ot] [1];
7894 public static string GetMetadataName (string name)
7896 for (int i = 0; i < names.Length; ++i) {
7897 if (names [i] [0] == name)
7898 return names [i] [1];
7900 return null;
7903 public OpType GetMatchingOperator ()
7905 switch (OperatorType) {
7906 case OpType.Equality:
7907 return OpType.Inequality;
7908 case OpType.Inequality:
7909 return OpType.Equality;
7910 case OpType.True:
7911 return OpType.False;
7912 case OpType.False:
7913 return OpType.True;
7914 case OpType.GreaterThan:
7915 return OpType.LessThan;
7916 case OpType.LessThan:
7917 return OpType.GreaterThan;
7918 case OpType.GreaterThanOrEqual:
7919 return OpType.LessThanOrEqual;
7920 case OpType.LessThanOrEqual:
7921 return OpType.GreaterThanOrEqual;
7922 default:
7923 return OpType.TOP;
7927 public override string GetSignatureForError ()
7929 StringBuilder sb = new StringBuilder ();
7930 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7931 sb.AppendFormat ("{0}.{1} operator {2}",
7932 Parent.GetSignatureForError (), GetName (OperatorType), type_name.GetSignatureForError ());
7934 else {
7935 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
7938 sb.Append (Parameters.GetSignatureForError ());
7939 return sb.ToString ();
7944 // This is used to compare method signatures
7946 struct MethodSignature {
7947 public string Name;
7948 public Type RetType;
7949 public Type [] Parameters;
7951 /// <summary>
7952 /// This delegate is used to extract methods which have the
7953 /// same signature as the argument
7954 /// </summary>
7955 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
7957 public MethodSignature (string name, Type ret_type, Type [] parameters)
7959 Name = name;
7960 RetType = ret_type;
7962 if (parameters == null)
7963 Parameters = Type.EmptyTypes;
7964 else
7965 Parameters = parameters;
7968 public override string ToString ()
7970 string pars = "";
7971 if (Parameters.Length != 0){
7972 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
7973 for (int i = 0; i < Parameters.Length; i++){
7974 sb.Append (Parameters [i]);
7975 if (i+1 < Parameters.Length)
7976 sb.Append (", ");
7978 pars = sb.ToString ();
7981 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
7984 public override int GetHashCode ()
7986 return Name.GetHashCode ();
7989 public override bool Equals (Object o)
7991 MethodSignature other = (MethodSignature) o;
7993 if (other.Name != Name)
7994 return false;
7996 if (other.RetType != RetType)
7997 return false;
7999 if (Parameters == null){
8000 if (other.Parameters == null)
8001 return true;
8002 return false;
8005 if (other.Parameters == null)
8006 return false;
8008 int c = Parameters.Length;
8009 if (other.Parameters.Length != c)
8010 return false;
8012 for (int i = 0; i < c; i++)
8013 if (other.Parameters [i] != Parameters [i])
8014 return false;
8016 return true;
8019 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
8021 MethodSignature sig = (MethodSignature) filter_criteria;
8023 if (m.Name != sig.Name)
8024 return false;
8026 Type ReturnType;
8027 MethodInfo mi = m as MethodInfo;
8028 PropertyInfo pi = m as PropertyInfo;
8030 if (mi != null)
8031 ReturnType = mi.ReturnType;
8032 else if (pi != null)
8033 ReturnType = pi.PropertyType;
8034 else
8035 return false;
8038 // we use sig.RetType == null to mean `do not check the
8039 // method return value.
8041 if (sig.RetType != null) {
8042 if (!TypeManager.IsEqual (ReturnType, sig.RetType))
8043 return false;
8046 Type [] args;
8047 if (mi != null)
8048 args = TypeManager.GetParameterData (mi).Types;
8049 else
8050 args = TypeManager.GetParameterData (pi).Types;
8051 Type [] sigp = sig.Parameters;
8053 if (args.Length != sigp.Length)
8054 return false;
8056 for (int i = args.Length - 1; i >= 0; i--)
8057 if (!TypeManager.IsEqual (args [i], sigp [i]))
8058 return false;
8060 return true;