2009-11-24 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / class.cs
blob2fcb856dd59451b129048f31b962d63a261b8955
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 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 container.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 && container.Report.WarningLevel > 2) {
142 if (container.Methods == null || !container.HasEquals)
143 container.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 container.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 ();
158 // Different context is needed when resolving type container base
159 // types. Type names come from the parent scope but type parameter
160 // names from the container scope.
162 struct BaseContext : IMemberContext
164 TypeContainer tc;
166 public BaseContext (TypeContainer tc)
168 this.tc = tc;
171 #region IMemberContext Members
173 public CompilerContext Compiler {
174 get { return tc.Compiler; }
177 public Type CurrentType {
178 get { return tc.Parent.CurrentType; }
181 public TypeParameter[] CurrentTypeParameters {
182 get { return tc.PartialContainer.CurrentTypeParameters; }
185 public TypeContainer CurrentTypeDefinition {
186 get { return tc.Parent.CurrentTypeDefinition; }
189 public bool IsObsolete {
190 get { return tc.IsObsolete; }
193 public bool IsUnsafe {
194 get { return tc.IsUnsafe; }
197 public bool IsStatic {
198 get { return tc.IsStatic; }
201 public string GetSignatureForError ()
203 throw new NotImplementedException ();
206 public ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
208 return null;
211 public FullNamedExpression LookupNamespaceAlias (string name)
213 return tc.Parent.LookupNamespaceAlias (name);
216 public FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
218 TypeParameter[] tp = CurrentTypeParameters;
219 if (tp != null) {
220 TypeParameter t = TypeParameter.FindTypeParameter (tp, name);
221 if (t != null)
222 return new TypeParameterExpr (t, loc);
225 return tc.Parent.LookupNamespaceOrType (name, loc, ignore_cs0104);
228 #endregion
231 [Flags]
232 enum CachedMethods
234 Equals = 1,
235 GetHashCode = 1 << 1,
236 HasStaticFieldInitializer = 1 << 2
240 // Whether this is a struct, class or interface
241 public readonly Kind Kind;
243 // Holds a list of classes and structures
244 protected ArrayList types;
246 MemberCoreArrayList ordered_explicit_member_list;
247 MemberCoreArrayList ordered_member_list;
249 // Holds the list of properties
250 MemberCoreArrayList properties;
252 // Holds the list of delegates
253 MemberCoreArrayList delegates;
255 // Holds the list of constructors
256 protected MemberCoreArrayList instance_constructors;
258 // Holds the list of fields
259 protected MemberCoreArrayList fields;
261 // Holds a list of fields that have initializers
262 protected ArrayList initialized_fields;
264 // Holds a list of static fields that have initializers
265 protected ArrayList initialized_static_fields;
267 // Holds the list of constants
268 protected MemberCoreArrayList constants;
270 // Holds the methods.
271 MemberCoreArrayList methods;
273 // Holds the events
274 protected MemberCoreArrayList events;
276 // Holds the indexers
277 ArrayList indexers;
279 // Holds the operators
280 MemberCoreArrayList operators;
282 // Holds the compiler generated classes
283 ArrayList compiler_generated;
286 // Pointers to the default constructor and the default static constructor
288 protected Constructor default_constructor;
289 protected Constructor default_static_constructor;
292 // Points to the first non-static field added to the container.
294 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
295 // and the first one's as good as any.
297 FieldBase first_nonstatic_field = null;
300 // This one is computed after we can distinguish interfaces
301 // from classes from the arraylist `type_bases'
303 TypeExpr base_type;
304 TypeExpr[] iface_exprs;
305 Type GenericType;
306 GenericTypeParameterBuilder[] nested_gen_params;
308 protected ArrayList type_bases;
310 protected bool members_defined;
311 bool members_defined_ok;
313 // The interfaces we implement.
314 protected Type[] ifaces;
316 // The base member cache and our member cache
317 MemberCache base_cache;
318 protected MemberCache member_cache;
320 public const string DefaultIndexerName = "Item";
322 private bool seen_normal_indexers = false;
323 private string indexer_name = DefaultIndexerName;
324 protected bool requires_delayed_unmanagedtype_check;
326 private CachedMethods cached_method;
328 ArrayList partial_parts;
330 /// <remarks>
331 /// The pending methods that need to be implemented
332 // (interfaces or abstract methods)
333 /// </remarks>
334 PendingImplementation pending;
336 public TypeContainer (NamespaceEntry ns, DeclSpace parent, MemberName name,
337 Attributes attrs, Kind kind)
338 : base (ns, parent, name, attrs)
340 if (parent != null && parent.NamespaceEntry != ns)
341 throw new InternalErrorException ("A nested type should be in the same NamespaceEntry as its enclosing class");
343 this.Kind = kind;
344 this.PartialContainer = this;
347 public bool AddMember (MemberCore symbol)
349 return AddToContainer (symbol, symbol.MemberName.Basename);
352 protected virtual bool AddMemberType (DeclSpace ds)
354 return AddToContainer (ds, ds.Basename);
357 protected virtual void RemoveMemberType (DeclSpace ds)
359 RemoveFromContainer (ds.Basename);
362 public void AddConstant (Const constant)
364 if (!AddMember (constant))
365 return;
367 if (constants == null)
368 constants = new MemberCoreArrayList ();
370 constants.Add (constant);
373 public TypeContainer AddTypeContainer (TypeContainer tc)
375 if (!AddMemberType (tc))
376 return tc;
378 if (types == null)
379 types = new MemberCoreArrayList ();
380 types.Add (tc);
382 return tc;
385 public virtual TypeContainer AddPartial (TypeContainer next_part)
387 return AddPartial (next_part, next_part.Basename);
390 protected TypeContainer AddPartial (TypeContainer next_part, string name)
392 next_part.ModFlags |= Modifiers.PARTIAL;
393 TypeContainer tc = defined_names [name] as TypeContainer;
395 if (tc == null)
396 return AddTypeContainer (next_part);
398 if ((tc.ModFlags & Modifiers.PARTIAL) == 0) {
399 Report.SymbolRelatedToPreviousError (next_part);
400 Error_MissingPartialModifier (tc);
403 if (tc.Kind != next_part.Kind) {
404 Report.SymbolRelatedToPreviousError (tc);
405 Report.Error (261, next_part.Location,
406 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
407 next_part.GetSignatureForError ());
410 if ((tc.ModFlags & Modifiers.Accessibility) != (next_part.ModFlags & Modifiers.Accessibility) &&
411 ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 &&
412 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
413 Report.SymbolRelatedToPreviousError (tc);
414 Report.Error (262, next_part.Location,
415 "Partial declarations of `{0}' have conflicting accessibility modifiers",
416 next_part.GetSignatureForError ());
419 if (tc.partial_parts == null)
420 tc.partial_parts = new ArrayList (1);
422 if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
423 tc.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.Accessibility);
424 } else if ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
425 tc.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.Accessibility);
426 tc.ModFlags |= next_part.ModFlags;
427 } else {
428 tc.ModFlags |= next_part.ModFlags;
431 if (next_part.attributes != null) {
432 if (tc.attributes == null)
433 tc.attributes = next_part.attributes;
434 else
435 tc.attributes.AddAttributes (next_part.attributes.Attrs);
438 next_part.PartialContainer = tc;
439 tc.partial_parts.Add (next_part);
440 return tc;
443 public virtual void RemoveTypeContainer (TypeContainer next_part)
445 if (types != null)
446 types.Remove (next_part);
447 RemoveMemberType (next_part);
450 public void AddDelegate (Delegate d)
452 if (!AddMemberType (d))
453 return;
455 if (delegates == null)
456 delegates = new MemberCoreArrayList ();
458 delegates.Add (d);
461 private void AddMemberToList (MemberCore mc, ArrayList alist, bool isexplicit)
463 if (ordered_explicit_member_list == null) {
464 ordered_explicit_member_list = new MemberCoreArrayList ();
465 ordered_member_list = new MemberCoreArrayList ();
468 if (isexplicit) {
469 if (Kind == Kind.Interface) {
470 Report.Error (541, mc.Location,
471 "`{0}': explicit interface declaration can only be declared in a class or struct",
472 mc.GetSignatureForError ());
475 ordered_explicit_member_list.Add (mc);
476 alist.Insert (0, mc);
477 } else {
478 ordered_member_list.Add (mc);
479 alist.Add (mc);
484 public void AddMethod (MethodOrOperator method)
486 if (!AddToContainer (method, method.MemberName.Basename))
487 return;
489 if (methods == null)
490 methods = new MemberCoreArrayList ();
492 if (method.MemberName.Left != null)
493 AddMemberToList (method, methods, true);
494 else
495 AddMemberToList (method, methods, false);
498 public void AddConstructor (Constructor c)
500 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
501 if (!AddToContainer (c, is_static ?
502 ConstructorBuilder.ConstructorName : ConstructorBuilder.TypeConstructorName))
503 return;
505 if (is_static && c.Parameters.IsEmpty){
506 if (default_static_constructor != null) {
507 Report.SymbolRelatedToPreviousError (default_static_constructor);
508 Report.Error (111, c.Location,
509 "A member `{0}' is already defined. Rename this member or use different parameter types",
510 c.GetSignatureForError ());
511 return;
514 default_static_constructor = c;
515 } else {
516 if (c.Parameters.IsEmpty)
517 default_constructor = c;
519 if (instance_constructors == null)
520 instance_constructors = new MemberCoreArrayList ();
522 instance_constructors.Add (c);
526 public bool AddField (FieldBase field)
528 if (!AddMember (field))
529 return false;
531 if (fields == null)
532 fields = new MemberCoreArrayList ();
534 fields.Add (field);
536 if ((field.ModFlags & Modifiers.STATIC) != 0)
537 return true;
539 if (first_nonstatic_field == null) {
540 first_nonstatic_field = field;
541 return true;
544 if (Kind == Kind.Struct && first_nonstatic_field.Parent != field.Parent) {
545 Report.SymbolRelatedToPreviousError (first_nonstatic_field.Parent);
546 Report.Warning (282, 3, field.Location,
547 "struct instance field `{0}' found in different declaration from instance field `{1}'",
548 field.GetSignatureForError (), first_nonstatic_field.GetSignatureForError ());
550 return true;
553 public void AddProperty (Property prop)
555 if (!AddMember (prop) ||
556 !AddMember (prop.Get) || !AddMember (prop.Set))
557 return;
559 if (properties == null)
560 properties = new MemberCoreArrayList ();
562 if (prop.MemberName.Left != null)
563 AddMemberToList (prop, properties, true);
564 else
565 AddMemberToList (prop, properties, false);
568 public void AddEvent (Event e)
570 if (!AddMember (e))
571 return;
573 if (e is EventProperty) {
574 if (!AddMember (e.Add))
575 return;
577 if (!AddMember (e.Remove))
578 return;
581 if (events == null)
582 events = new MemberCoreArrayList ();
584 events.Add (e);
587 /// <summary>
588 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
589 /// </summary>
590 public void AddIndexer (Indexer i)
592 if (indexers == null)
593 indexers = new ArrayList ();
595 if (i.IsExplicitImpl)
596 AddMemberToList (i, indexers, true);
597 else
598 AddMemberToList (i, indexers, false);
601 public void AddOperator (Operator op)
603 if (!AddMember (op))
604 return;
606 if (operators == null)
607 operators = new OperatorArrayList (this);
609 operators.Add (op);
612 public void AddCompilerGeneratedClass (CompilerGeneratedClass c)
614 Report.Debug (64, "ADD COMPILER GENERATED CLASS", this, c);
616 if (compiler_generated == null)
617 compiler_generated = new ArrayList ();
619 compiler_generated.Add (c);
622 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
624 if (a.Type == pa.DefaultMember) {
625 if (Indexers != null) {
626 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
627 return;
631 base.ApplyAttributeBuilder (a, cb, pa);
634 public override AttributeTargets AttributeTargets {
635 get {
636 throw new NotSupportedException ();
640 public ArrayList Types {
641 get {
642 return types;
646 public MemberCoreArrayList Methods {
647 get {
648 return methods;
652 public ArrayList Constants {
653 get {
654 return constants;
658 protected Type BaseType {
659 get {
660 return TypeBuilder.BaseType;
664 public ArrayList Fields {
665 get {
666 return fields;
670 public ArrayList InstanceConstructors {
671 get {
672 return instance_constructors;
676 public ArrayList Properties {
677 get {
678 return properties;
682 public ArrayList Events {
683 get {
684 return events;
688 public ArrayList Indexers {
689 get {
690 return indexers;
694 public ArrayList Operators {
695 get {
696 return operators;
700 public ArrayList Delegates {
701 get {
702 return delegates;
706 protected override TypeAttributes TypeAttr {
707 get {
708 return Modifiers.TypeAttr (ModFlags, IsTopLevel) | base.TypeAttr;
712 public string IndexerName {
713 get {
714 return indexers == null ? DefaultIndexerName : indexer_name;
718 public bool IsComImport {
719 get {
720 if (OptAttributes == null)
721 return false;
723 return OptAttributes.Contains (PredefinedAttributes.Get.ComImport);
727 public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
729 if ((field.ModFlags & Modifiers.STATIC) != 0){
730 if (initialized_static_fields == null) {
731 PartialContainer.HasStaticFieldInitializer = true;
732 initialized_static_fields = new ArrayList (4);
735 initialized_static_fields.Add (expression);
736 } else {
737 if (initialized_fields == null)
738 initialized_fields = new ArrayList (4);
740 initialized_fields.Add (expression);
744 public void ResolveFieldInitializers (BlockContext ec)
746 if (partial_parts != null) {
747 foreach (TypeContainer part in partial_parts) {
748 part.DoResolveFieldInitializers (ec);
751 DoResolveFieldInitializers (ec);
754 void DoResolveFieldInitializers (BlockContext ec)
756 if (ec.IsStatic) {
757 if (initialized_static_fields == null)
758 return;
760 bool has_complex_initializer = !RootContext.Optimize;
761 int i;
762 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
763 for (i = 0; i < initialized_static_fields.Count; ++i) {
764 FieldInitializer fi = (FieldInitializer) initialized_static_fields [i];
765 ExpressionStatement s = fi.ResolveStatement (ec);
766 if (s == null) {
767 s = EmptyExpressionStatement.Instance;
768 } else if (fi.IsComplexInitializer) {
769 has_complex_initializer |= true;
772 init [i] = s;
775 for (i = 0; i < initialized_static_fields.Count; ++i) {
776 FieldInitializer fi = (FieldInitializer) initialized_static_fields [i];
778 // Need special check to not optimize code like this
779 // static int a = b = 5;
780 // static int b = 0;
782 if (!has_complex_initializer && fi.IsDefaultInitializer)
783 continue;
785 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
788 return;
791 if (initialized_fields == null)
792 return;
794 for (int i = 0; i < initialized_fields.Count; ++i) {
795 FieldInitializer fi = (FieldInitializer) initialized_fields [i];
796 ExpressionStatement s = fi.ResolveStatement (ec);
797 if (s == null)
798 continue;
801 // Field is re-initialized to its default value => removed
803 if (fi.IsDefaultInitializer && RootContext.Optimize)
804 continue;
806 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
810 public override string DocComment {
811 get {
812 return comment;
814 set {
815 if (value == null)
816 return;
818 comment += value;
822 public PendingImplementation PendingImplementations {
823 get { return pending; }
826 public override bool GetClsCompliantAttributeValue ()
828 if (PartialContainer != this)
829 return PartialContainer.GetClsCompliantAttributeValue ();
831 return base.GetClsCompliantAttributeValue ();
834 public virtual void AddBasesForPart (DeclSpace part, ArrayList bases)
836 // FIXME: get rid of partial_parts and store lists of bases of each part here
837 // assumed, not verified: 'part' is in 'partial_parts'
838 ((TypeContainer) part).type_bases = bases;
841 /// <summary>
842 /// This function computes the Base class and also the
843 /// list of interfaces that the class or struct @c implements.
844 ///
845 /// The return value is an array (might be null) of
846 /// interfaces implemented (as Types).
847 ///
848 /// The @base_class argument is set to the base object or null
849 /// if this is `System.Object'.
850 /// </summary>
851 protected virtual TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
853 base_class = null;
854 if (type_bases == null)
855 return null;
857 int count = type_bases.Count;
858 TypeExpr [] ifaces = null;
859 IMemberContext base_context = new BaseContext (this);
860 for (int i = 0, j = 0; i < count; i++){
861 FullNamedExpression fne = (FullNamedExpression) type_bases [i];
864 // Standard ResolveAsTypeTerminal cannot be used in this case because
865 // it does ObsoleteAttribute and constraint checks which require
866 // base type to be set
868 TypeExpr fne_resolved = fne.ResolveAsBaseTerminal (base_context, false);
869 if (fne_resolved == null)
870 continue;
872 if (i == 0 && Kind == Kind.Class && !fne_resolved.Type.IsInterface) {
873 if (fne_resolved is DynamicTypeExpr)
874 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
875 GetSignatureForError ());
876 else
877 base_class = fne_resolved;
878 continue;
881 if (ifaces == null)
882 ifaces = new TypeExpr [count - i];
884 if (fne_resolved.Type.IsInterface) {
885 for (int ii = 0; ii < j; ++ii) {
886 if (TypeManager.IsEqual (fne_resolved.Type, ifaces [ii].Type)) {
887 Report.Error (528, Location, "`{0}' is already listed in interface list",
888 fne_resolved.GetSignatureForError ());
889 break;
893 if (Kind == Kind.Interface && !IsAccessibleAs (fne_resolved.Type)) {
894 Report.Error (61, fne.Location,
895 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
896 fne_resolved.GetSignatureForError (), GetSignatureForError ());
898 } else {
899 Report.SymbolRelatedToPreviousError (fne_resolved.Type);
900 if (Kind != Kind.Class) {
901 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
902 } else if (base_class != null)
903 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
904 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
905 else {
906 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
907 GetSignatureForError (), fne_resolved.GetSignatureForError ());
911 ifaces [j++] = fne_resolved;
914 return ifaces;
917 TypeExpr[] GetNormalPartialBases (ref TypeExpr base_class)
919 ArrayList ifaces = new ArrayList (0);
920 if (iface_exprs != null)
921 ifaces.AddRange (iface_exprs);
923 foreach (TypeContainer part in partial_parts) {
924 TypeExpr new_base_class;
925 TypeExpr[] new_ifaces = part.ResolveBaseTypes (out new_base_class);
926 if (new_base_class != TypeManager.system_object_expr) {
927 if (base_class == TypeManager.system_object_expr)
928 base_class = new_base_class;
929 else {
930 if (new_base_class != null && !TypeManager.IsEqual (new_base_class.Type, base_class.Type)) {
931 Report.SymbolRelatedToPreviousError (base_class.Location, "");
932 Report.Error (263, part.Location,
933 "Partial declarations of `{0}' must not specify different base classes",
934 part.GetSignatureForError ());
936 return null;
941 if (new_ifaces == null)
942 continue;
944 foreach (TypeExpr iface in new_ifaces) {
945 if (ifaces.Contains (iface))
946 continue;
948 ifaces.Add (iface);
952 if (ifaces.Count == 0)
953 return null;
955 return (TypeExpr[])ifaces.ToArray (typeof (TypeExpr));
958 bool CheckGenericInterfaces (Type[] ifaces)
960 ArrayList already_checked = new ArrayList ();
962 for (int i = 0; i < ifaces.Length; i++) {
963 Type iface = ifaces [i];
964 foreach (Type t in already_checked) {
965 if (iface == t)
966 continue;
968 Type[] inferred = new Type [CountTypeParameters];
969 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t, inferred, null))
970 continue;
972 Report.Error (695, Location,
973 "`{0}' cannot implement both `{1}' and `{2}' " +
974 "because they may unify for some type parameter substitutions",
975 TypeManager.CSharpName (TypeBuilder), TypeManager.CSharpName (iface),
976 TypeManager.CSharpName (t));
977 return false;
980 already_checked.Add (iface);
983 return true;
986 bool error = false;
988 bool CreateTypeBuilder ()
990 try {
991 Type default_parent = null;
992 if (Kind == Kind.Struct)
993 default_parent = TypeManager.value_type;
994 else if (Kind == Kind.Enum)
995 default_parent = TypeManager.enum_type;
996 else if (Kind == Kind.Delegate)
997 default_parent = TypeManager.multicast_delegate_type;
1000 // Sets .size to 1 for structs with no instance fields
1002 int type_size = Kind == Kind.Struct && first_nonstatic_field == null ? 1 : 0;
1004 if (IsTopLevel){
1005 if (GlobalRootNamespace.Instance.IsNamespace (Name)) {
1006 Report.Error (519, Location, "`{0}' clashes with a predefined namespace", Name);
1007 return false;
1010 ModuleBuilder builder = Module.Compiled.Builder;
1011 TypeBuilder = builder.DefineType (
1012 Name, TypeAttr, default_parent, type_size);
1013 } else {
1014 TypeBuilder builder = Parent.TypeBuilder;
1016 TypeBuilder = builder.DefineNestedType (
1017 Basename, TypeAttr, default_parent, type_size);
1019 } catch (ArgumentException) {
1020 Report.RuntimeMissingSupport (Location, "static classes");
1021 return false;
1024 TypeManager.AddUserType (this);
1026 if (IsGeneric) {
1027 string[] param_names = new string [TypeParameters.Length];
1028 for (int i = 0; i < TypeParameters.Length; i++)
1029 param_names [i] = TypeParameters [i].Name;
1031 GenericTypeParameterBuilder[] gen_params = TypeBuilder.DefineGenericParameters (param_names);
1033 int offset = CountTypeParameters;
1034 if (CurrentTypeParameters != null)
1035 offset -= CurrentTypeParameters.Length;
1037 if (offset > 0) {
1038 nested_gen_params = new GenericTypeParameterBuilder [offset];
1039 Array.Copy (gen_params, nested_gen_params, offset);
1042 for (int i = offset; i < gen_params.Length; i++)
1043 CurrentTypeParameters [i - offset].Define (gen_params [i]);
1046 return true;
1049 bool DefineBaseTypes ()
1051 iface_exprs = ResolveBaseTypes (out base_type);
1052 if (partial_parts != null) {
1053 iface_exprs = GetNormalPartialBases (ref base_type);
1057 // GetClassBases calls ResolveBaseTypeExpr() on the various type expressions involved,
1058 // which in turn should have called DefineType()s on base types if necessary.
1060 // None of the code below should trigger DefineType()s on classes that we depend on.
1061 // Thus, we are eligible to be on the topological sort `type_container_resolve_order'.
1063 // Let's do it as soon as possible, since code below can call DefineType() on classes
1064 // that depend on us to be populated before they are.
1066 if (!(this is CompilerGeneratedClass) && !(this is Delegate))
1067 RootContext.RegisterOrder (this);
1069 if (!CheckRecursiveDefinition (this))
1070 return false;
1072 if (base_type != null && base_type.Type != null) {
1073 TypeBuilder.SetParent (base_type.Type);
1076 // add interfaces that were not added at type creation
1077 if (iface_exprs != null) {
1078 ifaces = TypeManager.ExpandInterfaces (iface_exprs);
1079 if (ifaces == null)
1080 return false;
1082 foreach (Type itype in ifaces)
1083 TypeBuilder.AddInterfaceImplementation (itype);
1085 if (!CheckGenericInterfaces (ifaces))
1086 return false;
1088 TypeManager.RegisterBuilder (TypeBuilder, ifaces);
1091 return true;
1095 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1097 public TypeBuilder CreateType ()
1099 if (TypeBuilder != null)
1100 return TypeBuilder;
1102 if (error)
1103 return null;
1105 if (!CreateTypeBuilder ()) {
1106 error = true;
1107 return null;
1110 if (partial_parts != null) {
1111 foreach (TypeContainer part in partial_parts)
1112 part.TypeBuilder = TypeBuilder;
1115 if (Types != null) {
1116 foreach (TypeContainer tc in Types) {
1117 if (tc.CreateType () == null) {
1118 error = true;
1119 return null;
1124 return TypeBuilder;
1127 bool type_defined;
1129 public override TypeBuilder DefineType ()
1131 if (error)
1132 return null;
1133 if (type_defined)
1134 return TypeBuilder;
1136 type_defined = true;
1138 if (CreateType () == null) {
1139 error = true;
1140 return null;
1143 if (!DefineBaseTypes ()) {
1144 error = true;
1145 return null;
1148 if (!DefineNestedTypes ()) {
1149 error = true;
1150 return null;
1153 return TypeBuilder;
1156 public override void SetParameterInfo (ArrayList constraints_list)
1158 base.SetParameterInfo (constraints_list);
1160 if (!is_generic || PartialContainer == this)
1161 return;
1163 TypeParameter[] tc_names = PartialContainer.TypeParameters;
1164 for (int i = 0; i < tc_names.Length; ++i) {
1165 if (tc_names [i].Name != type_params [i].Name) {
1166 Report.SymbolRelatedToPreviousError (PartialContainer.Location, "");
1167 Report.Error (264, Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
1168 GetSignatureForError ());
1169 break;
1172 if (tc_names [i].Variance != type_params [i].Variance) {
1173 Report.SymbolRelatedToPreviousError (PartialContainer.Location, "");
1174 Report.Error (1067, Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers",
1175 GetSignatureForError ());
1176 break;
1181 void UpdateTypeParameterConstraints (TypeContainer part)
1183 TypeParameter[] current_params = type_params;
1184 for (int i = 0; i < current_params.Length; i++) {
1185 Constraints c = part.type_params [i].Constraints;
1186 if (c == null)
1187 continue;
1189 if (current_params [i].UpdateConstraints (part, c))
1190 continue;
1192 Report.SymbolRelatedToPreviousError (Location, "");
1193 Report.Error (265, part.Location,
1194 "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'",
1195 GetSignatureForError (), current_params [i].GetSignatureForError ());
1199 public bool ResolveType ()
1201 if (!DoResolveType ())
1202 return false;
1204 if (compiler_generated != null) {
1205 foreach (CompilerGeneratedClass c in compiler_generated)
1206 if (!c.ResolveType ())
1207 return false;
1210 return true;
1213 protected virtual bool DoResolveType ()
1215 if (!IsGeneric)
1216 return true;
1218 if (PartialContainer != this)
1219 throw new InternalErrorException ();
1221 TypeExpr current_type = null;
1222 if (CurrentTypeParameters != null) {
1223 foreach (TypeParameter type_param in CurrentTypeParameters) {
1224 if (!type_param.Resolve (this)) {
1225 error = true;
1226 return false;
1230 if (partial_parts != null) {
1231 foreach (TypeContainer part in partial_parts)
1232 UpdateTypeParameterConstraints (part);
1236 for (int i = 0; i < TypeParameters.Length; ++i) {
1238 // FIXME: Same should be done for delegates
1239 // TODO: Quite ugly way how to propagate constraints to
1240 // nested types
1242 if (nested_gen_params != null && i < nested_gen_params.Length) {
1243 TypeParameters [i].SetConstraints (nested_gen_params [i]);
1244 } else {
1245 if (!TypeParameters [i].DefineType (this)) {
1246 error = true;
1247 return false;
1252 // TODO: Very strange, why not simple make generic type from
1253 // current type parameters
1254 current_type = new GenericTypeExpr (this, Location);
1255 current_type = current_type.ResolveAsTypeTerminal (this, false);
1256 if (current_type == null) {
1257 error = true;
1258 return false;
1261 currentType = current_type.Type;
1262 return true;
1265 protected virtual bool DefineNestedTypes ()
1267 if (Types != null) {
1268 foreach (TypeContainer tc in Types)
1269 if (tc.DefineType () == null)
1270 return false;
1273 if (Delegates != null) {
1274 foreach (Delegate d in Delegates)
1275 if (d.DefineType () == null)
1276 return false;
1279 return true;
1282 TypeContainer InTransit;
1284 protected bool CheckRecursiveDefinition (TypeContainer tc)
1286 if (InTransit != null) {
1287 Report.SymbolRelatedToPreviousError (this);
1288 if (this is Interface)
1289 Report.Error (
1290 529, tc.Location, "Inherited interface `{0}' causes a " +
1291 "cycle in the interface hierarchy of `{1}'",
1292 GetSignatureForError (), tc.GetSignatureForError ());
1293 else
1294 Report.Error (
1295 146, tc.Location, "Circular base class dependency " +
1296 "involving `{0}' and `{1}'",
1297 tc.GetSignatureForError (), GetSignatureForError ());
1298 return false;
1301 InTransit = tc;
1303 if (base_type != null && base_type.Type != null) {
1304 Type t = TypeManager.DropGenericTypeArguments (base_type.Type);
1305 TypeContainer ptc = TypeManager.LookupTypeContainer (t);
1306 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1307 return false;
1310 if (iface_exprs != null) {
1311 foreach (TypeExpr iface in iface_exprs) {
1312 Type itype = TypeManager.DropGenericTypeArguments (iface.Type);
1313 TypeContainer ptc = TypeManager.LookupTypeContainer (itype);
1314 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1315 return false;
1319 if (!IsTopLevel && !Parent.PartialContainer.CheckRecursiveDefinition (this))
1320 return false;
1322 InTransit = null;
1323 return true;
1326 public override TypeParameter[] CurrentTypeParameters {
1327 get {
1328 return PartialContainer.type_params;
1332 /// <summary>
1333 /// Populates our TypeBuilder with fields and methods
1334 /// </summary>
1335 public override bool Define ()
1337 if (members_defined)
1338 return members_defined_ok;
1340 members_defined_ok = DoDefineMembers ();
1341 members_defined = true;
1343 return members_defined_ok;
1346 protected virtual bool DoDefineMembers ()
1348 if (iface_exprs != null) {
1349 foreach (TypeExpr iface in iface_exprs) {
1350 ObsoleteAttribute oa = AttributeTester.GetObsoleteAttribute (iface.Type);
1351 if ((oa != null) && !IsObsolete)
1352 AttributeTester.Report_ObsoleteMessage (
1353 oa, iface.GetSignatureForError (), Location, Report);
1355 GenericTypeExpr ct = iface as GenericTypeExpr;
1356 if (ct != null) {
1357 // TODO: passing `this' is wrong, should be base type iface instead
1358 TypeManager.CheckTypeVariance (ct.Type, Variance.Covariant, this);
1360 if (!ct.CheckConstraints (this))
1361 return false;
1363 if (ct.HasDynamicArguments ()) {
1364 Report.Error (1966, iface.Location,
1365 "`{0}': cannot implement a dynamic interface `{1}'",
1366 GetSignatureForError (), iface.GetSignatureForError ());
1367 return false;
1373 if (base_type != null) {
1374 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (base_type.Type);
1375 if (obsolete_attr != null && !IsObsolete)
1376 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), Location, Report);
1378 GenericTypeExpr ct = base_type as GenericTypeExpr;
1379 if ((ct != null) && !ct.CheckConstraints (this))
1380 return false;
1382 TypeContainer baseContainer = TypeManager.LookupTypeContainer(base_type.Type);
1383 if (baseContainer != null)
1384 baseContainer.Define();
1386 member_cache = new MemberCache (base_type.Type, this);
1387 } else if (Kind == Kind.Interface) {
1388 member_cache = new MemberCache (null, this);
1389 Type [] ifaces = TypeManager.GetInterfaces (TypeBuilder);
1390 for (int i = 0; i < ifaces.Length; ++i)
1391 member_cache.AddInterface (TypeManager.LookupMemberCache (ifaces [i]));
1392 } else {
1393 member_cache = new MemberCache (null, this);
1396 if (types != null)
1397 foreach (TypeContainer tc in types)
1398 member_cache.AddNestedType (tc);
1400 if (delegates != null)
1401 foreach (Delegate d in delegates)
1402 member_cache.AddNestedType (d);
1404 if (partial_parts != null) {
1405 foreach (TypeContainer part in partial_parts)
1406 part.member_cache = member_cache;
1409 if (!IsTopLevel) {
1410 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Basename, false);
1411 if (conflict_symbol == null) {
1412 if ((ModFlags & Modifiers.NEW) != 0)
1413 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
1414 } else {
1415 if ((ModFlags & Modifiers.NEW) == 0) {
1416 Report.SymbolRelatedToPreviousError (conflict_symbol);
1417 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
1418 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
1423 DefineContainerMembers (constants);
1424 DefineContainerMembers (fields);
1426 if (Kind == Kind.Struct || Kind == Kind.Class) {
1427 pending = PendingImplementation.GetPendingImplementations (this);
1429 if (requires_delayed_unmanagedtype_check) {
1430 requires_delayed_unmanagedtype_check = false;
1431 foreach (FieldBase f in fields) {
1432 if (f.MemberType != null && f.MemberType.IsPointer)
1433 TypeManager.VerifyUnmanaged (Compiler, f.MemberType, f.Location);
1439 // Constructors are not in the defined_names array
1441 DefineContainerMembers (instance_constructors);
1443 DefineContainerMembers (events);
1444 DefineContainerMembers (ordered_explicit_member_list);
1445 DefineContainerMembers (ordered_member_list);
1447 DefineContainerMembers (operators);
1448 DefineContainerMembers (delegates);
1450 ComputeIndexerName();
1451 CheckEqualsAndGetHashCode();
1453 if (CurrentType != null) {
1454 GenericType = CurrentType;
1458 // FIXME: This hack is needed because member cache does not work
1459 // with generic types, we rely on runtime to inflate dynamic types.
1460 // TODO: This hack requires member cache refactoring to be removed
1462 if (TypeManager.IsGenericType (TypeBuilder))
1463 member_cache = new MemberCache (this);
1465 return true;
1468 protected virtual void DefineContainerMembers (MemberCoreArrayList mcal)
1470 if (mcal != null)
1471 mcal.DefineContainerMembers ();
1474 protected virtual void ComputeIndexerName ()
1476 if (indexers == null)
1477 return;
1479 string class_indexer_name = null;
1482 // If there's both an explicit and an implicit interface implementation, the
1483 // explicit one actually implements the interface while the other one is just
1484 // a normal indexer. See bug #37714.
1487 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
1488 foreach (Indexer i in indexers) {
1489 if (i.InterfaceType != null) {
1490 if (seen_normal_indexers)
1491 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
1492 continue;
1495 seen_normal_indexers = true;
1497 if (class_indexer_name == null) {
1498 class_indexer_name = i.ShortName;
1499 continue;
1502 if (i.ShortName != class_indexer_name)
1503 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");
1506 if (class_indexer_name != null)
1507 indexer_name = class_indexer_name;
1510 protected virtual void EmitIndexerName ()
1512 if (!seen_normal_indexers)
1513 return;
1515 PredefinedAttribute pa = PredefinedAttributes.Get.DefaultMember;
1516 if (pa.Constructor == null &&
1517 !pa.ResolveConstructor (Location, TypeManager.string_type))
1518 return;
1520 CustomAttributeBuilder cb = new CustomAttributeBuilder (pa.Constructor, new string [] { IndexerName });
1521 TypeBuilder.SetCustomAttribute (cb);
1524 protected virtual void CheckEqualsAndGetHashCode ()
1526 if (methods == null)
1527 return;
1529 if (HasEquals && !HasGetHashCode) {
1530 Report.Warning (659, 3, this.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", this.GetSignatureForError ());
1534 public MemberInfo FindBaseMemberWithSameName (string name, bool ignore_methods)
1536 return BaseCache == null ? null : BaseCache.FindMemberWithSameName (name, ignore_methods, null);
1539 /// <summary>
1540 /// This function is based by a delegate to the FindMembers routine
1541 /// </summary>
1542 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1544 return true;
1547 /// <summary>
1548 /// This filter is used by FindMembers, and we just keep
1549 /// a global for the filter to `AlwaysAccept'
1550 /// </summary>
1551 static MemberFilter accepting_filter;
1554 static TypeContainer ()
1556 accepting_filter = new MemberFilter (AlwaysAccept);
1559 public MethodInfo[] GetMethods ()
1561 ArrayList members = new ArrayList ();
1563 Define ();
1565 if (methods != null) {
1566 int len = methods.Count;
1567 for (int i = 0; i < len; i++) {
1568 Method m = (Method) methods [i];
1570 members.Add (m.MethodBuilder);
1574 if (operators != null) {
1575 int len = operators.Count;
1576 for (int i = 0; i < len; i++) {
1577 Operator o = (Operator) operators [i];
1579 members.Add (o.MethodBuilder);
1583 if (properties != null) {
1584 int len = properties.Count;
1585 for (int i = 0; i < len; i++) {
1586 Property p = (Property) properties [i];
1588 if (p.GetBuilder != null)
1589 members.Add (p.GetBuilder);
1590 if (p.SetBuilder != null)
1591 members.Add (p.SetBuilder);
1595 if (indexers != null) {
1596 int len = indexers.Count;
1597 for (int i = 0; i < len; i++) {
1598 Indexer ix = (Indexer) indexers [i];
1600 if (ix.GetBuilder != null)
1601 members.Add (ix.GetBuilder);
1602 if (ix.SetBuilder != null)
1603 members.Add (ix.SetBuilder);
1607 if (events != null) {
1608 int len = events.Count;
1609 for (int i = 0; i < len; i++) {
1610 Event e = (Event) events [i];
1612 if (e.AddBuilder != null)
1613 members.Add (e.AddBuilder);
1614 if (e.RemoveBuilder != null)
1615 members.Add (e.RemoveBuilder);
1619 MethodInfo[] retMethods = new MethodInfo [members.Count];
1620 members.CopyTo (retMethods, 0);
1621 return retMethods;
1624 // Indicated whether container has StructLayout attribute set Explicit
1625 public bool HasExplicitLayout {
1626 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
1627 set { caching_flags |= Flags.HasExplicitLayout; }
1630 public bool HasStructLayout {
1631 get { return (caching_flags & Flags.HasStructLayout) != 0; }
1632 set { caching_flags |= Flags.HasStructLayout; }
1636 // Return the nested type with name @name. Ensures that the nested type
1637 // is defined if necessary. Do _not_ use this when you have a MemberCache handy.
1639 public Type FindNestedType (string name)
1641 if (PartialContainer != this)
1642 throw new InternalErrorException ("should not happen");
1644 ArrayList [] lists = { types, delegates };
1646 for (int j = 0; j < lists.Length; ++j) {
1647 ArrayList list = lists [j];
1648 if (list == null)
1649 continue;
1651 int len = list.Count;
1652 for (int i = 0; i < len; ++i) {
1653 DeclSpace ds = (DeclSpace) list [i];
1654 if (ds.Basename == name) {
1655 return ds.DefineType ();
1660 return null;
1663 private void FindMembers_NestedTypes (int modflags,
1664 BindingFlags bf, MemberFilter filter, object criteria,
1665 ref ArrayList members)
1667 ArrayList [] lists = { types, delegates };
1669 for (int j = 0; j < lists.Length; ++j) {
1670 ArrayList list = lists [j];
1671 if (list == null)
1672 continue;
1674 int len = list.Count;
1675 for (int i = 0; i < len; i++) {
1676 DeclSpace ds = (DeclSpace) list [i];
1678 if ((ds.ModFlags & modflags) == 0)
1679 continue;
1681 TypeBuilder tb = ds.TypeBuilder;
1682 if (tb == null) {
1683 if (!(criteria is string) || ds.Basename.Equals (criteria))
1684 tb = ds.DefineType ();
1687 if (tb != null && (filter (tb, criteria) == true)) {
1688 if (members == null)
1689 members = new ArrayList ();
1691 members.Add (tb);
1697 /// <summary>
1698 /// This method returns the members of this type just like Type.FindMembers would
1699 /// Only, we need to use this for types which are _being_ defined because MS'
1700 /// implementation can't take care of that.
1701 /// </summary>
1703 // FIXME: return an empty static array instead of null, that cleans up
1704 // some code and is consistent with some coding conventions I just found
1705 // out existed ;-)
1708 // Notice that in various cases we check if our field is non-null,
1709 // something that would normally mean that there was a bug elsewhere.
1711 // The problem happens while we are defining p-invoke methods, as those
1712 // will trigger a FindMembers, but this happens before things are defined
1714 // Since the whole process is a no-op, it is fine to check for null here.
1716 // TODO: This approach will be one day completely removed, it's already
1717 // used at few places only
1720 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1721 MemberFilter filter, object criteria)
1723 ArrayList members = null;
1725 int modflags = 0;
1726 if ((bf & BindingFlags.Public) != 0)
1727 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1728 Modifiers.INTERNAL;
1729 if ((bf & BindingFlags.NonPublic) != 0)
1730 modflags |= Modifiers.PRIVATE;
1732 int static_mask = 0, static_flags = 0;
1733 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1734 case BindingFlags.Static:
1735 static_mask = static_flags = Modifiers.STATIC;
1736 break;
1738 case BindingFlags.Instance:
1739 static_mask = Modifiers.STATIC;
1740 static_flags = 0;
1741 break;
1743 default:
1744 static_mask = static_flags = 0;
1745 break;
1748 Timer.StartTimer (TimerType.TcFindMembers);
1750 if (filter == null)
1751 filter = accepting_filter;
1753 if ((mt & MemberTypes.Field) != 0) {
1754 if (fields != null) {
1755 int len = fields.Count;
1756 for (int i = 0; i < len; i++) {
1757 FieldBase f = (FieldBase) fields [i];
1759 if ((f.ModFlags & modflags) == 0)
1760 continue;
1761 if ((f.ModFlags & static_mask) != static_flags)
1762 continue;
1764 FieldBuilder fb = f.FieldBuilder;
1765 if (fb != null && filter (fb, criteria) == true) {
1766 if (members == null)
1767 members = new ArrayList ();
1769 members.Add (fb);
1774 if (constants != null) {
1775 int len = constants.Count;
1776 for (int i = 0; i < len; i++) {
1777 Const con = (Const) constants [i];
1779 if ((con.ModFlags & modflags) == 0)
1780 continue;
1781 if ((con.ModFlags & static_mask) != static_flags)
1782 continue;
1784 FieldBuilder fb = con.FieldBuilder;
1785 if (fb == null) {
1786 // Define parent and not member, otherwise membercache can be null
1787 if (con.Parent.Define ())
1788 fb = con.FieldBuilder;
1790 if (fb != null && filter (fb, criteria) == true) {
1791 if (members == null)
1792 members = new ArrayList ();
1794 members.Add (fb);
1800 if ((mt & MemberTypes.Method) != 0) {
1801 if (methods != null) {
1802 int len = methods.Count;
1803 for (int i = 0; i < len; i++) {
1804 MethodOrOperator m = (MethodOrOperator) methods [i];
1806 if ((m.ModFlags & modflags) == 0)
1807 continue;
1808 if ((m.ModFlags & static_mask) != static_flags)
1809 continue;
1811 MethodBuilder mb = m.MethodBuilder;
1813 if (mb != null && filter (mb, criteria) == true) {
1814 if (members == null)
1815 members = new ArrayList ();
1817 members.Add (mb);
1822 if (operators != null) {
1823 int len = operators.Count;
1824 for (int i = 0; i < len; i++) {
1825 Operator o = (Operator) operators [i];
1827 if ((o.ModFlags & modflags) == 0)
1828 continue;
1829 if ((o.ModFlags & static_mask) != static_flags)
1830 continue;
1832 MethodBuilder ob = o.MethodBuilder;
1833 if (ob != null && filter (ob, criteria) == true) {
1834 if (members == null)
1835 members = new ArrayList ();
1837 members.Add (ob);
1842 if (events != null) {
1843 foreach (Event e in events) {
1844 if ((e.ModFlags & modflags) == 0)
1845 continue;
1846 if ((e.ModFlags & static_mask) != static_flags)
1847 continue;
1849 MethodBuilder b = e.AddBuilder;
1850 if (b != null && filter (b, criteria)) {
1851 if (members == null)
1852 members = new ArrayList (4);
1854 members.Add (b);
1857 b = e.RemoveBuilder;
1858 if (b != null && filter (b, criteria)) {
1859 if (members == null)
1860 members = new ArrayList (4);
1862 members.Add (b);
1867 if (properties != null) {
1868 int len = properties.Count;
1869 for (int i = 0; i < len; i++) {
1870 Property p = (Property) properties [i];
1872 if ((p.ModFlags & modflags) == 0)
1873 continue;
1874 if ((p.ModFlags & static_mask) != static_flags)
1875 continue;
1877 MethodBuilder b;
1879 b = p.GetBuilder;
1880 if (b != null && filter (b, criteria) == true) {
1881 if (members == null)
1882 members = new ArrayList ();
1884 members.Add (b);
1887 b = p.SetBuilder;
1888 if (b != null && filter (b, criteria) == true) {
1889 if (members == null)
1890 members = new ArrayList ();
1892 members.Add (b);
1897 if (indexers != null) {
1898 int len = indexers.Count;
1899 for (int i = 0; i < len; i++) {
1900 Indexer ix = (Indexer) indexers [i];
1902 if ((ix.ModFlags & modflags) == 0)
1903 continue;
1904 if ((ix.ModFlags & static_mask) != static_flags)
1905 continue;
1907 MethodBuilder b;
1909 b = ix.GetBuilder;
1910 if (b != null && filter (b, criteria) == true) {
1911 if (members == null)
1912 members = new ArrayList ();
1914 members.Add (b);
1917 b = ix.SetBuilder;
1918 if (b != null && filter (b, criteria) == true) {
1919 if (members == null)
1920 members = new ArrayList ();
1922 members.Add (b);
1928 if ((mt & MemberTypes.Event) != 0) {
1929 if (events != null) {
1930 int len = events.Count;
1931 for (int i = 0; i < len; i++) {
1932 Event e = (Event) events [i];
1934 if ((e.ModFlags & modflags) == 0)
1935 continue;
1936 if ((e.ModFlags & static_mask) != static_flags)
1937 continue;
1939 MemberInfo eb = e.EventBuilder;
1940 if (eb != null && filter (eb, criteria) == true) {
1941 if (members == null)
1942 members = new ArrayList ();
1944 members.Add (e.EventBuilder);
1950 if ((mt & MemberTypes.Property) != 0){
1951 if (properties != null) {
1952 int len = properties.Count;
1953 for (int i = 0; i < len; i++) {
1954 Property p = (Property) properties [i];
1956 if ((p.ModFlags & modflags) == 0)
1957 continue;
1958 if ((p.ModFlags & static_mask) != static_flags)
1959 continue;
1961 MemberInfo pb = p.PropertyBuilder;
1962 if (pb != null && filter (pb, criteria) == true) {
1963 if (members == null)
1964 members = new ArrayList ();
1966 members.Add (p.PropertyBuilder);
1971 if (indexers != null) {
1972 int len = indexers.Count;
1973 for (int i = 0; i < len; i++) {
1974 Indexer ix = (Indexer) indexers [i];
1976 if ((ix.ModFlags & modflags) == 0)
1977 continue;
1978 if ((ix.ModFlags & static_mask) != static_flags)
1979 continue;
1981 MemberInfo ib = ix.PropertyBuilder;
1982 if (ib != null && filter (ib, criteria) == true) {
1983 if (members == null)
1984 members = new ArrayList ();
1986 members.Add (ix.PropertyBuilder);
1992 if ((mt & MemberTypes.NestedType) != 0)
1993 FindMembers_NestedTypes (modflags, bf, filter, criteria, ref members);
1995 if ((mt & MemberTypes.Constructor) != 0){
1996 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1997 int len = instance_constructors.Count;
1998 for (int i = 0; i < len; i++) {
1999 Constructor c = (Constructor) instance_constructors [i];
2001 ConstructorBuilder cb = c.ConstructorBuilder;
2002 if (cb != null && filter (cb, criteria) == true) {
2003 if (members == null)
2004 members = new ArrayList ();
2006 members.Add (cb);
2011 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
2012 ConstructorBuilder cb =
2013 default_static_constructor.ConstructorBuilder;
2015 if (cb != null && filter (cb, criteria) == true) {
2016 if (members == null)
2017 members = new ArrayList ();
2019 members.Add (cb);
2025 // Lookup members in base if requested.
2027 if ((bf & BindingFlags.DeclaredOnly) == 0) {
2028 if (TypeBuilder.BaseType != null) {
2029 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
2030 if (list.Count > 0) {
2031 if (members == null)
2032 members = new ArrayList ();
2034 members.AddRange (list);
2039 Timer.StopTimer (TimerType.TcFindMembers);
2041 if (members == null)
2042 return MemberList.Empty;
2043 else
2044 return new MemberList (members);
2047 public override MemberCache MemberCache {
2048 get {
2049 return member_cache;
2053 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
2054 MemberFilter filter, object criteria)
2056 DeclSpace ds = TypeManager.LookupDeclSpace (t);
2058 if (ds != null)
2059 return ds.FindMembers (mt, bf, filter, criteria);
2060 else
2061 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
2064 /// <summary>
2065 /// Emits the values for the constants
2066 /// </summary>
2067 public void EmitConstants ()
2069 if (constants != null)
2070 foreach (Const con in constants)
2071 con.Emit ();
2072 return;
2075 void CheckMemberUsage (MemberCoreArrayList al, string member_type)
2077 if (al == null)
2078 return;
2080 foreach (MemberCore mc in al) {
2081 if ((mc.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
2082 continue;
2084 if (!mc.IsUsed && (mc.caching_flags & Flags.Excluded) == 0) {
2085 Report.Warning (169, 3, mc.Location, "The private {0} `{1}' is never used", member_type, mc.GetSignatureForError ());
2090 public virtual void VerifyMembers ()
2093 // Check for internal or private fields that were never assigned
2095 if (Report.WarningLevel >= 3) {
2096 CheckMemberUsage (properties, "property");
2097 CheckMemberUsage (methods, "method");
2098 CheckMemberUsage (constants, "constant");
2100 if (fields != null){
2101 bool is_type_exposed = Kind == Kind.Struct || IsExposedFromAssembly ();
2102 foreach (FieldBase f in fields) {
2103 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE) {
2104 if (is_type_exposed)
2105 continue;
2107 f.SetMemberIsUsed ();
2110 if (!f.IsUsed){
2111 if ((f.caching_flags & Flags.IsAssigned) == 0)
2112 Report.Warning (169, 3, f.Location, "The private field `{0}' is never used", f.GetSignatureForError ());
2113 else {
2114 Report.Warning (414, 3, f.Location, "The private field `{0}' is assigned but its value is never used",
2115 f.GetSignatureForError ());
2117 continue;
2121 // Only report 649 on level 4
2123 if (Report.WarningLevel < 4)
2124 continue;
2126 if ((f.caching_flags & Flags.IsAssigned) != 0)
2127 continue;
2130 // Don't be pendatic over serializable attributes
2132 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2133 continue;
2135 Constant c = New.Constantify (f.MemberType);
2136 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value `{1}'",
2137 f.GetSignatureForError (), c == null ? "null" : c.AsString ());
2143 // TODO: move to ClassOrStruct
2144 void EmitConstructors ()
2146 if (instance_constructors == null)
2147 return;
2149 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && RootContext.VerifyClsCompliance && IsClsComplianceRequired ()) {
2150 bool has_compliant_args = false;
2152 foreach (Constructor c in instance_constructors) {
2153 try {
2154 c.Emit ();
2156 catch (Exception e) {
2157 throw new InternalErrorException (c, e);
2160 if (has_compliant_args)
2161 continue;
2163 has_compliant_args = c.HasCompliantArgs;
2165 if (!has_compliant_args)
2166 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2167 } else {
2168 foreach (Constructor c in instance_constructors) {
2169 try {
2170 c.Emit ();
2172 catch (Exception e) {
2173 throw new InternalErrorException (c, e);
2179 /// <summary>
2180 /// Emits the code, this step is performed after all
2181 /// the types, enumerations, constructors
2182 /// </summary>
2183 public virtual void EmitType ()
2185 if (OptAttributes != null)
2186 OptAttributes.Emit ();
2188 Emit ();
2190 EmitConstructors ();
2192 // Can not continue if constants are broken
2193 EmitConstants ();
2194 if (Report.Errors > 0)
2195 return;
2197 if (default_static_constructor != null)
2198 default_static_constructor.Emit ();
2200 if (operators != null)
2201 foreach (Operator o in operators)
2202 o.Emit ();
2204 if (properties != null)
2205 foreach (Property p in properties)
2206 p.Emit ();
2208 if (indexers != null) {
2209 foreach (Indexer indx in indexers)
2210 indx.Emit ();
2211 EmitIndexerName ();
2214 if (events != null){
2215 foreach (Event e in Events)
2216 e.Emit ();
2219 if (methods != null) {
2220 for (int i = 0; i < methods.Count; ++i)
2221 ((MethodOrOperator) methods [i]).Emit ();
2224 if (fields != null)
2225 foreach (FieldBase f in fields)
2226 f.Emit ();
2228 if (delegates != null) {
2229 foreach (Delegate d in Delegates) {
2230 d.Emit ();
2234 if (pending != null)
2235 pending.VerifyPendingMethods (Report);
2237 if (Report.Errors > 0)
2238 return;
2240 if (compiler_generated != null) {
2241 for (int i = 0; i < compiler_generated.Count; ++i)
2242 ((CompilerGeneratedClass) compiler_generated [i]).EmitType ();
2246 public override void CloseType ()
2248 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2249 return;
2251 try {
2252 caching_flags |= Flags.CloseTypeCreated;
2253 TypeBuilder.CreateType ();
2254 } catch (TypeLoadException){
2256 // This is fine, the code still created the type
2258 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
2259 // Console.WriteLine (e.Message);
2260 } catch (Exception e) {
2261 throw new InternalErrorException (this, e);
2264 if (Types != null){
2265 foreach (TypeContainer tc in Types)
2266 if (tc.Kind == Kind.Struct)
2267 tc.CloseType ();
2269 foreach (TypeContainer tc in Types)
2270 if (tc.Kind != Kind.Struct)
2271 tc.CloseType ();
2274 if (Delegates != null)
2275 foreach (Delegate d in Delegates)
2276 d.CloseType ();
2278 if (compiler_generated != null)
2279 foreach (CompilerGeneratedClass c in compiler_generated)
2280 c.CloseType ();
2282 PartialContainer = null;
2283 types = null;
2284 // properties = null;
2285 delegates = null;
2286 fields = null;
2287 initialized_fields = null;
2288 initialized_static_fields = null;
2289 constants = null;
2290 ordered_explicit_member_list = null;
2291 ordered_member_list = null;
2292 methods = null;
2293 events = null;
2294 indexers = null;
2295 operators = null;
2296 compiler_generated = null;
2297 default_constructor = null;
2298 default_static_constructor = null;
2299 type_bases = null;
2300 OptAttributes = null;
2301 ifaces = null;
2302 base_cache = null;
2303 member_cache = null;
2307 // Performs the validation on a Method's modifiers (properties have
2308 // the same properties).
2310 public bool MethodModifiersValid (MemberCore mc)
2312 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2313 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2314 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2315 bool ok = true;
2316 int flags = mc.ModFlags;
2319 // At most one of static, virtual or override
2321 if ((flags & Modifiers.STATIC) != 0){
2322 if ((flags & vao) != 0){
2323 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2324 mc.GetSignatureForError ());
2325 ok = false;
2329 if (Kind == Kind.Struct){
2330 if ((flags & va) != 0){
2331 Modifiers.Error_InvalidModifier (mc.Location, "virtual or abstract", Report);
2332 ok = false;
2336 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2337 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2338 mc.GetSignatureForError ());
2339 ok = false;
2343 // If the declaration includes the abstract modifier, then the
2344 // declaration does not include static, virtual or extern
2346 if ((flags & Modifiers.ABSTRACT) != 0){
2347 if ((flags & Modifiers.EXTERN) != 0){
2348 Report.Error (
2349 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2350 ok = false;
2353 if ((flags & Modifiers.SEALED) != 0) {
2354 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2355 ok = false;
2358 if ((flags & Modifiers.VIRTUAL) != 0){
2359 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2360 ok = false;
2363 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2364 Report.SymbolRelatedToPreviousError (this);
2365 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2366 mc.GetSignatureForError (), GetSignatureForError ());
2367 ok = false;
2371 if ((flags & Modifiers.PRIVATE) != 0){
2372 if ((flags & vao) != 0){
2373 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2374 ok = false;
2378 if ((flags & Modifiers.SEALED) != 0){
2379 if ((flags & Modifiers.OVERRIDE) == 0){
2380 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2381 ok = false;
2385 return ok;
2388 public Constructor DefaultStaticConstructor {
2389 get { return default_static_constructor; }
2392 protected override bool VerifyClsCompliance ()
2394 if (!base.VerifyClsCompliance ())
2395 return false;
2397 VerifyClsName ();
2399 Type base_type = TypeBuilder.BaseType;
2400 if (base_type != null && !AttributeTester.IsClsCompliant (base_type)) {
2401 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (base_type));
2403 return true;
2407 /// <summary>
2408 /// Checks whether container name is CLS Compliant
2409 /// </summary>
2410 void VerifyClsName ()
2412 Hashtable base_members = base_cache == null ?
2413 new Hashtable () :
2414 base_cache.GetPublicMembers ();
2415 Hashtable this_members = new Hashtable ();
2417 foreach (DictionaryEntry entry in defined_names) {
2418 MemberCore mc = (MemberCore)entry.Value;
2419 if (!mc.IsClsComplianceRequired ())
2420 continue;
2422 string name = (string) entry.Key;
2423 string basename = name.Substring (name.LastIndexOf ('.') + 1);
2425 string lcase = basename.ToLower (System.Globalization.CultureInfo.InvariantCulture);
2426 object found = base_members [lcase];
2427 if (found == null) {
2428 found = this_members [lcase];
2429 if (found == null) {
2430 this_members.Add (lcase, mc);
2431 continue;
2435 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
2436 continue;
2438 if (found is MemberInfo) {
2439 if (basename == ((MemberInfo) found).Name)
2440 continue;
2441 Report.SymbolRelatedToPreviousError ((MemberInfo) found);
2442 } else {
2443 Report.SymbolRelatedToPreviousError ((MemberCore) found);
2446 Report.Warning (3005, 1, mc.Location, "Identifier `{0}' differing only in case is not CLS-compliant", mc.GetSignatureForError ());
2451 /// <summary>
2452 /// Performs checks for an explicit interface implementation. First it
2453 /// checks whether the `interface_type' is a base inteface implementation.
2454 /// Then it checks whether `name' exists in the interface type.
2455 /// </summary>
2456 public bool VerifyImplements (InterfaceMemberBase mb)
2458 if (ifaces != null) {
2459 foreach (Type t in ifaces){
2460 if (TypeManager.IsEqual (t, mb.InterfaceType))
2461 return true;
2465 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2466 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2467 mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType));
2468 return false;
2471 public override Type LookupAnyGeneric (string typeName)
2473 if (types != null) {
2474 foreach (TypeContainer tc in types) {
2475 if (!tc.IsGeneric)
2476 continue;
2478 int pos = tc.Basename.LastIndexOf ('`');
2479 if (pos == typeName.Length && String.Compare (typeName, 0, tc.Basename, 0, pos) == 0)
2480 return tc.TypeBuilder;
2484 return base.LookupAnyGeneric (typeName);
2487 public void Mark_HasEquals ()
2489 cached_method |= CachedMethods.Equals;
2492 public void Mark_HasGetHashCode ()
2494 cached_method |= CachedMethods.GetHashCode;
2497 /// <summary>
2498 /// Method container contains Equals method
2499 /// </summary>
2500 public bool HasEquals {
2501 get {
2502 return (cached_method & CachedMethods.Equals) != 0;
2506 /// <summary>
2507 /// Method container contains GetHashCode method
2508 /// </summary>
2509 public bool HasGetHashCode {
2510 get {
2511 return (cached_method & CachedMethods.GetHashCode) != 0;
2515 public bool HasStaticFieldInitializer {
2516 get {
2517 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2519 set {
2520 if (value)
2521 cached_method |= CachedMethods.HasStaticFieldInitializer;
2522 else
2523 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2528 // IMemberContainer
2531 string IMemberContainer.Name {
2532 get {
2533 return Name;
2537 Type IMemberContainer.Type {
2538 get {
2539 return TypeBuilder;
2543 bool IMemberContainer.IsInterface {
2544 get {
2545 return Kind == Kind.Interface;
2549 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2551 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2553 if (GenericType != null)
2554 return TypeManager.FindMembers (GenericType, mt, new_bf,
2555 null, null);
2556 else
2557 return FindMembers (mt, new_bf, null, null);
2561 // Generates xml doc comments (if any), and if required,
2562 // handle warning report.
2564 internal override void GenerateDocComment (DeclSpace ds)
2566 DocUtil.GenerateTypeDocComment (this, ds, Report);
2569 public override string DocCommentHeader {
2570 get { return "T:"; }
2573 public MemberCache BaseCache {
2574 get {
2575 if (base_cache != null)
2576 return base_cache;
2577 if (TypeBuilder.BaseType != null)
2578 base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
2579 if (TypeBuilder.IsInterface)
2580 base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
2581 return base_cache;
2586 public abstract class ClassOrStruct : TypeContainer {
2587 ListDictionary declarative_security;
2589 public ClassOrStruct (NamespaceEntry ns, DeclSpace parent,
2590 MemberName name, Attributes attrs, Kind kind)
2591 : base (ns, parent, name, attrs, kind)
2595 protected override bool AddToContainer (MemberCore symbol, string name)
2597 if (name == MemberName.Name) {
2598 if (symbol is TypeParameter) {
2599 Report.Error (694, symbol.Location,
2600 "Type parameter `{0}' has same name as containing type, or method",
2601 symbol.GetSignatureForError ());
2602 return false;
2605 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2606 if (imb == null || !imb.IsExplicitImpl) {
2607 Report.SymbolRelatedToPreviousError (this);
2608 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2609 symbol.GetSignatureForError ());
2610 return false;
2614 return base.AddToContainer (symbol, name);
2617 public override void VerifyMembers ()
2619 base.VerifyMembers ();
2621 if ((events != null) && Report.WarningLevel >= 3) {
2622 foreach (Event e in events){
2623 // Note: The event can be assigned from same class only, so we can report
2624 // this warning for all accessibility modes
2625 if ((e.caching_flags & Flags.IsUsed) == 0)
2626 Report.Warning (67, 3, e.Location, "The event `{0}' is never used", e.GetSignatureForError ());
2631 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2633 if (a.IsValidSecurityAttribute ()) {
2634 if (declarative_security == null)
2635 declarative_security = new ListDictionary ();
2637 a.ExtractSecurityPermissionSet (declarative_security);
2638 return;
2641 if (a.Type == pa.StructLayout) {
2642 PartialContainer.HasStructLayout = true;
2644 if (a.GetLayoutKindValue () == LayoutKind.Explicit)
2645 PartialContainer.HasExplicitLayout = true;
2648 if (a.Type == pa.Dynamic) {
2649 a.Error_MisusedDynamicAttribute ();
2650 return;
2653 base.ApplyAttributeBuilder (a, cb, pa);
2656 /// <summary>
2657 /// Defines the default constructors
2658 /// </summary>
2659 protected void DefineDefaultConstructor (bool is_static)
2661 // The default instance constructor is public
2662 // If the class is abstract, the default constructor is protected
2663 // The default static constructor is private
2665 int mods;
2666 if (is_static) {
2667 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2668 } else {
2669 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2672 Constructor c = new Constructor (this, MemberName.Name, mods,
2673 null, ParametersCompiled.EmptyReadOnlyParameters,
2674 new GeneratedBaseInitializer (Location),
2675 Location);
2677 AddConstructor (c);
2678 c.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
2681 public override bool Define ()
2683 CheckProtectedModifier ();
2685 base.Define ();
2687 if (default_static_constructor != null)
2688 default_static_constructor.Define ();
2690 return true;
2693 public override void Emit ()
2695 if (default_static_constructor == null && PartialContainer.HasStaticFieldInitializer) {
2696 DefineDefaultConstructor (true);
2697 default_static_constructor.Define ();
2700 base.Emit ();
2702 if (declarative_security != null) {
2703 foreach (DictionaryEntry de in declarative_security) {
2704 TypeBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
2709 public override ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
2711 DeclSpace top_level = Parent;
2712 if (top_level != null) {
2713 while (top_level.Parent != null)
2714 top_level = top_level.Parent;
2716 ArrayList candidates = NamespaceEntry.NS.LookupExtensionMethod (extensionType, this, name);
2717 if (candidates != null)
2718 return new ExtensionMethodGroupExpr (candidates, NamespaceEntry, extensionType, loc);
2721 return NamespaceEntry.LookupExtensionMethod (extensionType, name, loc);
2724 protected override TypeAttributes TypeAttr {
2725 get {
2726 if (default_static_constructor == null)
2727 return base.TypeAttr | TypeAttributes.BeforeFieldInit;
2729 return base.TypeAttr;
2735 // TODO: should be sealed
2736 public class Class : ClassOrStruct {
2737 const int AllowedModifiers =
2738 Modifiers.NEW |
2739 Modifiers.PUBLIC |
2740 Modifiers.PROTECTED |
2741 Modifiers.INTERNAL |
2742 Modifiers.PRIVATE |
2743 Modifiers.ABSTRACT |
2744 Modifiers.SEALED |
2745 Modifiers.STATIC |
2746 Modifiers.UNSAFE;
2748 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2750 public Class (NamespaceEntry ns, DeclSpace parent, MemberName name, int mod,
2751 Attributes attrs)
2752 : base (ns, parent, name, attrs, Kind.Class)
2754 int accmods = Parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2755 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, Location, Report);
2757 if (IsStatic && RootContext.Version == LanguageVersion.ISO_1) {
2758 Report.FeatureIsNotAvailable (Location, "static classes");
2762 public override void AddBasesForPart (DeclSpace part, ArrayList bases)
2764 if (part.Name == "System.Object")
2765 Report.Error (537, part.Location,
2766 "The class System.Object cannot have a base class or implement an interface.");
2767 base.AddBasesForPart (part, bases);
2770 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2772 if (a.Type == pa.AttributeUsage) {
2773 if (!TypeManager.IsAttributeType (BaseType) &&
2774 TypeBuilder.FullName != "System.Attribute") {
2775 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2779 if (a.Type == pa.Conditional && !TypeManager.IsAttributeType (BaseType)) {
2780 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2781 return;
2784 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2785 a.Error_MissingGuidAttribute ();
2786 return;
2789 if (a.Type == pa.Extension) {
2790 a.Error_MisusedExtensionAttribute ();
2791 return;
2794 if (AttributeTester.IsAttributeExcluded (a.Type, Location))
2795 return;
2797 base.ApplyAttributeBuilder (a, cb, pa);
2800 public override AttributeTargets AttributeTargets {
2801 get {
2802 return AttributeTargets.Class;
2806 protected override void DefineContainerMembers (MemberCoreArrayList list)
2808 if (list == null)
2809 return;
2811 if (!IsStatic) {
2812 base.DefineContainerMembers (list);
2813 return;
2816 foreach (MemberCore m in list) {
2817 if (m is Operator) {
2818 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2819 continue;
2822 if (m is Destructor) {
2823 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2824 continue;
2827 if (m is Indexer) {
2828 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2829 continue;
2832 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is Enum || m is Delegate)
2833 continue;
2835 if (m is Constructor) {
2836 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2837 continue;
2840 Method method = m as Method;
2841 if (method != null && method.Parameters.HasExtensionMethodType) {
2842 Report.Error (1105, m.Location, "`{0}': Extension methods must be declared static", m.GetSignatureForError ());
2843 continue;
2846 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2849 base.DefineContainerMembers (list);
2852 public override bool Define ()
2854 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2855 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2858 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2859 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2862 return base.Define ();
2865 protected override bool DoDefineMembers ()
2867 if (InstanceConstructors == null && !IsStatic)
2868 DefineDefaultConstructor (false);
2870 return base.DoDefineMembers ();
2873 public override void Emit ()
2875 base.Emit ();
2877 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2878 PredefinedAttributes.Get.Extension.EmitAttribute (TypeBuilder);
2881 protected override TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
2883 TypeExpr[] ifaces = base.ResolveBaseTypes (out base_class);
2885 if (base_class == null) {
2886 if (RootContext.StdLib)
2887 base_class = TypeManager.system_object_expr;
2888 else if (Name != "System.Object")
2889 base_class = TypeManager.system_object_expr;
2890 } else {
2891 if (Kind == Kind.Class && TypeManager.IsGenericParameter (base_class.Type)){
2892 Report.Error (
2893 689, base_class.Location,
2894 "Cannot derive from `{0}' because it is a type parameter",
2895 base_class.GetSignatureForError ());
2896 return ifaces;
2899 if (IsGeneric && TypeManager.IsAttributeType (base_class.Type)) {
2900 Report.Error (698, base_class.Location,
2901 "A generic type cannot derive from `{0}' because it is an attribute class",
2902 base_class.GetSignatureForError ());
2905 if (base_class.IsSealed){
2906 Report.SymbolRelatedToPreviousError (base_class.Type);
2907 if (base_class.Type.IsAbstract) {
2908 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2909 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
2910 } else {
2911 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2912 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
2914 return ifaces;
2917 if (!base_class.CanInheritFrom ()){
2918 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2919 GetSignatureForError (), base_class.GetSignatureForError ());
2920 return ifaces;
2923 if (!IsAccessibleAs (base_class.Type)) {
2924 Report.SymbolRelatedToPreviousError (base_class.Type);
2925 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2926 TypeManager.CSharpName (base_class.Type), GetSignatureForError ());
2930 if (PartialContainer.IsStaticClass) {
2931 if (base_class.Type != TypeManager.object_type) {
2932 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2933 GetSignatureForError (), base_class.GetSignatureForError ());
2934 return ifaces;
2937 if (ifaces != null) {
2938 foreach (TypeExpr t in ifaces)
2939 Report.SymbolRelatedToPreviousError (t.Type);
2940 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2944 return ifaces;
2947 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2948 /// Valid only for attribute classes.
2949 public bool IsExcluded ()
2951 if ((caching_flags & Flags.Excluded_Undetected) == 0)
2952 return (caching_flags & Flags.Excluded) != 0;
2954 caching_flags &= ~Flags.Excluded_Undetected;
2956 if (OptAttributes == null)
2957 return false;
2959 Attribute[] attrs = OptAttributes.SearchMulti (PredefinedAttributes.Get.Conditional);
2960 if (attrs == null)
2961 return false;
2963 foreach (Attribute a in attrs) {
2964 string condition = a.GetConditionalAttributeValue ();
2965 if (Location.CompilationUnit.IsConditionalDefined (condition))
2966 return false;
2969 caching_flags |= Flags.Excluded;
2970 return true;
2974 // FIXME: How do we deal with the user specifying a different
2975 // layout?
2977 protected override TypeAttributes TypeAttr {
2978 get {
2979 TypeAttributes ta = base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2980 if (IsStatic)
2981 ta |= StaticClassAttribute;
2982 return ta;
2987 public sealed class Struct : ClassOrStruct {
2989 bool is_unmanaged, has_unmanaged_check_done;
2991 // <summary>
2992 // Modifiers allowed in a struct declaration
2993 // </summary>
2994 const int AllowedModifiers =
2995 Modifiers.NEW |
2996 Modifiers.PUBLIC |
2997 Modifiers.PROTECTED |
2998 Modifiers.INTERNAL |
2999 Modifiers.UNSAFE |
3000 Modifiers.PRIVATE;
3002 public Struct (NamespaceEntry ns, DeclSpace parent, MemberName name,
3003 int mod, Attributes attrs)
3004 : base (ns, parent, name, attrs, Kind.Struct)
3006 int accmods;
3008 if (parent.Parent == null)
3009 accmods = Modifiers.INTERNAL;
3010 else
3011 accmods = Modifiers.PRIVATE;
3013 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, Location, Report);
3015 this.ModFlags |= Modifiers.SEALED;
3018 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
3020 base.ApplyAttributeBuilder (a, cb, pa);
3023 // When struct constains fixed fixed and struct layout has explicitly
3024 // set CharSet, its value has to be propagated to compiler generated
3025 // fixed field types
3027 if (a.Type == pa.StructLayout && Fields != null && a.HasField ("CharSet")) {
3028 for (int i = 0; i < Fields.Count; ++i) {
3029 FixedField ff = Fields [i] as FixedField;
3030 if (ff != null)
3031 ff.SetCharSet (TypeBuilder.Attributes);
3036 public override AttributeTargets AttributeTargets {
3037 get {
3038 return AttributeTargets.Struct;
3042 public override bool IsUnmanagedType ()
3044 if (fields == null)
3045 return true;
3047 if (requires_delayed_unmanagedtype_check)
3048 return true;
3050 if (has_unmanaged_check_done)
3051 return is_unmanaged;
3053 has_unmanaged_check_done = true;
3055 foreach (FieldBase f in fields) {
3056 if ((f.ModFlags & Modifiers.STATIC) != 0)
3057 continue;
3059 // It can happen when recursive unmanaged types are defined
3060 // struct S { S* s; }
3061 Type mt = f.MemberType;
3062 if (mt == null) {
3063 has_unmanaged_check_done = false;
3064 requires_delayed_unmanagedtype_check = true;
3065 return true;
3068 // TODO: Remove when pointer types are under mcs control
3069 while (mt.IsPointer)
3070 mt = TypeManager.GetElementType (mt);
3071 if (TypeManager.IsEqual (mt, TypeBuilder))
3072 continue;
3074 if (TypeManager.IsUnmanagedType (mt))
3075 continue;
3077 return false;
3080 is_unmanaged = true;
3081 return true;
3084 protected override TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
3086 TypeExpr[] ifaces = base.ResolveBaseTypes (out base_class);
3088 // If we are compiling our runtime,
3089 // and we are defining ValueType, then our
3090 // base is `System.Object'.
3092 if (base_class == null) {
3093 if (!RootContext.StdLib && Name == "System.ValueType")
3094 base_class = TypeManager.system_object_expr;
3095 else
3096 base_class = TypeManager.system_valuetype_expr;
3099 return ifaces;
3103 // FIXME: Allow the user to specify a different set of attributes
3104 // in some cases (Sealed for example is mandatory for a class,
3105 // but what SequentialLayout can be changed
3107 protected override TypeAttributes TypeAttr {
3108 get {
3109 const TypeAttributes DefaultTypeAttributes =
3110 TypeAttributes.SequentialLayout |
3111 TypeAttributes.Sealed;
3113 return base.TypeAttr | DefaultTypeAttributes;
3117 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
3119 if ((field.ModFlags & Modifiers.STATIC) == 0) {
3120 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
3121 field.GetSignatureForError ());
3122 return;
3124 base.RegisterFieldForInitialization (field, expression);
3129 /// <summary>
3130 /// Interfaces
3131 /// </summary>
3132 public sealed class Interface : TypeContainer, IMemberContainer {
3134 /// <summary>
3135 /// Modifiers allowed in a class declaration
3136 /// </summary>
3137 public const int AllowedModifiers =
3138 Modifiers.NEW |
3139 Modifiers.PUBLIC |
3140 Modifiers.PROTECTED |
3141 Modifiers.INTERNAL |
3142 Modifiers.UNSAFE |
3143 Modifiers.PRIVATE;
3145 public Interface (NamespaceEntry ns, DeclSpace parent, MemberName name, int mod,
3146 Attributes attrs)
3147 : base (ns, parent, name, attrs, Kind.Interface)
3149 int accmods;
3151 if (parent.Parent == null)
3152 accmods = Modifiers.INTERNAL;
3153 else
3154 accmods = Modifiers.PRIVATE;
3156 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, name.Location, Report);
3159 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
3161 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3162 a.Error_MissingGuidAttribute ();
3163 return;
3166 base.ApplyAttributeBuilder (a, cb, pa);
3170 public override AttributeTargets AttributeTargets {
3171 get {
3172 return AttributeTargets.Interface;
3176 protected override TypeAttributes TypeAttr {
3177 get {
3178 const TypeAttributes DefaultTypeAttributes =
3179 TypeAttributes.AutoLayout |
3180 TypeAttributes.Abstract |
3181 TypeAttributes.Interface;
3183 return base.TypeAttr | DefaultTypeAttributes;
3187 protected override bool VerifyClsCompliance ()
3189 if (!base.VerifyClsCompliance ())
3190 return false;
3192 if (ifaces != null) {
3193 foreach (Type t in ifaces) {
3194 if (AttributeTester.IsClsCompliant (t))
3195 continue;
3197 Report.SymbolRelatedToPreviousError (t);
3198 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3199 GetSignatureForError (), TypeManager.CSharpName (t));
3203 return true;
3207 // It is used as a base class for all property based members
3208 // This includes properties, indexers, and events
3209 public abstract class PropertyBasedMember : InterfaceMemberBase
3211 public PropertyBasedMember (DeclSpace parent, GenericMethod generic,
3212 FullNamedExpression type, int mod, int allowed_mod,
3213 MemberName name, Attributes attrs)
3214 : base (parent, generic, type, mod, allowed_mod, name, attrs)
3218 protected override bool VerifyClsCompliance ()
3220 if (!base.VerifyClsCompliance ())
3221 return false;
3223 if (!AttributeTester.IsClsCompliant (MemberType)) {
3224 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
3225 GetSignatureForError ());
3227 return true;
3233 public abstract class MethodCore : InterfaceMemberBase
3235 public readonly ParametersCompiled Parameters;
3236 protected ToplevelBlock block;
3238 public MethodCore (DeclSpace parent, GenericMethod generic,
3239 FullNamedExpression type, int mod, int allowed_mod,
3240 MemberName name, Attributes attrs, ParametersCompiled parameters)
3241 : base (parent, generic, type, mod, allowed_mod, name, attrs)
3243 Parameters = parameters;
3247 // Returns the System.Type array for the parameters of this method
3249 public Type [] ParameterTypes {
3250 get {
3251 return Parameters.Types;
3255 public ParametersCompiled ParameterInfo {
3256 get {
3257 return Parameters;
3261 public ToplevelBlock Block {
3262 get {
3263 return block;
3266 set {
3267 block = value;
3271 public CallingConventions CallingConventions {
3272 get {
3273 CallingConventions cc = Parameters.CallingConvention;
3274 if (!IsInterface)
3275 if ((ModFlags & Modifiers.STATIC) == 0)
3276 cc |= CallingConventions.HasThis;
3278 // FIXME: How is `ExplicitThis' used in C#?
3280 return cc;
3284 protected override bool CheckBase ()
3286 // Check whether arguments were correct.
3287 if (!DefineParameters (Parameters))
3288 return false;
3290 return base.CheckBase ();
3294 // Returns a string that represents the signature for this
3295 // member which should be used in XML documentation.
3297 public override string GetDocCommentName (DeclSpace ds)
3299 return DocUtil.GetMethodDocCommentName (this, Parameters, ds);
3303 // Raised (and passed an XmlElement that contains the comment)
3304 // when GenerateDocComment is writing documentation expectedly.
3306 // FIXME: with a few effort, it could be done with XmlReader,
3307 // that means removal of DOM use.
3309 internal override void OnGenerateDocComment (XmlElement el)
3311 DocUtil.OnMethodGenerateDocComment (this, el, Report);
3315 // Represents header string for documentation comment.
3317 public override string DocCommentHeader
3319 get { return "M:"; }
3322 public override bool EnableOverloadChecks (MemberCore overload)
3324 if (overload is MethodCore || overload is AbstractPropertyEventMethod) {
3325 caching_flags |= Flags.MethodOverloadsExist;
3326 return true;
3329 return base.EnableOverloadChecks (overload);
3332 protected override bool VerifyClsCompliance ()
3334 if (!base.VerifyClsCompliance ())
3335 return false;
3337 if (Parameters.HasArglist) {
3338 Report.Warning (3000, 1, Location, "Methods with variable arguments are not CLS-compliant");
3341 if (!AttributeTester.IsClsCompliant (MemberType)) {
3342 Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant",
3343 GetSignatureForError ());
3346 Parameters.VerifyClsCompliance (this);
3347 return true;
3352 public abstract class InterfaceMemberBase : MemberBase {
3354 // Whether this is an interface member.
3356 public bool IsInterface;
3359 // If true, this is an explicit interface implementation
3361 public bool IsExplicitImpl;
3363 protected bool is_external_implementation;
3366 // The interface type we are explicitly implementing
3368 public Type InterfaceType;
3371 // The method we're overriding if this is an override method.
3373 protected MethodInfo base_method;
3375 readonly int explicit_mod_flags;
3376 public MethodAttributes flags;
3378 public InterfaceMemberBase (DeclSpace parent, GenericMethod generic,
3379 FullNamedExpression type, int mod, int allowed_mod,
3380 MemberName name, Attributes attrs)
3381 : base (parent, generic, type, mod, allowed_mod, Modifiers.PRIVATE,
3382 name, attrs)
3384 IsInterface = parent.PartialContainer.Kind == Kind.Interface;
3385 IsExplicitImpl = (MemberName.Left != null);
3386 explicit_mod_flags = mod;
3389 protected override bool CheckBase ()
3391 if (!base.CheckBase ())
3392 return false;
3394 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3395 CheckForDuplications ();
3397 if (IsExplicitImpl)
3398 return true;
3400 // Is null for System.Object while compiling corlib and base interfaces
3401 if (Parent.PartialContainer.BaseCache == null) {
3402 if ((ModFlags & Modifiers.NEW) != 0) {
3403 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3405 return true;
3408 Type base_ret_type = null;
3409 base_method = FindOutBaseMethod (ref base_ret_type);
3411 // method is override
3412 if (base_method != null) {
3413 if (!CheckMethodAgainstBase (base_ret_type))
3414 return false;
3416 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3417 ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (base_method);
3418 if (oa != null) {
3419 if (OptAttributes == null || !OptAttributes.Contains (PredefinedAttributes.Get.Obsolete)) {
3420 Report.SymbolRelatedToPreviousError (base_method);
3421 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3422 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3424 } else {
3425 if (OptAttributes != null && OptAttributes.Contains (PredefinedAttributes.Get.Obsolete)) {
3426 Report.SymbolRelatedToPreviousError (base_method);
3427 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3428 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3432 return true;
3435 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Name, !((this is Event) || (this is Property)));
3436 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3437 if (conflict_symbol != null) {
3438 Report.SymbolRelatedToPreviousError (conflict_symbol);
3439 if (this is Event)
3440 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3441 else if (this is PropertyBase)
3442 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3443 else
3444 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3445 } else {
3446 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3447 GetSignatureForError (), SimpleName.GetMemberType (this));
3449 return false;
3452 if (conflict_symbol == null) {
3453 if ((ModFlags & Modifiers.NEW) != 0) {
3454 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3456 return true;
3459 if ((ModFlags & Modifiers.NEW) == 0) {
3460 if (this is MethodOrOperator && conflict_symbol.MemberType == MemberTypes.Method)
3461 return true;
3463 Report.SymbolRelatedToPreviousError (conflict_symbol);
3464 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3465 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3468 return true;
3471 protected virtual bool CheckForDuplications ()
3473 return Parent.MemberCache.CheckExistingMembersOverloads (
3474 this, GetFullName (MemberName), ParametersCompiled.EmptyReadOnlyParameters, Report);
3478 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3479 // that have been defined.
3481 // `name' is the user visible name for reporting errors (this is used to
3482 // provide the right name regarding method names and properties)
3484 bool CheckMethodAgainstBase (Type base_method_type)
3486 bool ok = true;
3488 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3489 if (!(base_method.IsAbstract || base_method.IsVirtual)){
3490 Report.SymbolRelatedToPreviousError (base_method);
3491 Report.Error (506, Location,
3492 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3493 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3494 ok = false;
3497 // Now we check that the overriden method is not final
3499 if (base_method.IsFinal) {
3500 Report.SymbolRelatedToPreviousError (base_method);
3501 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3502 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3503 ok = false;
3506 // Check that the permissions are not being changed
3508 MethodAttributes thisp = flags & MethodAttributes.MemberAccessMask;
3509 MethodAttributes base_classp = base_method.Attributes & MethodAttributes.MemberAccessMask;
3511 if (!CheckAccessModifiers (thisp, base_classp, base_method)) {
3512 Error_CannotChangeAccessModifiers (Location, base_method, base_classp, null);
3513 ok = false;
3516 if (!TypeManager.IsEqual (MemberType, TypeManager.TypeToCoreType (base_method_type))) {
3517 Report.SymbolRelatedToPreviousError (base_method);
3518 if (this is PropertyBasedMember) {
3519 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3520 GetSignatureForError (), TypeManager.CSharpName (base_method_type), TypeManager.CSharpSignature (base_method));
3522 else {
3523 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3524 GetSignatureForError (), TypeManager.CSharpName (base_method_type), TypeManager.CSharpSignature (base_method));
3526 ok = false;
3530 if ((ModFlags & Modifiers.NEW) == 0) {
3531 if ((ModFlags & Modifiers.OVERRIDE) == 0) {
3532 ModFlags |= Modifiers.NEW;
3533 Report.SymbolRelatedToPreviousError (base_method);
3534 if (!IsInterface && (base_method.IsVirtual || base_method.IsAbstract)) {
3535 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",
3536 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3537 if (base_method.IsAbstract){
3538 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3539 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3540 ok = false;
3542 } else {
3543 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3544 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3547 } else {
3548 if (base_method.IsAbstract && !IsInterface) {
3549 Report.SymbolRelatedToPreviousError (base_method);
3550 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3551 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3552 return ok = false;
3556 return ok;
3559 protected bool CheckAccessModifiers (MethodAttributes thisp, MethodAttributes base_classp, MethodInfo base_method)
3561 if ((base_classp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3563 // when overriding protected internal, the method can be declared
3564 // protected internal only within the same assembly or assembly
3565 // which has InternalsVisibleTo
3567 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3568 return TypeManager.IsThisOrFriendAssembly (Parent.Module.Assembly, base_method.DeclaringType.Assembly);
3569 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3571 // if it's not "protected internal", it must be "protected"
3574 return false;
3575 } else if (Parent.TypeBuilder.Assembly == base_method.DeclaringType.Assembly) {
3577 // protected within the same assembly - an error
3579 return false;
3580 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3581 (base_classp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3583 // protected ok, but other attributes differ - report an error
3585 return false;
3587 return true;
3588 } else {
3589 return (thisp == base_classp);
3593 public override bool Define ()
3595 if (IsInterface) {
3596 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3597 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3599 flags = MethodAttributes.Public |
3600 MethodAttributes.Abstract |
3601 MethodAttributes.HideBySig |
3602 MethodAttributes.NewSlot |
3603 MethodAttributes.Virtual;
3604 } else {
3605 Parent.PartialContainer.MethodModifiersValid (this);
3607 flags = Modifiers.MethodAttr (ModFlags);
3610 if (IsExplicitImpl) {
3611 TypeExpr iface_texpr = MemberName.Left.GetTypeExpression ().ResolveAsTypeTerminal (this, false);
3612 if (iface_texpr == null)
3613 return false;
3615 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3616 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3617 GetSignatureForError ());
3620 InterfaceType = iface_texpr.Type;
3622 if (!InterfaceType.IsInterface) {
3623 Report.SymbolRelatedToPreviousError (InterfaceType);
3624 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3625 TypeManager.CSharpName (InterfaceType));
3626 } else {
3627 Parent.PartialContainer.VerifyImplements (this);
3630 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location, Report);
3633 return base.Define ();
3636 protected bool DefineParameters (ParametersCompiled parameters)
3638 if (!parameters.Resolve (this))
3639 return false;
3641 bool error = false;
3642 for (int i = 0; i < parameters.Count; ++i) {
3643 Parameter p = parameters [i];
3645 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3646 p.Warning_UselessOptionalParameter (Report);
3648 if (p.CheckAccessibility (this))
3649 continue;
3651 Type t = parameters.Types [i];
3652 Report.SymbolRelatedToPreviousError (t);
3653 if (this is Indexer)
3654 Report.Error (55, Location,
3655 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3656 TypeManager.CSharpName (t), GetSignatureForError ());
3657 else if (this is Operator)
3658 Report.Error (57, Location,
3659 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3660 TypeManager.CSharpName (t), GetSignatureForError ());
3661 else
3662 Report.Error (51, Location,
3663 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3664 TypeManager.CSharpName (t), GetSignatureForError ());
3665 error = true;
3667 return !error;
3670 public override void Emit()
3672 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3673 // We are more strict than csc and report this as an error because SRE does not allow emit that
3674 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation) {
3675 if (this is Constructor) {
3676 Report.Error (824, Location,
3677 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3678 } else {
3679 Report.Error (626, Location,
3680 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3681 GetSignatureForError ());
3685 base.Emit ();
3688 public override bool EnableOverloadChecks (MemberCore overload)
3691 // Two members can differ in their explicit interface
3692 // type parameter only
3694 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3695 if (imb != null && imb.IsExplicitImpl) {
3696 if (IsExplicitImpl) {
3697 caching_flags |= Flags.MethodOverloadsExist;
3699 return true;
3702 return IsExplicitImpl;
3705 protected void Error_CannotChangeAccessModifiers (Location loc, MemberInfo base_method, MethodAttributes ma, string suffix)
3707 Report.SymbolRelatedToPreviousError (base_method);
3708 string base_name = TypeManager.GetFullNameSignature (base_method);
3709 string this_name = GetSignatureForError ();
3710 if (suffix != null) {
3711 base_name += suffix;
3712 this_name += suffix;
3715 Report.Error (507, loc, "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3716 this_name, Modifiers.GetDescription (ma), base_name);
3719 protected static string Error722 {
3720 get {
3721 return "`{0}': static types cannot be used as return types";
3725 /// <summary>
3726 /// Gets base method and its return type
3727 /// </summary>
3728 protected abstract MethodInfo FindOutBaseMethod (ref Type base_ret_type);
3731 // The "short" name of this property / indexer / event. This is the
3732 // name without the explicit interface.
3734 public string ShortName
3736 get { return MemberName.Name; }
3737 set { SetMemberName (new MemberName (MemberName.Left, value, Location)); }
3741 // Returns full metadata method name
3743 public string GetFullName (MemberName name)
3745 if (!IsExplicitImpl)
3746 return name.Name;
3749 // When dealing with explicit members a full interface type
3750 // name is added to member name to avoid possible name conflicts
3752 // We use CSharpName which gets us full name with benefit of
3753 // replacing predefined names which saves some space and name
3754 // is still unique
3756 return TypeManager.CSharpName (InterfaceType) + "." + name.Name;
3759 protected override bool VerifyClsCompliance ()
3761 if (!base.VerifyClsCompliance ()) {
3762 if (IsInterface && HasClsCompliantAttribute && Parent.IsClsComplianceRequired ()) {
3763 Report.Warning (3010, 1, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
3766 if ((ModFlags & Modifiers.ABSTRACT) != 0 && Parent.TypeBuilder.IsClass && IsExposedFromAssembly () && Parent.IsClsComplianceRequired ()) {
3767 Report.Warning (3011, 1, Location, "`{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
3769 return false;
3772 if (GenericMethod != null)
3773 GenericMethod.VerifyClsCompliance ();
3775 return true;
3778 public override bool IsUsed
3780 get { return IsExplicitImpl || base.IsUsed; }
3785 public abstract class MethodOrOperator : MethodCore, IMethodData
3787 public MethodBuilder MethodBuilder;
3788 ReturnParameter return_attributes;
3789 ListDictionary declarative_security;
3790 protected MethodData MethodData;
3792 static string[] attribute_targets = new string [] { "method", "return" };
3794 protected MethodOrOperator (DeclSpace parent, GenericMethod generic, FullNamedExpression type, int mod,
3795 int allowed_mod, MemberName name,
3796 Attributes attrs, ParametersCompiled parameters)
3797 : base (parent, generic, type, mod, allowed_mod, name,
3798 attrs, parameters)
3802 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
3804 if (a.Target == AttributeTargets.ReturnValue) {
3805 if (return_attributes == null)
3806 return_attributes = new ReturnParameter (this, MethodBuilder, Location);
3808 return_attributes.ApplyAttributeBuilder (a, cb, pa);
3809 return;
3812 if (a.IsInternalMethodImplAttribute) {
3813 is_external_implementation = true;
3816 if (a.Type == pa.DllImport) {
3817 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3818 if ((ModFlags & extern_static) != extern_static) {
3819 Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
3821 is_external_implementation = true;
3824 if (a.IsValidSecurityAttribute ()) {
3825 if (declarative_security == null)
3826 declarative_security = new ListDictionary ();
3827 a.ExtractSecurityPermissionSet (declarative_security);
3828 return;
3831 if (MethodBuilder != null)
3832 MethodBuilder.SetCustomAttribute (cb);
3835 public override AttributeTargets AttributeTargets {
3836 get {
3837 return AttributeTargets.Method;
3841 protected override bool CheckForDuplications ()
3843 string name = GetFullName (MemberName);
3844 if (MemberName.IsGeneric)
3845 name = MemberName.MakeName (name, MemberName.TypeArguments);
3847 return Parent.MemberCache.CheckExistingMembersOverloads (this, name, Parameters, Report);
3850 public virtual EmitContext CreateEmitContext (ILGenerator ig)
3852 return new EmitContext (
3853 this, ig, MemberType);
3856 protected override bool ResolveMemberType ()
3858 if (GenericMethod != null) {
3859 MethodBuilder = Parent.TypeBuilder.DefineMethod (GetFullName (MemberName), flags);
3860 if (!GenericMethod.Define (this))
3861 return false;
3864 return base.ResolveMemberType ();
3867 public override bool Define ()
3869 if (!base.Define ())
3870 return false;
3872 if (!CheckBase ())
3873 return false;
3875 if (block != null && block.IsIterator && !(Parent is IteratorStorey)) {
3877 // Current method is turned into automatically generated
3878 // wrapper which creates an instance of iterator
3880 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
3881 ModFlags |= Modifiers.DEBUGGER_HIDDEN;
3884 if (IsPartialDefinition) {
3885 caching_flags &= ~Flags.Excluded_Undetected;
3886 caching_flags |= Flags.Excluded;
3887 // Add to member cache only when a partial method implementation is not there
3888 if ((caching_flags & Flags.MethodOverloadsExist) == 0) {
3889 MethodBase mb = new PartialMethodDefinitionInfo (this);
3890 Parent.MemberCache.AddMember (mb, this);
3891 TypeManager.AddMethod (mb, this);
3894 return true;
3897 MethodData = new MethodData (
3898 this, ModFlags, flags, this, MethodBuilder, GenericMethod, base_method);
3900 if (!MethodData.Define (Parent.PartialContainer, GetFullName (MemberName), Report))
3901 return false;
3903 MethodBuilder = MethodData.MethodBuilder;
3905 if (TypeManager.IsGenericMethod (MethodBuilder))
3906 Parent.MemberCache.AddGenericMember (MethodBuilder, this);
3908 Parent.MemberCache.AddMember (MethodBuilder, this);
3910 return true;
3913 protected override void DoMemberTypeIndependentChecks ()
3915 base.DoMemberTypeIndependentChecks ();
3917 CheckAbstractAndExtern (block != null);
3919 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3920 for (int i = 0; i < Parameters.Count; ++i) {
3921 IParameterData p = Parameters.FixedParameters [i];
3922 if (p.ModFlags == Parameter.Modifier.OUT) {
3923 Report.Error (752, Location, "`{0}': A partial method parameters cannot use `out' modifier",
3924 GetSignatureForError ());
3927 if (p.HasDefaultValue && IsPartialImplementation)
3928 ((Parameter) p).Warning_UselessOptionalParameter (Report);
3933 protected override void DoMemberTypeDependentChecks ()
3935 base.DoMemberTypeDependentChecks ();
3937 if (!TypeManager.IsGenericParameter (MemberType)) {
3938 if (MemberType.IsAbstract && MemberType.IsSealed) {
3939 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
3944 public override void Emit ()
3946 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
3947 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (MethodBuilder);
3948 if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
3949 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (MethodBuilder);
3951 if (TypeManager.IsDynamicType (ReturnType)) {
3952 return_attributes = new ReturnParameter (this, MethodBuilder, Location);
3953 PredefinedAttributes.Get.Dynamic.EmitAttribute (return_attributes.Builder);
3956 if (OptAttributes != null)
3957 OptAttributes.Emit ();
3959 if (declarative_security != null) {
3960 foreach (DictionaryEntry de in declarative_security) {
3961 MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
3965 if (MethodData != null)
3966 MethodData.Emit (Parent);
3968 base.Emit ();
3970 Block = null;
3971 MethodData = null;
3974 protected void Error_ConditionalAttributeIsNotValid ()
3976 Report.Error (577, Location,
3977 "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
3978 GetSignatureForError ());
3981 public bool IsPartialDefinition {
3982 get {
3983 return (ModFlags & Modifiers.PARTIAL) != 0 && Block == null;
3987 public bool IsPartialImplementation {
3988 get {
3989 return (ModFlags & Modifiers.PARTIAL) != 0 && Block != null;
3993 public override string[] ValidAttributeTargets {
3994 get {
3995 return attribute_targets;
3999 #region IMethodData Members
4001 public Type ReturnType {
4002 get {
4003 return MemberType;
4007 public MemberName MethodName {
4008 get {
4009 return MemberName;
4013 /// <summary>
4014 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
4015 /// </summary>
4016 public bool IsExcluded () {
4017 if ((caching_flags & Flags.Excluded_Undetected) == 0)
4018 return (caching_flags & Flags.Excluded) != 0;
4020 caching_flags &= ~Flags.Excluded_Undetected;
4022 if (base_method == null) {
4023 if (OptAttributes == null)
4024 return false;
4026 Attribute[] attrs = OptAttributes.SearchMulti (PredefinedAttributes.Get.Conditional);
4028 if (attrs == null)
4029 return false;
4031 foreach (Attribute a in attrs) {
4032 string condition = a.GetConditionalAttributeValue ();
4033 if (condition == null)
4034 return false;
4036 if (Location.CompilationUnit.IsConditionalDefined (condition))
4037 return false;
4040 caching_flags |= Flags.Excluded;
4041 return true;
4044 IMethodData md = TypeManager.GetMethod (TypeManager.DropGenericMethodArguments (base_method));
4045 if (md == null) {
4046 if (AttributeTester.IsConditionalMethodExcluded (base_method, Location)) {
4047 caching_flags |= Flags.Excluded;
4048 return true;
4050 return false;
4053 if (md.IsExcluded ()) {
4054 caching_flags |= Flags.Excluded;
4055 return true;
4057 return false;
4060 GenericMethod IMethodData.GenericMethod {
4061 get {
4062 return GenericMethod;
4066 public virtual void EmitExtraSymbolInfo (SourceMethod source)
4069 #endregion
4073 public class SourceMethod : IMethodDef
4075 MethodBase method;
4076 SourceMethodBuilder builder;
4078 protected SourceMethod (DeclSpace parent, MethodBase method, ICompileUnit file)
4080 this.method = method;
4082 builder = SymbolWriter.OpenMethod (file, parent.NamespaceEntry.SymbolFileID, this);
4085 public string Name {
4086 get { return method.Name; }
4089 public int Token {
4090 get {
4091 if (method is MethodBuilder)
4092 return ((MethodBuilder) method).GetToken ().Token;
4093 else if (method is ConstructorBuilder)
4094 return ((ConstructorBuilder) method).GetToken ().Token;
4095 else
4096 throw new NotSupportedException ();
4100 public void CloseMethod ()
4102 SymbolWriter.CloseMethod ();
4105 public void SetRealMethodName (string name)
4107 if (builder != null)
4108 builder.SetRealMethodName (name);
4111 public static SourceMethod Create (DeclSpace parent, MethodBase method, Block block)
4113 if (!SymbolWriter.HasSymbolWriter)
4114 return null;
4115 if (block == null)
4116 return null;
4118 Location start_loc = block.StartLocation;
4119 if (start_loc.IsNull)
4120 return null;
4122 ICompileUnit compile_unit = start_loc.CompilationUnit;
4123 if (compile_unit == null)
4124 return null;
4126 return new SourceMethod (parent, method, compile_unit);
4130 public class Method : MethodOrOperator {
4132 /// <summary>
4133 /// Modifiers allowed in a class declaration
4134 /// </summary>
4135 const int AllowedModifiers =
4136 Modifiers.NEW |
4137 Modifiers.PUBLIC |
4138 Modifiers.PROTECTED |
4139 Modifiers.INTERNAL |
4140 Modifiers.PRIVATE |
4141 Modifiers.STATIC |
4142 Modifiers.VIRTUAL |
4143 Modifiers.SEALED |
4144 Modifiers.OVERRIDE |
4145 Modifiers.ABSTRACT |
4146 Modifiers.UNSAFE |
4147 Modifiers.EXTERN;
4149 const int AllowedInterfaceModifiers =
4150 Modifiers.NEW | Modifiers.UNSAFE;
4152 Method partialMethodImplementation;
4154 public Method (DeclSpace parent, GenericMethod generic,
4155 FullNamedExpression return_type, int mod,
4156 MemberName name, ParametersCompiled parameters, Attributes attrs)
4157 : base (parent, generic, return_type, mod,
4158 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
4159 name, attrs, parameters)
4163 protected Method (DeclSpace parent, FullNamedExpression return_type, int mod, int amod,
4164 MemberName name, ParametersCompiled parameters, Attributes attrs)
4165 : base (parent, null, return_type, mod, amod, name, attrs, parameters)
4169 public override string GetSignatureForError()
4171 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
4174 void Error_DuplicateEntryPoint (Method b)
4176 Report.Error (17, b.Location,
4177 "Program `{0}' has more than one entry point defined: `{1}'",
4178 CodeGen.FileName, b.GetSignatureForError ());
4181 bool IsEntryPoint ()
4183 if (ReturnType != TypeManager.void_type &&
4184 ReturnType != TypeManager.int32_type)
4185 return false;
4187 if (Parameters.Count == 0)
4188 return true;
4190 if (Parameters.Count > 1)
4191 return false;
4193 Type t = Parameters.Types [0];
4194 return t.IsArray && t.GetArrayRank () == 1 &&
4195 TypeManager.GetElementType (t) == TypeManager.string_type &&
4196 (Parameters[0].ModFlags & ~Parameter.Modifier.PARAMS) == Parameter.Modifier.NONE;
4199 public override FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
4201 TypeParameter[] tp = CurrentTypeParameters;
4202 if (tp != null) {
4203 TypeParameter t = TypeParameter.FindTypeParameter (tp, name);
4204 if (t != null)
4205 return new TypeParameterExpr (t, loc);
4208 return base.LookupNamespaceOrType (name, loc, ignore_cs0104);
4211 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
4213 if (a.Type == pa.Conditional) {
4214 if (IsExplicitImpl) {
4215 Error_ConditionalAttributeIsNotValid ();
4216 return;
4219 if (ReturnType != TypeManager.void_type) {
4220 Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ());
4221 return;
4224 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
4225 Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ());
4226 return;
4229 if (IsInterface) {
4230 Report.Error (582, Location, "Conditional not valid on interface members");
4231 return;
4234 if (MethodData.implementing != null) {
4235 Report.SymbolRelatedToPreviousError (MethodData.implementing.DeclaringType);
4236 Report.Error (629, Location, "Conditional member `{0}' cannot implement interface member `{1}'",
4237 GetSignatureForError (), TypeManager.CSharpSignature (MethodData.implementing));
4238 return;
4241 for (int i = 0; i < Parameters.Count; ++i) {
4242 if (Parameters.FixedParameters [i].ModFlags == Parameter.Modifier.OUT) {
4243 Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
4244 return;
4249 if (a.Type == pa.Extension) {
4250 a.Error_MisusedExtensionAttribute ();
4251 return;
4254 base.ApplyAttributeBuilder (a, cb, pa);
4257 protected override bool CheckForDuplications ()
4259 if (!base.CheckForDuplications ())
4260 return false;
4262 ArrayList ar = Parent.PartialContainer.Properties;
4263 if (ar != null) {
4264 for (int i = 0; i < ar.Count; ++i) {
4265 PropertyBase pb = (PropertyBase) ar [i];
4266 if (pb.AreAccessorsDuplicateImplementation (this))
4267 return false;
4271 ar = Parent.PartialContainer.Indexers;
4272 if (ar != null) {
4273 for (int i = 0; i < ar.Count; ++i) {
4274 PropertyBase pb = (PropertyBase) ar [i];
4275 if (pb.AreAccessorsDuplicateImplementation (this))
4276 return false;
4280 return true;
4283 protected override bool CheckBase ()
4285 if (!base.CheckBase ())
4286 return false;
4288 if (base_method != null && (ModFlags & Modifiers.OVERRIDE) != 0 && Name == Destructor.MetadataName) {
4289 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
4290 TypeManager.CSharpSignature (base_method));
4293 return true;
4296 public override TypeParameter[] CurrentTypeParameters {
4297 get {
4298 if (GenericMethod != null)
4299 return GenericMethod.CurrentTypeParameters;
4301 return null;
4306 // Creates the type
4308 public override bool Define ()
4310 if (type_name == TypeManager.system_void_expr && Parameters.IsEmpty && Name == Destructor.MetadataName) {
4311 Report.Warning (465, 1, Location, "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
4314 if (!base.Define ())
4315 return false;
4317 if (partialMethodImplementation != null && IsPartialDefinition)
4318 MethodBuilder = partialMethodImplementation.MethodBuilder;
4320 if (RootContext.StdLib && TypeManager.IsSpecialType (ReturnType)) {
4321 Error1599 (Location, ReturnType, Report);
4322 return false;
4325 if (base_method != null && (ModFlags & Modifiers.NEW) == 0) {
4326 if (Parameters.Count == 1 && ParameterTypes [0] == TypeManager.object_type && Name == "Equals")
4327 Parent.PartialContainer.Mark_HasEquals ();
4328 else if (Parameters.IsEmpty && Name == "GetHashCode")
4329 Parent.PartialContainer.Mark_HasGetHashCode ();
4332 if ((ModFlags & Modifiers.STATIC) == 0)
4333 return true;
4335 if (Parameters.HasExtensionMethodType) {
4336 if (Parent.PartialContainer.IsStaticClass && !Parent.IsGeneric) {
4337 if (!Parent.IsTopLevel)
4338 Report.Error (1109, Location, "`{0}': Extension methods cannot be defined in a nested class",
4339 GetSignatureForError ());
4341 PredefinedAttribute pa = PredefinedAttributes.Get.Extension;
4342 if (!pa.IsDefined) {
4343 Report.Error (1110, Location,
4344 "`{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",
4345 GetSignatureForError ());
4348 ModFlags |= Modifiers.METHOD_EXTENSION;
4349 Parent.PartialContainer.ModFlags |= Modifiers.METHOD_EXTENSION;
4350 CodeGen.Assembly.HasExtensionMethods = true;
4351 } else {
4352 Report.Error (1106, Location, "`{0}': Extension methods must be defined in a non-generic static class",
4353 GetSignatureForError ());
4358 // This is used to track the Entry Point,
4360 if (RootContext.NeedsEntryPoint &&
4361 Name == "Main" &&
4362 (RootContext.MainClass == null ||
4363 RootContext.MainClass == Parent.TypeBuilder.FullName)){
4364 if (IsEntryPoint ()) {
4366 if (RootContext.EntryPoint == null) {
4367 if (Parent.IsGeneric || MemberName.IsGeneric) {
4368 Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type",
4369 GetSignatureForError ());
4370 } else {
4371 SetMemberIsUsed ();
4372 RootContext.EntryPoint = this;
4374 } else {
4375 Error_DuplicateEntryPoint (RootContext.EntryPoint);
4376 Error_DuplicateEntryPoint (this);
4378 } else {
4379 Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point",
4380 GetSignatureForError ());
4384 return true;
4388 // Emits the code
4390 public override void Emit ()
4392 try {
4393 Report.Debug (64, "METHOD EMIT", this, MethodBuilder, Location, Block, MethodData);
4394 if (IsPartialDefinition) {
4396 // Use partial method implementation builder for partial method declaration attributes
4398 if (partialMethodImplementation != null) {
4399 MethodBuilder = partialMethodImplementation.MethodBuilder;
4400 return;
4402 } else if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.PartialDefinitionExists) == 0) {
4403 Report.Error (759, Location, "A partial method `{0}' implementation is missing a partial method declaration",
4404 GetSignatureForError ());
4407 base.Emit ();
4409 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
4410 PredefinedAttributes.Get.Extension.EmitAttribute (MethodBuilder);
4411 } catch {
4412 Console.WriteLine ("Internal compiler error at {0}: exception caught while emitting {1}",
4413 Location, MethodBuilder);
4414 throw;
4418 public override bool EnableOverloadChecks (MemberCore overload)
4420 // TODO: It can be deleted when members will be defined in correct order
4421 if (overload is Operator)
4422 return overload.EnableOverloadChecks (this);
4424 if (overload is Indexer)
4425 return false;
4427 return base.EnableOverloadChecks (overload);
4430 public static void Error1599 (Location loc, Type t, Report Report)
4432 Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t));
4435 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
4437 MethodInfo mi = (MethodInfo) Parent.PartialContainer.BaseCache.FindMemberToOverride (
4438 Parent.TypeBuilder, Name, Parameters, GenericMethod, false);
4440 if (mi == null)
4441 return null;
4443 if (mi.IsSpecialName)
4444 return null;
4446 base_ret_type = TypeManager.TypeToCoreType (mi.ReturnType);
4447 return mi;
4450 public void SetPartialDefinition (Method methodDefinition)
4452 caching_flags |= Flags.PartialDefinitionExists;
4453 methodDefinition.partialMethodImplementation = this;
4455 // Ensure we are always using method declaration parameters
4456 for (int i = 0; i < methodDefinition.Parameters.Count; ++i ) {
4457 Parameters [i].Name = methodDefinition.Parameters [i].Name;
4458 Parameters [i].DefaultValue = methodDefinition.Parameters [i].DefaultValue;
4461 if (methodDefinition.attributes == null)
4462 return;
4464 if (attributes == null) {
4465 attributes = methodDefinition.attributes;
4466 } else {
4467 attributes.Attrs.AddRange (methodDefinition.attributes.Attrs);
4471 protected override bool VerifyClsCompliance ()
4473 if (!base.VerifyClsCompliance ())
4474 return false;
4476 if (!Parameters.IsEmpty) {
4477 ArrayList al = (ArrayList)Parent.PartialContainer.MemberCache.Members [Name];
4478 if (al.Count > 1)
4479 MemberCache.VerifyClsParameterConflict (al, this, MethodBuilder, Report);
4482 return true;
4486 public abstract class ConstructorInitializer : ExpressionStatement
4488 Arguments argument_list;
4489 MethodGroupExpr base_constructor_group;
4491 public ConstructorInitializer (Arguments argument_list, Location loc)
4493 this.argument_list = argument_list;
4494 this.loc = loc;
4497 public Arguments Arguments {
4498 get {
4499 return argument_list;
4503 public override Expression CreateExpressionTree (ResolveContext ec)
4505 throw new NotSupportedException ("ET");
4508 protected override Expression DoResolve (ResolveContext ec)
4510 eclass = ExprClass.Value;
4512 // TODO: ec.GetSignatureForError ()
4513 ConstructorBuilder caller_builder = ((Constructor) ec.MemberContext).ConstructorBuilder;
4515 if (argument_list != null) {
4516 bool dynamic;
4519 // Spec mandates that constructor initializer will not have `this' access
4521 using (ec.Set (ResolveContext.Options.BaseInitializer)) {
4522 argument_list.Resolve (ec, out dynamic);
4525 if (dynamic) {
4526 ec.Report.Error (1975, loc,
4527 "The constructor call cannot be dynamically dispatched within constructor initializer");
4529 return null;
4533 type = ec.CurrentType;
4534 if (this is ConstructorBaseInitializer) {
4535 if (ec.CurrentType.BaseType == null)
4536 return this;
4538 type = ec.CurrentType.BaseType;
4539 if (TypeManager.IsStruct (ec.CurrentType)) {
4540 ec.Report.Error (522, loc,
4541 "`{0}': Struct constructors cannot call base constructors", TypeManager.CSharpSignature (caller_builder));
4542 return this;
4544 } else {
4546 // It is legal to have "this" initializers that take no arguments
4547 // in structs, they are just no-ops.
4549 // struct D { public D (int a) : this () {}
4551 if (TypeManager.IsStruct (ec.CurrentType) && argument_list == null)
4552 return this;
4555 base_constructor_group = MemberLookupFinal (
4556 ec, null, type, ConstructorBuilder.ConstructorName, MemberTypes.Constructor,
4557 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
4558 loc) as MethodGroupExpr;
4560 if (base_constructor_group == null)
4561 return this;
4563 base_constructor_group = base_constructor_group.OverloadResolve (
4564 ec, ref argument_list, false, loc);
4566 if (base_constructor_group == null)
4567 return this;
4569 if (!ec.IsStatic)
4570 base_constructor_group.InstanceExpression = ec.GetThis (loc);
4572 ConstructorInfo base_ctor = (ConstructorInfo)base_constructor_group;
4574 if (base_ctor == caller_builder){
4575 ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself", TypeManager.CSharpSignature (caller_builder));
4578 return this;
4581 public override void Emit (EmitContext ec)
4583 // It can be null for static initializers
4584 if (base_constructor_group == null)
4585 return;
4587 ec.Mark (loc);
4589 base_constructor_group.EmitCall (ec, argument_list);
4592 public override void EmitStatement (EmitContext ec)
4594 Emit (ec);
4598 public class ConstructorBaseInitializer : ConstructorInitializer {
4599 public ConstructorBaseInitializer (Arguments argument_list, Location l) :
4600 base (argument_list, l)
4605 class GeneratedBaseInitializer: ConstructorBaseInitializer {
4606 public GeneratedBaseInitializer (Location loc):
4607 base (null, loc)
4612 public class ConstructorThisInitializer : ConstructorInitializer {
4613 public ConstructorThisInitializer (Arguments argument_list, Location l) :
4614 base (argument_list, l)
4619 public class Constructor : MethodCore, IMethodData {
4620 public ConstructorBuilder ConstructorBuilder;
4621 public ConstructorInitializer Initializer;
4622 ListDictionary declarative_security;
4623 bool has_compliant_args;
4625 // <summary>
4626 // Modifiers allowed for a constructor.
4627 // </summary>
4628 public const int AllowedModifiers =
4629 Modifiers.PUBLIC |
4630 Modifiers.PROTECTED |
4631 Modifiers.INTERNAL |
4632 Modifiers.STATIC |
4633 Modifiers.UNSAFE |
4634 Modifiers.EXTERN |
4635 Modifiers.PRIVATE;
4637 static readonly string[] attribute_targets = new string [] { "method" };
4640 // The spec claims that static is not permitted, but
4641 // my very own code has static constructors.
4643 public Constructor (DeclSpace parent, string name, int mod, Attributes attrs, ParametersCompiled args,
4644 ConstructorInitializer init, Location loc)
4645 : base (parent, null, null, mod, AllowedModifiers,
4646 new MemberName (name, loc), attrs, args)
4648 Initializer = init;
4651 public bool HasCompliantArgs {
4652 get { return has_compliant_args; }
4655 public override AttributeTargets AttributeTargets {
4656 get { return AttributeTargets.Constructor; }
4660 // Returns true if this is a default constructor
4662 public bool IsDefault ()
4664 if ((ModFlags & Modifiers.STATIC) != 0)
4665 return Parameters.IsEmpty;
4667 return Parameters.IsEmpty &&
4668 (Initializer is ConstructorBaseInitializer) &&
4669 (Initializer.Arguments == null);
4672 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
4674 if (a.IsValidSecurityAttribute ()) {
4675 if (declarative_security == null) {
4676 declarative_security = new ListDictionary ();
4678 a.ExtractSecurityPermissionSet (declarative_security);
4679 return;
4682 if (a.IsInternalMethodImplAttribute) {
4683 is_external_implementation = true;
4686 ConstructorBuilder.SetCustomAttribute (cb);
4689 protected override bool CheckBase ()
4691 if ((ModFlags & Modifiers.STATIC) != 0) {
4692 if (!Parameters.IsEmpty) {
4693 Report.Error (132, Location, "`{0}': The static constructor must be parameterless",
4694 GetSignatureForError ());
4695 return false;
4698 // the rest can be ignored
4699 return true;
4702 // Check whether arguments were correct.
4703 if (!DefineParameters (Parameters))
4704 return false;
4706 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
4707 Parent.MemberCache.CheckExistingMembersOverloads (this, ConstructorInfo.ConstructorName,
4708 Parameters, Report);
4710 if (Parent.PartialContainer.Kind == Kind.Struct) {
4711 if (Parameters.Count == 0) {
4712 Report.Error (568, Location,
4713 "Structs cannot contain explicit parameterless constructors");
4714 return false;
4718 CheckProtectedModifier ();
4720 return true;
4724 // Creates the ConstructorBuilder
4726 public override bool Define ()
4728 if (ConstructorBuilder != null)
4729 return true;
4731 MethodAttributes ca = (MethodAttributes.RTSpecialName |
4732 MethodAttributes.SpecialName);
4734 if ((ModFlags & Modifiers.STATIC) != 0) {
4735 ca |= MethodAttributes.Static | MethodAttributes.Private;
4736 } else {
4737 ca |= MethodAttributes.HideBySig;
4739 if ((ModFlags & Modifiers.PUBLIC) != 0)
4740 ca |= MethodAttributes.Public;
4741 else if ((ModFlags & Modifiers.PROTECTED) != 0){
4742 if ((ModFlags & Modifiers.INTERNAL) != 0)
4743 ca |= MethodAttributes.FamORAssem;
4744 else
4745 ca |= MethodAttributes.Family;
4746 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
4747 ca |= MethodAttributes.Assembly;
4748 else
4749 ca |= MethodAttributes.Private;
4752 if (!CheckAbstractAndExtern (block != null))
4753 return false;
4755 // Check if arguments were correct.
4756 if (!CheckBase ())
4757 return false;
4759 ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
4760 ca, CallingConventions,
4761 Parameters.GetEmitTypes ());
4763 if (Parent.PartialContainer.IsComImport) {
4764 if (!IsDefault ()) {
4765 Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
4766 Parent.GetSignatureForError ());
4768 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
4771 Parent.MemberCache.AddMember (ConstructorBuilder, this);
4772 TypeManager.AddMethod (ConstructorBuilder, this);
4774 // It's here only to report an error
4775 if (block != null && block.IsIterator) {
4776 member_type = TypeManager.void_type;
4777 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
4780 return true;
4784 // Emits the code
4786 public override void Emit ()
4788 if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
4789 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (ConstructorBuilder);
4791 if (OptAttributes != null)
4792 OptAttributes.Emit ();
4794 base.Emit ();
4797 // If we use a "this (...)" constructor initializer, then
4798 // do not emit field initializers, they are initialized in the other constructor
4800 bool emit_field_initializers = ((ModFlags & Modifiers.STATIC) != 0) ||
4801 !(Initializer is ConstructorThisInitializer);
4803 BlockContext bc = new BlockContext (this, block, TypeManager.void_type);
4804 bc.Set (ResolveContext.Options.ConstructorScope);
4806 if (emit_field_initializers)
4807 Parent.PartialContainer.ResolveFieldInitializers (bc);
4809 if (block != null) {
4810 // If this is a non-static `struct' constructor and doesn't have any
4811 // initializer, it must initialize all of the struct's fields.
4812 if ((Parent.PartialContainer.Kind == Kind.Struct) &&
4813 ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
4814 block.AddThisVariable (Parent, Location);
4816 if (block != null && (ModFlags & Modifiers.STATIC) == 0){
4817 if (Parent.PartialContainer.Kind == Kind.Class && Initializer == null)
4818 Initializer = new GeneratedBaseInitializer (Location);
4820 if (Initializer != null) {
4821 block.AddScopeStatement (new StatementExpression (Initializer));
4826 Parameters.ApplyAttributes (ConstructorBuilder);
4828 SourceMethod source = SourceMethod.Create (Parent, ConstructorBuilder, block);
4830 if (block != null) {
4831 if (block.Resolve (null, bc, Parameters, this)) {
4832 EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType);
4833 ec.With (EmitContext.Options.ConstructorScope, true);
4835 if (!ec.HasReturnLabel && bc.HasReturnLabel) {
4836 ec.ReturnLabel = bc.ReturnLabel;
4837 ec.HasReturnLabel = true;
4840 block.Emit (ec);
4844 if (source != null)
4845 source.CloseMethod ();
4847 if (declarative_security != null) {
4848 foreach (DictionaryEntry de in declarative_security) {
4849 ConstructorBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
4853 block = null;
4856 // Is never override
4857 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
4859 return null;
4862 public override string GetSignatureForError()
4864 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
4867 public override string[] ValidAttributeTargets {
4868 get {
4869 return attribute_targets;
4873 protected override bool VerifyClsCompliance ()
4875 if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
4876 return false;
4879 if (!Parameters.IsEmpty) {
4880 ArrayList al = (ArrayList)Parent.MemberCache.Members [ConstructorInfo.ConstructorName];
4881 if (al.Count > 2)
4882 MemberCache.VerifyClsParameterConflict (al, this, ConstructorBuilder, Report);
4884 if (TypeManager.IsSubclassOf (Parent.TypeBuilder, TypeManager.attribute_type)) {
4885 foreach (Type param in Parameters.Types) {
4886 if (param.IsArray) {
4887 return true;
4892 has_compliant_args = true;
4893 return true;
4896 #region IMethodData Members
4898 public MemberName MethodName {
4899 get {
4900 return MemberName;
4904 public Type ReturnType {
4905 get {
4906 return MemberType;
4910 public EmitContext CreateEmitContext (ILGenerator ig)
4912 throw new NotImplementedException ();
4915 public bool IsExcluded()
4917 return false;
4920 GenericMethod IMethodData.GenericMethod {
4921 get {
4922 return null;
4926 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
4929 #endregion
4932 /// <summary>
4933 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
4934 /// </summary>
4935 public interface IMethodData
4937 CallingConventions CallingConventions { get; }
4938 Location Location { get; }
4939 MemberName MethodName { get; }
4940 Type ReturnType { get; }
4941 GenericMethod GenericMethod { get; }
4942 ParametersCompiled ParameterInfo { get; }
4944 Attributes OptAttributes { get; }
4945 ToplevelBlock Block { get; set; }
4947 EmitContext CreateEmitContext (ILGenerator ig);
4948 ObsoleteAttribute GetObsoleteAttribute ();
4949 string GetSignatureForError ();
4950 bool IsExcluded ();
4951 bool IsClsComplianceRequired ();
4952 void SetMemberIsUsed ();
4953 void EmitExtraSymbolInfo (SourceMethod source);
4957 // Encapsulates most of the Method's state
4959 public class MethodData {
4960 static FieldInfo methodbuilder_attrs_field;
4961 public readonly IMethodData method;
4963 public readonly GenericMethod GenericMethod;
4966 // Are we implementing an interface ?
4968 public MethodInfo implementing;
4971 // Protected data.
4973 protected InterfaceMemberBase member;
4974 protected int modifiers;
4975 protected MethodAttributes flags;
4976 protected Type declaring_type;
4977 protected MethodInfo parent_method;
4979 MethodBuilder builder = null;
4980 public MethodBuilder MethodBuilder {
4981 get {
4982 return builder;
4986 public Type DeclaringType {
4987 get {
4988 return declaring_type;
4992 public MethodData (InterfaceMemberBase member,
4993 int modifiers, MethodAttributes flags, IMethodData method)
4995 this.member = member;
4996 this.modifiers = modifiers;
4997 this.flags = flags;
4999 this.method = method;
5002 public MethodData (InterfaceMemberBase member,
5003 int modifiers, MethodAttributes flags,
5004 IMethodData method, MethodBuilder builder,
5005 GenericMethod generic, MethodInfo parent_method)
5006 : this (member, modifiers, flags, method)
5008 this.builder = builder;
5009 this.GenericMethod = generic;
5010 this.parent_method = parent_method;
5013 public bool Define (DeclSpace parent, string method_full_name, Report Report)
5015 string name = method.MethodName.Basename;
5017 TypeContainer container = parent.PartialContainer;
5019 PendingImplementation pending = container.PendingImplementations;
5020 if (pending != null){
5021 implementing = pending.IsInterfaceMethod (name, member.InterfaceType, this);
5023 if (member.InterfaceType != null){
5024 if (implementing == null){
5025 if (member is PropertyBase) {
5026 Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'",
5027 method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType),
5028 member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
5030 } else {
5031 Report.Error (539, method.Location,
5032 "`{0}.{1}' in explicit interface declaration is not a member of interface",
5033 TypeManager.CSharpName (member.InterfaceType), member.ShortName);
5035 return false;
5037 if (implementing.IsSpecialName && !(method is AbstractPropertyEventMethod)) {
5038 Report.SymbolRelatedToPreviousError (implementing);
5039 Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
5040 member.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
5041 return false;
5043 } else {
5044 if (implementing != null) {
5045 AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod;
5046 if (prop_method == null) {
5047 if (TypeManager.IsSpecialMethod (implementing)) {
5048 Report.SymbolRelatedToPreviousError (implementing);
5049 Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}.{2}'",
5050 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing),
5051 implementing.Name.StartsWith ("get_") ? "get" : "set");
5053 } else if (implementing.DeclaringType.IsInterface) {
5054 if (!implementing.IsSpecialName) {
5055 Report.SymbolRelatedToPreviousError (implementing);
5056 Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
5057 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
5058 return false;
5060 PropertyBase.PropertyMethod pm = prop_method as PropertyBase.PropertyMethod;
5061 if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
5062 Report.SymbolRelatedToPreviousError (implementing);
5063 Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'",
5064 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing, true));
5065 return false;
5073 // For implicit implementations, make sure we are public, for
5074 // explicit implementations, make sure we are private.
5076 if (implementing != null){
5078 // Setting null inside this block will trigger a more
5079 // verbose error reporting for missing interface implementations
5081 // The "candidate" function has been flagged already
5082 // but it wont get cleared
5084 if (member.IsExplicitImpl){
5085 if (method.ParameterInfo.HasParams && !TypeManager.GetParameterData (implementing).HasParams) {
5086 Report.SymbolRelatedToPreviousError (implementing);
5087 Report.Error (466, method.Location, "`{0}': the explicit interface implementation cannot introduce the params modifier",
5088 method.GetSignatureForError ());
5089 return false;
5091 } else {
5092 if (implementing.DeclaringType.IsInterface) {
5094 // If this is an interface method implementation,
5095 // check for public accessibility
5097 if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
5099 implementing = null;
5101 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
5102 // We may never be private.
5103 implementing = null;
5105 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
5107 // We may be protected if we're overriding something.
5109 implementing = null;
5114 // Static is not allowed
5116 if ((modifiers & Modifiers.STATIC) != 0){
5117 implementing = null;
5122 // If implementing is still valid, set flags
5124 if (implementing != null){
5126 // When implementing interface methods, set NewSlot
5127 // unless, we are overwriting a method.
5129 if (implementing.DeclaringType.IsInterface){
5130 if ((modifiers & Modifiers.OVERRIDE) == 0)
5131 flags |= MethodAttributes.NewSlot;
5133 flags |=
5134 MethodAttributes.Virtual |
5135 MethodAttributes.HideBySig;
5137 // Set Final unless we're virtual, abstract or already overriding a method.
5138 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
5139 flags |= MethodAttributes.Final;
5142 DefineMethodBuilder (container, method_full_name, method.ParameterInfo);
5144 if (builder == null)
5145 return false;
5147 if (container.CurrentType != null)
5148 declaring_type = container.CurrentType;
5149 else
5150 declaring_type = container.TypeBuilder;
5152 if (implementing != null && member.IsExplicitImpl) {
5153 container.TypeBuilder.DefineMethodOverride (builder, implementing);
5156 TypeManager.AddMethod (builder, method);
5158 if (GenericMethod != null) {
5159 bool is_override = member.IsExplicitImpl |
5160 ((modifiers & Modifiers.OVERRIDE) != 0);
5162 if (implementing != null)
5163 parent_method = implementing;
5165 if (!GenericMethod.DefineType (GenericMethod, builder, parent_method, is_override))
5166 return false;
5169 return true;
5173 /// <summary>
5174 /// Create the MethodBuilder for the method
5175 /// </summary>
5176 void DefineMethodBuilder (TypeContainer container, string method_name, ParametersCompiled param)
5178 if (builder == null) {
5179 builder = container.TypeBuilder.DefineMethod (
5180 method_name, flags, method.CallingConventions,
5181 method.ReturnType,
5182 param.GetEmitTypes ());
5183 return;
5187 // Generic method has been already defined to resolve method parameters
5188 // correctly when they use type parameters
5190 builder.SetParameters (param.GetEmitTypes ());
5191 builder.SetReturnType (method.ReturnType);
5192 if (builder.Attributes != flags) {
5193 try {
5194 if (methodbuilder_attrs_field == null)
5195 methodbuilder_attrs_field = typeof (MethodBuilder).GetField ("attrs", BindingFlags.NonPublic | BindingFlags.Instance);
5196 methodbuilder_attrs_field.SetValue (builder, flags);
5197 } catch {
5198 container.Compiler.Report.RuntimeMissingSupport (method.Location, "Generic method MethodAttributes");
5204 // Emits the code
5206 public void Emit (DeclSpace parent)
5208 method.ParameterInfo.ApplyAttributes (MethodBuilder);
5210 if (GenericMethod != null)
5211 GenericMethod.EmitAttributes ();
5214 // clear the pending implementation flag
5216 if (implementing != null)
5217 parent.PartialContainer.PendingImplementations.ImplementMethod (method.MethodName.Basename,
5218 member.InterfaceType, this, member.IsExplicitImpl);
5220 SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
5222 ToplevelBlock block = method.Block;
5223 if (block != null) {
5224 BlockContext bc = new BlockContext ((IMemberContext) method, block, method.ReturnType);
5225 if (block.Resolve (null, bc, method.ParameterInfo, method)) {
5226 EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator ());
5227 if (!ec.HasReturnLabel && bc.HasReturnLabel) {
5228 ec.ReturnLabel = bc.ReturnLabel;
5229 ec.HasReturnLabel = true;
5232 block.Emit (ec);
5236 if (source != null) {
5237 method.EmitExtraSymbolInfo (source);
5238 source.CloseMethod ();
5243 public class Destructor : MethodOrOperator
5245 const int AllowedModifiers =
5246 Modifiers.UNSAFE |
5247 Modifiers.EXTERN;
5249 static readonly string[] attribute_targets = new string [] { "method" };
5251 public static readonly string MetadataName = "Finalize";
5253 public Destructor (DeclSpace parent, int mod, ParametersCompiled parameters, Attributes attrs, Location l)
5254 : base (parent, null, TypeManager.system_void_expr, mod, AllowedModifiers,
5255 new MemberName (MetadataName, l), attrs, parameters)
5257 ModFlags &= ~Modifiers.PRIVATE;
5258 ModFlags |= Modifiers.PROTECTED;
5261 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
5263 if (a.Type == pa.Conditional) {
5264 Error_ConditionalAttributeIsNotValid ();
5265 return;
5268 base.ApplyAttributeBuilder (a, cb, pa);
5271 protected override bool CheckBase ()
5273 flags |= MethodAttributes.Virtual;
5275 if (!base.CheckBase ())
5276 return false;
5278 if (Parent.PartialContainer.BaseCache == null)
5279 return true;
5281 Type base_type = Parent.PartialContainer.BaseCache.Container.Type;
5282 if (base_type != null && Block != null) {
5283 MethodGroupExpr method_expr = Expression.MethodLookup (Parent.Module.Compiler, Parent.TypeBuilder, base_type, MetadataName, Location);
5284 if (method_expr == null)
5285 throw new NotImplementedException ();
5287 method_expr.IsBase = true;
5288 method_expr.InstanceExpression = new CompilerGeneratedThis (Parent.TypeBuilder, Location);
5290 ToplevelBlock new_block = new ToplevelBlock (Compiler, Block.StartLocation);
5291 new_block.EndLocation = Block.EndLocation;
5293 Block finaly_block = new ExplicitBlock (new_block, Location, Location);
5294 Block try_block = new Block (new_block, block);
5297 // 0-size arguments to avoid CS0250 error
5298 // TODO: Should use AddScopeStatement or something else which emits correct
5299 // debugger scope
5301 finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0))));
5302 new_block.AddStatement (new TryFinally (try_block, finaly_block, Location));
5304 block = new_block;
5307 return true;
5310 public override string GetSignatureForError ()
5312 return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
5315 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
5317 return null;
5320 public override string[] ValidAttributeTargets {
5321 get {
5322 return attribute_targets;
5327 public abstract class MemberBase : MemberCore
5329 protected FullNamedExpression type_name;
5330 protected Type member_type;
5332 public readonly DeclSpace ds;
5333 public readonly GenericMethod GenericMethod;
5335 protected MemberBase (DeclSpace parent, GenericMethod generic,
5336 FullNamedExpression type, int mod, int allowed_mod, int def_mod,
5337 MemberName name, Attributes attrs)
5338 : base (parent, name, attrs)
5340 this.ds = generic != null ? generic : (DeclSpace) parent;
5341 this.type_name = type;
5342 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, Location, Report);
5343 GenericMethod = generic;
5344 if (GenericMethod != null)
5345 GenericMethod.ModFlags = ModFlags;
5349 // Main member define entry
5351 public override bool Define ()
5353 DoMemberTypeIndependentChecks ();
5356 // Returns false only when type resolution failed
5358 if (!ResolveMemberType ())
5359 return false;
5361 DoMemberTypeDependentChecks ();
5362 return true;
5366 // Any type_name independent checks
5368 protected virtual void DoMemberTypeIndependentChecks ()
5370 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
5371 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
5372 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
5373 GetSignatureForError (), Parent.GetSignatureForError ());
5378 // Any type_name dependent checks
5380 protected virtual void DoMemberTypeDependentChecks ()
5382 // verify accessibility
5383 if (!IsAccessibleAs (MemberType)) {
5384 Report.SymbolRelatedToPreviousError (MemberType);
5385 if (this is Property)
5386 Report.Error (53, Location,
5387 "Inconsistent accessibility: property type `" +
5388 TypeManager.CSharpName (MemberType) + "' is less " +
5389 "accessible than property `" + GetSignatureForError () + "'");
5390 else if (this is Indexer)
5391 Report.Error (54, Location,
5392 "Inconsistent accessibility: indexer return type `" +
5393 TypeManager.CSharpName (MemberType) + "' is less " +
5394 "accessible than indexer `" + GetSignatureForError () + "'");
5395 else if (this is MethodCore) {
5396 if (this is Operator)
5397 Report.Error (56, Location,
5398 "Inconsistent accessibility: return type `" +
5399 TypeManager.CSharpName (MemberType) + "' is less " +
5400 "accessible than operator `" + GetSignatureForError () + "'");
5401 else
5402 Report.Error (50, Location,
5403 "Inconsistent accessibility: return type `" +
5404 TypeManager.CSharpName (MemberType) + "' is less " +
5405 "accessible than method `" + GetSignatureForError () + "'");
5406 } else {
5407 Report.Error (52, Location,
5408 "Inconsistent accessibility: field type `" +
5409 TypeManager.CSharpName (MemberType) + "' is less " +
5410 "accessible than field `" + GetSignatureForError () + "'");
5414 Variance variance = this is Event ? Variance.Contravariant : Variance.Covariant;
5415 TypeManager.CheckTypeVariance (MemberType, variance, this);
5418 protected bool IsTypePermitted ()
5420 if (TypeManager.IsSpecialType (MemberType)) {
5421 Report.Error (610, Location, "Field or property cannot be of type `{0}'", TypeManager.CSharpName (MemberType));
5422 return false;
5424 return true;
5427 protected virtual bool CheckBase ()
5429 CheckProtectedModifier ();
5431 return true;
5434 public Type MemberType {
5435 get { return member_type; }
5438 protected virtual bool ResolveMemberType ()
5440 if (member_type != null)
5441 throw new InternalErrorException ("Multi-resolve");
5443 TypeExpr te = type_name.ResolveAsTypeTerminal (this, false);
5444 if (te == null)
5445 return false;
5448 // Replace original type name, error reporting can use fully resolved name
5450 type_name = te;
5452 member_type = te.Type;
5453 return true;
5458 // Abstract class for all fields
5460 abstract public class FieldBase : MemberBase {
5461 public FieldBuilder FieldBuilder;
5462 public Status status;
5463 protected Expression initializer;
5465 [Flags]
5466 public enum Status : byte {
5467 HAS_OFFSET = 4 // Used by FieldMember.
5470 static readonly string[] attribute_targets = new string [] { "field" };
5472 protected FieldBase (DeclSpace parent, FullNamedExpression type, int mod,
5473 int allowed_mod, MemberName name, Attributes attrs)
5474 : base (parent, null, type, mod, allowed_mod | Modifiers.ABSTRACT, Modifiers.PRIVATE,
5475 name, attrs)
5477 if ((mod & Modifiers.ABSTRACT) != 0)
5478 Report.Error (681, Location, "The modifier 'abstract' is not valid on fields. Try using a property instead");
5481 public override AttributeTargets AttributeTargets {
5482 get {
5483 return AttributeTargets.Field;
5487 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
5489 if (a.Type == pa.FieldOffset) {
5490 status |= Status.HAS_OFFSET;
5492 if (!Parent.PartialContainer.HasExplicitLayout) {
5493 Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)");
5494 return;
5497 if ((ModFlags & Modifiers.STATIC) != 0 || this is Const) {
5498 Report.Error (637, Location, "The FieldOffset attribute is not allowed on static or const fields");
5499 return;
5503 if (a.Type == pa.FixedBuffer) {
5504 Report.Error (1716, Location, "Do not use 'System.Runtime.CompilerServices.FixedBuffer' attribute. Use the 'fixed' field modifier instead");
5505 return;
5508 #if false
5509 if (a.Type == pa.MarshalAs) {
5510 UnmanagedMarshal marshal = a.GetMarshal (this);
5511 if (marshal != null) {
5512 FieldBuilder.SetMarshal (marshal);
5514 return;
5516 #endif
5517 if ((a.HasSecurityAttribute)) {
5518 a.Error_InvalidSecurityParent ();
5519 return;
5522 if (a.Type == pa.Dynamic) {
5523 a.Error_MisusedDynamicAttribute ();
5524 return;
5527 FieldBuilder.SetCustomAttribute (cb);
5530 protected override bool CheckBase ()
5532 if (!base.CheckBase ())
5533 return false;
5535 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Name, false);
5536 if (conflict_symbol == null) {
5537 if ((ModFlags & Modifiers.NEW) != 0) {
5538 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
5540 return true;
5543 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE | Modifiers.BACKING_FIELD)) == 0) {
5544 Report.SymbolRelatedToPreviousError (conflict_symbol);
5545 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
5546 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
5549 return true;
5552 protected override void DoMemberTypeDependentChecks ()
5554 base.DoMemberTypeDependentChecks ();
5556 if (TypeManager.IsGenericParameter (MemberType))
5557 return;
5559 if (MemberType.IsSealed && MemberType.IsAbstract) {
5560 Error_VariableOfStaticClass (Location, GetSignatureForError (), MemberType, Report);
5563 CheckBase ();
5564 IsTypePermitted ();
5568 // Represents header string for documentation comment.
5570 public override string DocCommentHeader {
5571 get { return "F:"; }
5574 public override void Emit ()
5576 if (TypeManager.IsDynamicType (member_type))
5577 PredefinedAttributes.Get.Dynamic.EmitAttribute (FieldBuilder);
5579 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
5580 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (FieldBuilder);
5582 if (OptAttributes != null) {
5583 OptAttributes.Emit ();
5586 if (((status & Status.HAS_OFFSET) == 0) && (ModFlags & (Modifiers.STATIC | Modifiers.BACKING_FIELD)) == 0 && Parent.PartialContainer.HasExplicitLayout) {
5587 Report.Error (625, Location, "`{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute", GetSignatureForError ());
5590 base.Emit ();
5593 public static void Error_VariableOfStaticClass (Location loc, string variable_name, Type static_class, Report Report)
5595 Report.SymbolRelatedToPreviousError (static_class);
5596 Report.Error (723, loc, "`{0}': cannot declare variables of static types",
5597 variable_name);
5600 public Expression Initializer {
5601 set {
5602 if (value != null) {
5603 this.initializer = value;
5608 protected virtual bool IsFieldClsCompliant {
5609 get {
5610 if (FieldBuilder == null)
5611 return true;
5613 return AttributeTester.IsClsCompliant (FieldBuilder.FieldType);
5617 public override string[] ValidAttributeTargets
5619 get {
5620 return attribute_targets;
5624 protected override bool VerifyClsCompliance ()
5626 if (!base.VerifyClsCompliance ())
5627 return false;
5629 if (!IsFieldClsCompliant) {
5630 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
5631 GetSignatureForError ());
5633 return true;
5636 public void SetAssigned ()
5638 caching_flags |= Flags.IsAssigned;
5642 interface IFixedBuffer
5644 FieldInfo Element { get; }
5645 Type ElementType { get; }
5648 public class FixedFieldExternal: IFixedBuffer
5650 FieldInfo element_field;
5652 public FixedFieldExternal (FieldInfo fi)
5654 element_field = fi.FieldType.GetField (FixedField.FixedElementName);
5657 #region IFixedField Members
5659 public FieldInfo Element {
5660 get {
5661 return element_field;
5665 public Type ElementType {
5666 get {
5667 return element_field.FieldType;
5671 #endregion
5674 /// <summary>
5675 /// Fixed buffer implementation
5676 /// </summary>
5677 public class FixedField : FieldBase, IFixedBuffer
5679 public const string FixedElementName = "FixedElementField";
5680 static int GlobalCounter = 0;
5681 static object[] ctor_args = new object[] { (short)LayoutKind.Sequential };
5682 static FieldInfo[] fi;
5684 TypeBuilder fixed_buffer_type;
5685 FieldBuilder element;
5686 Expression size_expr;
5688 const int AllowedModifiers =
5689 Modifiers.NEW |
5690 Modifiers.PUBLIC |
5691 Modifiers.PROTECTED |
5692 Modifiers.INTERNAL |
5693 Modifiers.PRIVATE;
5695 public FixedField (DeclSpace parent, FullNamedExpression type, int mod, string name,
5696 Expression size_expr, Attributes attrs, Location loc):
5697 base (parent, type, mod, AllowedModifiers, new MemberName (name, loc), attrs)
5699 if (RootContext.Version < LanguageVersion.ISO_2)
5700 Report.FeatureIsNotAvailable (loc, "fixed size buffers");
5702 this.size_expr = size_expr;
5705 public override bool Define()
5707 if (!base.Define ())
5708 return false;
5710 if (!TypeManager.IsPrimitiveType (MemberType)) {
5711 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",
5712 GetSignatureForError ());
5715 // Create nested fixed buffer container
5716 string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++);
5717 fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name, Parent.Module.DefaultCharSetType |
5718 TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, TypeManager.value_type);
5720 element = fixed_buffer_type.DefineField (FixedElementName, MemberType, FieldAttributes.Public);
5721 RootContext.RegisterCompilerGeneratedType (fixed_buffer_type);
5723 FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, Modifiers.FieldAttr (ModFlags));
5724 Parent.MemberCache.AddMember (FieldBuilder, this);
5725 TypeManager.RegisterFieldBase (FieldBuilder, this);
5727 return true;
5730 protected override void DoMemberTypeIndependentChecks ()
5732 base.DoMemberTypeIndependentChecks ();
5734 if (!Parent.IsUnsafe)
5735 Expression.UnsafeError (Report, Location);
5737 if (Parent.PartialContainer.Kind != Kind.Struct) {
5738 Report.Error (1642, Location, "`{0}': Fixed size buffer fields may only be members of structs",
5739 GetSignatureForError ());
5743 public override void Emit()
5745 ResolveContext rc = new ResolveContext (this);
5746 Constant c = size_expr.ResolveAsConstant (rc, this);
5747 if (c == null)
5748 return;
5750 IntConstant buffer_size_const = c.ImplicitConversionRequired (rc, TypeManager.int32_type, Location) as IntConstant;
5751 if (buffer_size_const == null)
5752 return;
5754 int buffer_size = buffer_size_const.Value;
5756 if (buffer_size <= 0) {
5757 Report.Error (1665, Location, "`{0}': Fixed size buffers must have a length greater than zero", GetSignatureForError ());
5758 return;
5761 int type_size = Expression.GetTypeSize (MemberType);
5763 if (buffer_size > int.MaxValue / type_size) {
5764 Report.Error (1664, Location, "Fixed size buffer `{0}' of length `{1}' and type `{2}' exceeded 2^31 limit",
5765 GetSignatureForError (), buffer_size.ToString (), TypeManager.CSharpName (MemberType));
5766 return;
5769 buffer_size *= type_size;
5770 EmitFieldSize (buffer_size);
5772 PredefinedAttributes.Get.UnsafeValueType.EmitAttribute (fixed_buffer_type);
5774 base.Emit ();
5777 void EmitFieldSize (int buffer_size)
5779 CustomAttributeBuilder cab;
5780 PredefinedAttribute pa;
5782 pa = PredefinedAttributes.Get.StructLayout;
5783 if (pa.Constructor == null &&
5784 !pa.ResolveConstructor (Location, TypeManager.short_type))
5785 return;
5787 // TODO: It's not cleared
5788 if (fi == null)
5789 fi = new FieldInfo[] { pa.Type.GetField ("Size") };
5791 object[] fi_val = new object[] { buffer_size };
5792 cab = new CustomAttributeBuilder (pa.Constructor,
5793 ctor_args, fi, fi_val);
5794 fixed_buffer_type.SetCustomAttribute (cab);
5797 // Don't emit FixedBufferAttribute attribute for private types
5799 if ((ModFlags & Modifiers.PRIVATE) != 0)
5800 return;
5802 pa = PredefinedAttributes.Get.FixedBuffer;
5803 if (pa.Constructor == null &&
5804 !pa.ResolveConstructor (Location, TypeManager.type_type, TypeManager.int32_type))
5805 return;
5807 cab = new CustomAttributeBuilder (pa.Constructor, new object[] { MemberType, buffer_size });
5808 FieldBuilder.SetCustomAttribute (cab);
5811 protected override bool IsFieldClsCompliant {
5812 get {
5813 return false;
5817 public void SetCharSet (TypeAttributes ta)
5819 TypeAttributes cta = fixed_buffer_type.Attributes;
5820 if ((cta & TypeAttributes.UnicodeClass) != (ta & TypeAttributes.UnicodeClass))
5821 SetTypeBuilderCharSet ((cta & ~TypeAttributes.AutoClass) | TypeAttributes.UnicodeClass);
5822 else if ((cta & TypeAttributes.AutoClass) != (ta & TypeAttributes.AutoClass))
5823 SetTypeBuilderCharSet ((cta & ~TypeAttributes.UnicodeClass) | TypeAttributes.AutoClass);
5824 else if (cta == 0 && ta != 0)
5825 SetTypeBuilderCharSet (cta & ~(TypeAttributes.UnicodeClass | TypeAttributes.AutoClass));
5828 void SetTypeBuilderCharSet (TypeAttributes ta)
5830 MethodInfo mi = typeof (TypeBuilder).GetMethod ("SetCharSet", BindingFlags.Instance | BindingFlags.NonPublic);
5831 if (mi == null) {
5832 Report.RuntimeMissingSupport (Location, "TypeBuilder::SetCharSet");
5833 } else {
5834 mi.Invoke (fixed_buffer_type, new object [] { ta });
5838 #region IFixedField Members
5840 public FieldInfo Element {
5841 get {
5842 return element;
5846 public Type ElementType {
5847 get {
5848 return MemberType;
5852 #endregion
5856 // The Field class is used to represents class/struct fields during parsing.
5858 public class Field : FieldBase {
5859 // <summary>
5860 // Modifiers allowed in a class declaration
5861 // </summary>
5862 const int AllowedModifiers =
5863 Modifiers.NEW |
5864 Modifiers.PUBLIC |
5865 Modifiers.PROTECTED |
5866 Modifiers.INTERNAL |
5867 Modifiers.PRIVATE |
5868 Modifiers.STATIC |
5869 Modifiers.VOLATILE |
5870 Modifiers.UNSAFE |
5871 Modifiers.READONLY;
5873 public Field (DeclSpace parent, FullNamedExpression type, int mod, MemberName name,
5874 Attributes attrs)
5875 : base (parent, type, mod, AllowedModifiers, name, attrs)
5879 bool CanBeVolatile ()
5881 if (TypeManager.IsReferenceType (MemberType))
5882 return true;
5884 if (MemberType == TypeManager.bool_type || MemberType == TypeManager.char_type ||
5885 MemberType == TypeManager.sbyte_type || MemberType == TypeManager.byte_type ||
5886 MemberType == TypeManager.short_type || MemberType == TypeManager.ushort_type ||
5887 MemberType == TypeManager.int32_type || MemberType == TypeManager.uint32_type ||
5888 MemberType == TypeManager.float_type ||
5889 MemberType == TypeManager.intptr_type || MemberType == TypeManager.uintptr_type)
5890 return true;
5892 if (TypeManager.IsEnumType (MemberType))
5893 return true;
5895 return false;
5898 bool CheckStructLayout (Type type, bool isStatic)
5900 if (TypeManager.IsBuiltinType (type))
5901 return true;
5903 if (isStatic) {
5904 if (!TypeManager.IsValueType (type) || TypeManager.IsEqual (type, Parent.TypeBuilder))
5905 return true;
5908 if (!TypeManager.IsEqual (TypeManager.DropGenericTypeArguments (type), Parent.TypeBuilder)) {
5909 if (!TypeManager.IsGenericType (type))
5910 return true;
5912 foreach (Type t in TypeManager.GetTypeArguments (type)) {
5913 if (!CheckStructLayout (t, false))
5914 return false;
5916 return true;
5919 Report.Error (523, Location,
5920 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
5921 GetSignatureForError (), TypeManager.CSharpName (MemberType));
5922 return false;
5925 public override bool Define ()
5927 if (!base.Define ())
5928 return false;
5930 try {
5931 Type[] required_modifier = null;
5932 if ((ModFlags & Modifiers.VOLATILE) != 0) {
5933 if (TypeManager.isvolatile_type == null)
5934 TypeManager.isvolatile_type = TypeManager.CoreLookupType (Compiler,
5935 "System.Runtime.CompilerServices", "IsVolatile", Kind.Class, true);
5937 if (TypeManager.isvolatile_type != null)
5938 required_modifier = new Type [] { TypeManager.isvolatile_type };
5941 FieldBuilder = Parent.TypeBuilder.DefineField (
5942 Name, MemberType, required_modifier, null, Modifiers.FieldAttr (ModFlags));
5944 // Don't cache inaccessible fields
5945 if ((ModFlags & Modifiers.BACKING_FIELD) == 0) {
5946 Parent.MemberCache.AddMember (FieldBuilder, this);
5949 TypeManager.RegisterFieldBase (FieldBuilder, this);
5951 catch (ArgumentException) {
5952 Report.RuntimeMissingSupport (Location, "`void' or `void*' field type");
5953 return false;
5956 if (initializer != null) {
5957 ((TypeContainer) Parent).RegisterFieldForInitialization (this,
5958 new FieldInitializer (FieldBuilder, initializer, this));
5959 } else {
5960 if (Parent.PartialContainer.Kind == Kind.Struct)
5961 CheckStructLayout (member_type, (ModFlags & Modifiers.STATIC) != 0);
5964 return true;
5967 protected override void DoMemberTypeDependentChecks ()
5969 base.DoMemberTypeDependentChecks ();
5971 if ((ModFlags & Modifiers.VOLATILE) != 0) {
5972 if (!CanBeVolatile ()) {
5973 Report.Error (677, Location, "`{0}': A volatile field cannot be of the type `{1}'",
5974 GetSignatureForError (), TypeManager.CSharpName (MemberType));
5977 if ((ModFlags & Modifiers.READONLY) != 0) {
5978 Report.Error (678, Location, "`{0}': A field cannot be both volatile and readonly",
5979 GetSignatureForError ());
5984 protected override bool VerifyClsCompliance ()
5986 if (!base.VerifyClsCompliance ())
5987 return false;
5989 if ((ModFlags & Modifiers.VOLATILE) != 0) {
5990 Report.Warning (3026, 1, Location, "CLS-compliant field `{0}' cannot be volatile", GetSignatureForError ());
5993 return true;
5998 // `set' and `get' accessors are represented with an Accessor.
6000 public class Accessor {
6002 // Null if the accessor is empty, or a Block if not
6004 public const int AllowedModifiers =
6005 Modifiers.PUBLIC |
6006 Modifiers.PROTECTED |
6007 Modifiers.INTERNAL |
6008 Modifiers.PRIVATE;
6010 public ToplevelBlock Block;
6011 public Attributes Attributes;
6012 public Location Location;
6013 public int ModFlags;
6014 public ParametersCompiled Parameters;
6016 public Accessor (ToplevelBlock b, int mod, Attributes attrs, ParametersCompiled p, Location loc)
6018 Block = b;
6019 Attributes = attrs;
6020 Location = loc;
6021 Parameters = p;
6022 ModFlags = Modifiers.Check (AllowedModifiers, mod, 0, loc, RootContext.ToplevelTypes.Compiler.Report);
6026 // Ooouh Martin, templates are missing here.
6027 // When it will be possible move here a lot of child code and template method type.
6028 public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData {
6029 protected MethodData method_data;
6030 protected ToplevelBlock block;
6031 protected ListDictionary declarative_security;
6033 // The accessor are created even if they are not wanted.
6034 // But we need them because their names are reserved.
6035 // Field says whether accessor will be emited or not
6036 public readonly bool IsDummy;
6038 protected readonly string prefix;
6040 ReturnParameter return_attributes;
6042 public AbstractPropertyEventMethod (PropertyBasedMember member, string prefix)
6043 : base (member.Parent, SetupName (prefix, member, member.Location), null)
6045 this.prefix = prefix;
6046 IsDummy = true;
6049 public AbstractPropertyEventMethod (InterfaceMemberBase member, Accessor accessor,
6050 string prefix)
6051 : base (member.Parent, SetupName (prefix, member, accessor.Location),
6052 accessor.Attributes)
6054 this.prefix = prefix;
6055 this.block = accessor.Block;
6058 static MemberName SetupName (string prefix, InterfaceMemberBase member, Location loc)
6060 return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc);
6063 public void UpdateName (InterfaceMemberBase member)
6065 SetMemberName (SetupName (prefix, member, Location));
6068 #region IMethodData Members
6070 public ToplevelBlock Block {
6071 get {
6072 return block;
6075 set {
6076 block = value;
6080 public CallingConventions CallingConventions {
6081 get {
6082 return CallingConventions.Standard;
6086 public EmitContext CreateEmitContext (ILGenerator ig)
6088 return new EmitContext (this, ig, ReturnType);
6091 public bool IsExcluded ()
6093 return false;
6096 GenericMethod IMethodData.GenericMethod {
6097 get {
6098 return null;
6102 public MemberName MethodName {
6103 get {
6104 return MemberName;
6108 public Type[] ParameterTypes {
6109 get {
6110 return ParameterInfo.Types;
6114 public abstract ParametersCompiled ParameterInfo { get ; }
6115 public abstract Type ReturnType { get; }
6117 #endregion
6119 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6121 if (a.Type == pa.CLSCompliant || a.Type == pa.Obsolete || a.Type == pa.Conditional) {
6122 Report.Error (1667, a.Location,
6123 "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
6124 TypeManager.CSharpName (a.Type), a.GetValidTargets ());
6125 return;
6128 if (a.IsValidSecurityAttribute ()) {
6129 if (declarative_security == null)
6130 declarative_security = new ListDictionary ();
6131 a.ExtractSecurityPermissionSet (declarative_security);
6132 return;
6135 if (a.Target == AttributeTargets.Method) {
6136 method_data.MethodBuilder.SetCustomAttribute (cb);
6137 return;
6140 if (a.Target == AttributeTargets.ReturnValue) {
6141 if (return_attributes == null)
6142 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
6144 return_attributes.ApplyAttributeBuilder (a, cb, pa);
6145 return;
6148 ApplyToExtraTarget (a, cb, pa);
6151 protected virtual void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6153 throw new NotSupportedException ("You forgot to define special attribute target handling");
6156 // It is not supported for the accessors
6157 public sealed override bool Define()
6159 throw new NotSupportedException ();
6162 public virtual void Emit (DeclSpace parent)
6164 method_data.Emit (parent);
6166 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
6167 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (method_data.MethodBuilder);
6168 if (((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0))
6169 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (method_data.MethodBuilder);
6171 if (TypeManager.IsDynamicType (ReturnType)) {
6172 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
6173 PredefinedAttributes.Get.Dynamic.EmitAttribute (return_attributes.Builder);
6176 if (OptAttributes != null)
6177 OptAttributes.Emit ();
6179 if (declarative_security != null) {
6180 foreach (DictionaryEntry de in declarative_security) {
6181 method_data.MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
6185 block = null;
6188 public override bool EnableOverloadChecks (MemberCore overload)
6190 // This can only happen with indexers and it will
6191 // be catched as indexer difference
6192 if (overload is AbstractPropertyEventMethod)
6193 return true;
6195 if (overload is MethodCore) {
6196 caching_flags |= Flags.MethodOverloadsExist;
6197 return true;
6199 return false;
6202 public override bool IsClsComplianceRequired()
6204 return false;
6207 public bool IsDuplicateImplementation (MethodCore method)
6209 if (!MemberName.Equals (method.MemberName))
6210 return false;
6212 Type[] param_types = method.ParameterTypes;
6214 if (param_types == null || param_types.Length != ParameterTypes.Length)
6215 return false;
6217 for (int i = 0; i < param_types.Length; i++)
6218 if (param_types [i] != ParameterTypes [i])
6219 return false;
6221 Report.SymbolRelatedToPreviousError (method);
6222 Report.Error (82, Location, "A member `{0}' is already reserved",
6223 method.GetSignatureForError ());
6224 return true;
6227 public override bool IsUsed
6229 get {
6230 if (IsDummy)
6231 return false;
6233 return base.IsUsed;
6238 // Represents header string for documentation comment.
6240 public override string DocCommentHeader {
6241 get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
6244 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
6249 // Properties and Indexers both generate PropertyBuilders, we use this to share
6250 // their common bits.
6252 abstract public class PropertyBase : PropertyBasedMember {
6254 public class GetMethod : PropertyMethod
6256 static string[] attribute_targets = new string [] { "method", "return" };
6258 public GetMethod (PropertyBase method):
6259 base (method, "get_")
6263 public GetMethod (PropertyBase method, Accessor accessor):
6264 base (method, accessor, "get_")
6268 public override MethodBuilder Define (DeclSpace parent)
6270 base.Define (parent);
6272 if (IsDummy)
6273 return null;
6275 method_data = new MethodData (method, ModFlags, flags, this);
6277 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
6278 return null;
6280 return method_data.MethodBuilder;
6283 public override Type ReturnType {
6284 get {
6285 return method.MemberType;
6289 public override ParametersCompiled ParameterInfo {
6290 get {
6291 return ParametersCompiled.EmptyReadOnlyParameters;
6295 public override string[] ValidAttributeTargets {
6296 get {
6297 return attribute_targets;
6302 public class SetMethod : PropertyMethod {
6304 static string[] attribute_targets = new string [] { "method", "param", "return" };
6305 ImplicitParameter param_attr;
6306 protected ParametersCompiled parameters;
6308 public SetMethod (PropertyBase method) :
6309 base (method, "set_")
6311 parameters = new ParametersCompiled (Compiler,
6312 new Parameter (method.type_name, "value", Parameter.Modifier.NONE, null, Location));
6315 public SetMethod (PropertyBase method, Accessor accessor):
6316 base (method, accessor, "set_")
6318 this.parameters = accessor.Parameters;
6321 protected override void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6323 if (a.Target == AttributeTargets.Parameter) {
6324 if (param_attr == null)
6325 param_attr = new ImplicitParameter (method_data.MethodBuilder);
6327 param_attr.ApplyAttributeBuilder (a, cb, pa);
6328 return;
6331 base.ApplyAttributeBuilder (a, cb, pa);
6334 public override ParametersCompiled ParameterInfo {
6335 get {
6336 return parameters;
6340 public override MethodBuilder Define (DeclSpace parent)
6342 parameters.Resolve (this);
6344 base.Define (parent);
6346 if (IsDummy)
6347 return null;
6349 method_data = new MethodData (method, ModFlags, flags, this);
6351 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
6352 return null;
6354 return method_data.MethodBuilder;
6357 public override Type ReturnType {
6358 get {
6359 return TypeManager.void_type;
6363 public override string[] ValidAttributeTargets {
6364 get {
6365 return attribute_targets;
6370 static string[] attribute_targets = new string [] { "property" };
6372 public abstract class PropertyMethod : AbstractPropertyEventMethod
6374 protected readonly PropertyBase method;
6375 protected MethodAttributes flags;
6377 public PropertyMethod (PropertyBase method, string prefix)
6378 : base (method, prefix)
6380 this.method = method;
6381 this.ModFlags = method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE);
6384 public PropertyMethod (PropertyBase method, Accessor accessor,
6385 string prefix)
6386 : base (method, accessor, prefix)
6388 this.method = method;
6389 this.ModFlags = accessor.ModFlags | (method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE));
6391 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
6392 Report.FeatureIsNotAvailable (Location, "access modifiers on properties");
6396 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6398 if (a.IsInternalMethodImplAttribute) {
6399 method.is_external_implementation = true;
6402 base.ApplyAttributeBuilder (a, cb, pa);
6405 public override AttributeTargets AttributeTargets {
6406 get {
6407 return AttributeTargets.Method;
6411 public override bool IsClsComplianceRequired ()
6413 return method.IsClsComplianceRequired ();
6416 public virtual MethodBuilder Define (DeclSpace parent)
6418 CheckForDuplications ();
6420 if (IsDummy) {
6421 if (method.InterfaceType != null && parent.PartialContainer.PendingImplementations != null) {
6422 MethodInfo mi = parent.PartialContainer.PendingImplementations.IsInterfaceMethod (
6423 MethodName.Name, method.InterfaceType, new MethodData (method, ModFlags, flags, this));
6424 if (mi != null) {
6425 Report.SymbolRelatedToPreviousError (mi);
6426 Report.Error (551, Location, "Explicit interface implementation `{0}' is missing accessor `{1}'",
6427 method.GetSignatureForError (), TypeManager.CSharpSignature (mi, true));
6430 return null;
6433 TypeContainer container = parent.PartialContainer;
6436 // Check for custom access modifier
6438 if ((ModFlags & Modifiers.Accessibility) == 0) {
6439 ModFlags |= method.ModFlags;
6440 flags = method.flags;
6441 } else {
6442 if (container.Kind == Kind.Interface)
6443 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
6444 GetSignatureForError ());
6446 if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
6447 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
6450 CheckModifiers (ModFlags);
6451 ModFlags |= (method.ModFlags & (~Modifiers.Accessibility));
6452 ModFlags |= Modifiers.PROPERTY_CUSTOM;
6453 flags = Modifiers.MethodAttr (ModFlags);
6454 flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
6457 CheckAbstractAndExtern (block != null);
6458 CheckProtectedModifier ();
6460 if (block != null && block.IsIterator)
6461 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
6463 return null;
6466 public bool HasCustomAccessModifier {
6467 get {
6468 return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
6472 public PropertyBase Property {
6473 get {
6474 return method;
6478 public override ObsoleteAttribute GetObsoleteAttribute ()
6480 return method.GetObsoleteAttribute ();
6483 public override string GetSignatureForError()
6485 return method.GetSignatureForError () + '.' + prefix.Substring (0, 3);
6488 void CheckModifiers (int modflags)
6490 modflags &= Modifiers.Accessibility;
6491 int flags = 0;
6492 int mflags = method.ModFlags & Modifiers.Accessibility;
6494 if ((mflags & Modifiers.PUBLIC) != 0) {
6495 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
6497 else if ((mflags & Modifiers.PROTECTED) != 0) {
6498 if ((mflags & Modifiers.INTERNAL) != 0)
6499 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL;
6501 flags |= Modifiers.PRIVATE;
6503 else if ((mflags & Modifiers.INTERNAL) != 0)
6504 flags |= Modifiers.PRIVATE;
6506 if ((mflags == modflags) || (modflags & (~flags)) != 0) {
6507 Report.Error (273, Location,
6508 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
6509 GetSignatureForError (), method.GetSignatureForError ());
6513 protected bool CheckForDuplications ()
6515 if ((caching_flags & Flags.MethodOverloadsExist) == 0)
6516 return true;
6518 return Parent.MemberCache.CheckExistingMembersOverloads (this, Name, ParameterInfo, Report);
6522 public PropertyMethod Get, Set;
6523 public PropertyBuilder PropertyBuilder;
6524 public MethodBuilder GetBuilder, SetBuilder;
6526 protected bool define_set_first = false;
6528 public PropertyBase (DeclSpace parent, FullNamedExpression type, int mod_flags,
6529 int allowed_mod, MemberName name,
6530 Attributes attrs, bool define_set_first)
6531 : base (parent, null, type, mod_flags, allowed_mod, name, attrs)
6533 this.define_set_first = define_set_first;
6536 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6538 if (a.HasSecurityAttribute) {
6539 a.Error_InvalidSecurityParent ();
6540 return;
6543 if (a.Type == pa.Dynamic) {
6544 a.Error_MisusedDynamicAttribute ();
6545 return;
6548 PropertyBuilder.SetCustomAttribute (cb);
6551 public override AttributeTargets AttributeTargets {
6552 get {
6553 return AttributeTargets.Property;
6557 protected override void DoMemberTypeDependentChecks ()
6559 base.DoMemberTypeDependentChecks ();
6561 IsTypePermitted ();
6562 #if MS_COMPATIBLE
6563 if (MemberType.IsGenericParameter)
6564 return;
6565 #endif
6567 if ((MemberType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
6568 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
6572 protected override void DoMemberTypeIndependentChecks ()
6574 base.DoMemberTypeIndependentChecks ();
6577 // Accessors modifiers check
6579 if ((Get.ModFlags & Modifiers.Accessibility) != 0 &&
6580 (Set.ModFlags & Modifiers.Accessibility) != 0) {
6581 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
6582 GetSignatureForError ());
6585 if ((ModFlags & Modifiers.OVERRIDE) == 0 &&
6586 (Get.IsDummy && (Set.ModFlags & Modifiers.Accessibility) != 0) ||
6587 (Set.IsDummy && (Get.ModFlags & Modifiers.Accessibility) != 0)) {
6588 Report.Error (276, Location,
6589 "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
6590 GetSignatureForError ());
6594 bool DefineGet ()
6596 GetBuilder = Get.Define (Parent);
6597 return (Get.IsDummy) ? true : GetBuilder != null;
6600 bool DefineSet (bool define)
6602 if (!define)
6603 return true;
6605 SetBuilder = Set.Define (Parent);
6606 return (Set.IsDummy) ? true : SetBuilder != null;
6609 protected bool DefineAccessors ()
6611 return DefineSet (define_set_first) &&
6612 DefineGet () &&
6613 DefineSet (!define_set_first);
6616 protected abstract PropertyInfo ResolveBaseProperty ();
6618 // TODO: rename to Resolve......
6619 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
6621 PropertyInfo base_property = ResolveBaseProperty ();
6622 if (base_property == null)
6623 return null;
6625 base_ret_type = base_property.PropertyType;
6626 MethodInfo get_accessor = base_property.GetGetMethod (true);
6627 MethodInfo set_accessor = base_property.GetSetMethod (true);
6628 MethodAttributes get_accessor_access = 0, set_accessor_access = 0;
6631 // Check base property accessors conflict
6633 if ((ModFlags & (Modifiers.OVERRIDE | Modifiers.NEW)) == Modifiers.OVERRIDE) {
6634 if (get_accessor == null) {
6635 if (Get != null && !Get.IsDummy) {
6636 Report.SymbolRelatedToPreviousError (base_property);
6637 Report.Error (545, Location,
6638 "`{0}.get': cannot override because `{1}' does not have an overridable get accessor",
6639 GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6641 } else {
6642 get_accessor_access = get_accessor.Attributes & MethodAttributes.MemberAccessMask;
6644 if (!Get.IsDummy && !CheckAccessModifiers (
6645 Modifiers.MethodAttr (Get.ModFlags) & MethodAttributes.MemberAccessMask, get_accessor_access, get_accessor))
6646 Error_CannotChangeAccessModifiers (Get.Location, get_accessor, get_accessor_access, ".get");
6649 if (set_accessor == null) {
6650 if (Set != null && !Set.IsDummy) {
6651 Report.SymbolRelatedToPreviousError (base_property);
6652 Report.Error (546, Location,
6653 "`{0}.set': cannot override because `{1}' does not have an overridable set accessor",
6654 GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6656 } else {
6657 set_accessor_access = set_accessor.Attributes & MethodAttributes.MemberAccessMask;
6659 if (!Set.IsDummy && !CheckAccessModifiers (
6660 Modifiers.MethodAttr (Set.ModFlags) & MethodAttributes.MemberAccessMask, set_accessor_access, set_accessor))
6661 Error_CannotChangeAccessModifiers (Set.Location, set_accessor, set_accessor_access, ".set");
6665 // When one accessor does not exist and property hides base one
6666 // we need to propagate this upwards
6667 if (set_accessor == null)
6668 set_accessor = get_accessor;
6671 // Get the less restrictive access
6673 return get_accessor_access > set_accessor_access ? get_accessor : set_accessor;
6676 public override void Emit ()
6679 // The PropertyBuilder can be null for explicit implementations, in that
6680 // case, we do not actually emit the ".property", so there is nowhere to
6681 // put the attribute
6683 if (PropertyBuilder != null) {
6684 if (OptAttributes != null)
6685 OptAttributes.Emit ();
6687 if (TypeManager.IsDynamicType (member_type))
6688 PredefinedAttributes.Get.Dynamic.EmitAttribute (PropertyBuilder);
6691 if (!Get.IsDummy)
6692 Get.Emit (Parent);
6694 if (!Set.IsDummy)
6695 Set.Emit (Parent);
6697 base.Emit ();
6700 /// <summary>
6701 /// Tests whether accessors are not in collision with some method (CS0111)
6702 /// </summary>
6703 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6705 return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
6708 public override bool IsUsed
6710 get {
6711 if (IsExplicitImpl)
6712 return true;
6714 return Get.IsUsed | Set.IsUsed;
6718 protected override void SetMemberName (MemberName new_name)
6720 base.SetMemberName (new_name);
6722 Get.UpdateName (this);
6723 Set.UpdateName (this);
6726 public override string[] ValidAttributeTargets {
6727 get {
6728 return attribute_targets;
6733 // Represents header string for documentation comment.
6735 public override string DocCommentHeader {
6736 get { return "P:"; }
6740 public class Property : PropertyBase
6742 public sealed class BackingField : Field
6744 readonly Property property;
6746 public BackingField (Property p)
6747 : base (p.Parent, p.type_name,
6748 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
6749 new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
6751 this.property = p;
6754 public override string GetSignatureForError ()
6756 return property.GetSignatureForError ();
6760 const int AllowedModifiers =
6761 Modifiers.NEW |
6762 Modifiers.PUBLIC |
6763 Modifiers.PROTECTED |
6764 Modifiers.INTERNAL |
6765 Modifiers.PRIVATE |
6766 Modifiers.STATIC |
6767 Modifiers.SEALED |
6768 Modifiers.OVERRIDE |
6769 Modifiers.ABSTRACT |
6770 Modifiers.UNSAFE |
6771 Modifiers.EXTERN |
6772 Modifiers.VIRTUAL;
6774 const int AllowedInterfaceModifiers =
6775 Modifiers.NEW;
6777 public Property (DeclSpace parent, FullNamedExpression type, int mod,
6778 MemberName name, Attributes attrs, Accessor get_block,
6779 Accessor set_block, bool define_set_first)
6780 : this (parent, type, mod, name, attrs, get_block, set_block,
6781 define_set_first, null)
6785 public Property (DeclSpace parent, FullNamedExpression type, int mod,
6786 MemberName name, Attributes attrs, Accessor get_block,
6787 Accessor set_block, bool define_set_first, Block current_block)
6788 : base (parent, type, mod,
6789 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
6790 name, attrs, define_set_first)
6792 if (get_block == null)
6793 Get = new GetMethod (this);
6794 else
6795 Get = new GetMethod (this, get_block);
6797 if (set_block == null)
6798 Set = new SetMethod (this);
6799 else
6800 Set = new SetMethod (this, set_block);
6802 if (!IsInterface && (mod & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
6803 get_block != null && get_block.Block == null &&
6804 set_block != null && set_block.Block == null) {
6805 if (RootContext.Version <= LanguageVersion.ISO_2)
6806 Report.FeatureIsNotAvailable (Location, "automatically implemented properties");
6808 Get.ModFlags |= Modifiers.COMPILER_GENERATED;
6809 Set.ModFlags |= Modifiers.COMPILER_GENERATED;
6813 void CreateAutomaticProperty ()
6815 // Create backing field
6816 Field field = new BackingField (this);
6817 if (!field.Define ())
6818 return;
6820 Parent.PartialContainer.AddField (field);
6822 FieldExpr fe = new FieldExpr (field.FieldBuilder, Location);
6823 if ((field.ModFlags & Modifiers.STATIC) == 0)
6824 fe.InstanceExpression = new CompilerGeneratedThis (fe.Type, Location);
6826 // Create get block
6827 Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
6828 Return r = new Return (fe, Location);
6829 Get.Block.AddStatement (r);
6831 // Create set block
6832 Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location);
6833 Assign a = new SimpleAssign (fe, new SimpleName ("value", Location));
6834 Set.Block.AddStatement (new StatementExpression (a));
6837 public override bool Define ()
6839 if (!base.Define ())
6840 return false;
6842 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6844 if ((Get.ModFlags & Modifiers.COMPILER_GENERATED) != 0)
6845 CreateAutomaticProperty ();
6847 if (!DefineAccessors ())
6848 return false;
6850 if (!CheckBase ())
6851 return false;
6853 // FIXME - PropertyAttributes.HasDefault ?
6855 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6856 GetFullName (MemberName), PropertyAttributes.None, MemberType, null);
6858 if (!Get.IsDummy) {
6859 PropertyBuilder.SetGetMethod (GetBuilder);
6860 Parent.MemberCache.AddMember (GetBuilder, Get);
6863 if (!Set.IsDummy) {
6864 PropertyBuilder.SetSetMethod (SetBuilder);
6865 Parent.MemberCache.AddMember (SetBuilder, Set);
6868 TypeManager.RegisterProperty (PropertyBuilder, this);
6869 Parent.MemberCache.AddMember (PropertyBuilder, this);
6870 return true;
6873 public override void Emit ()
6875 if (((Set.ModFlags | Get.ModFlags) & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) {
6876 Report.Error (842, Location,
6877 "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
6878 GetSignatureForError ());
6881 base.Emit ();
6884 protected override PropertyInfo ResolveBaseProperty ()
6886 return Parent.PartialContainer.BaseCache.FindMemberToOverride (
6887 Parent.TypeBuilder, Name, ParametersCompiled.EmptyReadOnlyParameters, null, true) as PropertyInfo;
6891 /// </summary>
6892 /// Gigantic workaround for lameness in SRE follows :
6893 /// This class derives from EventInfo and attempts to basically
6894 /// wrap around the EventBuilder so that FindMembers can quickly
6895 /// return this in it search for members
6896 /// </summary>
6897 public class MyEventBuilder : EventInfo {
6900 // We use this to "point" to our Builder which is
6901 // not really a MemberInfo
6903 EventBuilder MyBuilder;
6906 // We "catch" and wrap these methods
6908 MethodInfo raise, remove, add;
6910 EventAttributes attributes;
6911 Type declaring_type, reflected_type, event_type;
6912 string name;
6914 Event my_event;
6916 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
6918 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
6920 // And now store the values in our own fields.
6922 declaring_type = type_builder;
6924 reflected_type = type_builder;
6926 attributes = event_attr;
6927 this.name = name;
6928 my_event = ev;
6929 this.event_type = event_type;
6933 // Methods that you have to override. Note that you only need
6934 // to "implement" the variants that take the argument (those are
6935 // the "abstract" methods, the others (GetAddMethod()) are
6936 // regular.
6938 public override MethodInfo GetAddMethod (bool nonPublic)
6940 return add;
6943 public override MethodInfo GetRemoveMethod (bool nonPublic)
6945 return remove;
6948 public override MethodInfo GetRaiseMethod (bool nonPublic)
6950 return raise;
6954 // These methods make "MyEventInfo" look like a Builder
6956 public void SetRaiseMethod (MethodBuilder raiseMethod)
6958 raise = raiseMethod;
6959 MyBuilder.SetRaiseMethod (raiseMethod);
6962 public void SetRemoveOnMethod (MethodBuilder removeMethod)
6964 remove = removeMethod;
6965 MyBuilder.SetRemoveOnMethod (removeMethod);
6968 public void SetAddOnMethod (MethodBuilder addMethod)
6970 add = addMethod;
6971 MyBuilder.SetAddOnMethod (addMethod);
6974 public void SetCustomAttribute (CustomAttributeBuilder cb)
6976 MyBuilder.SetCustomAttribute (cb);
6979 public override object [] GetCustomAttributes (bool inherit)
6981 // FIXME : There's nothing which can be seemingly done here because
6982 // we have no way of getting at the custom attribute objects of the
6983 // EventBuilder !
6984 return null;
6987 public override object [] GetCustomAttributes (Type t, bool inherit)
6989 // FIXME : Same here !
6990 return null;
6993 public override bool IsDefined (Type t, bool b)
6995 return true;
6998 public override EventAttributes Attributes {
6999 get {
7000 return attributes;
7004 public override string Name {
7005 get {
7006 return name;
7010 public override Type DeclaringType {
7011 get {
7012 return declaring_type;
7016 public override Type ReflectedType {
7017 get {
7018 return reflected_type;
7022 public Type EventType {
7023 get {
7024 return event_type;
7028 public void SetUsed ()
7030 if (my_event != null) {
7031 // my_event.SetAssigned ();
7032 my_event.SetMemberIsUsed ();
7037 /// <summary>
7038 /// For case when event is declared like property (with add and remove accessors).
7039 /// </summary>
7040 public class EventProperty: Event {
7041 abstract class AEventPropertyAccessor : AEventAccessor
7043 protected AEventPropertyAccessor (Event method, Accessor accessor, string prefix):
7044 base (method, accessor, prefix)
7048 public override MethodBuilder Define (DeclSpace ds)
7050 CheckAbstractAndExtern (block != null);
7051 return base.Define (ds);
7054 public override string GetSignatureForError ()
7056 return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1);
7060 sealed class AddDelegateMethod: AEventPropertyAccessor
7062 public AddDelegateMethod (Event method, Accessor accessor):
7063 base (method, accessor, AddPrefix)
7068 sealed class RemoveDelegateMethod: AEventPropertyAccessor
7070 public RemoveDelegateMethod (Event method, Accessor accessor):
7071 base (method, accessor, RemovePrefix)
7077 static readonly string[] attribute_targets = new string [] { "event" }; // "property" target was disabled for 2.0 version
7079 public EventProperty (DeclSpace parent, FullNamedExpression type, int mod_flags,
7080 MemberName name,
7081 Attributes attrs, Accessor add, Accessor remove)
7082 : base (parent, type, mod_flags, name, attrs)
7084 Add = new AddDelegateMethod (this, add);
7085 Remove = new RemoveDelegateMethod (this, remove);
7088 public override bool Define()
7090 if (!base.Define ())
7091 return false;
7093 SetMemberIsUsed ();
7094 return true;
7097 public override string[] ValidAttributeTargets {
7098 get {
7099 return attribute_targets;
7104 /// <summary>
7105 /// Event is declared like field.
7106 /// </summary>
7107 public class EventField : Event {
7108 abstract class EventFieldAccessor : AEventAccessor
7110 protected EventFieldAccessor (Event method, string prefix)
7111 : base (method, prefix)
7115 public override void Emit (DeclSpace parent)
7117 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
7118 if (parent is Class) {
7119 MethodBuilder mb = method_data.MethodBuilder;
7120 mb.SetImplementationFlags (mb.GetMethodImplementationFlags () | MethodImplAttributes.Synchronized);
7123 // TODO: because we cannot use generics yet
7124 FieldInfo field_info = ((EventField) method).BackingField.FieldBuilder;
7125 FieldExpr f_expr = new FieldExpr (field_info, Location);
7126 if ((method.ModFlags & Modifiers.STATIC) == 0)
7127 f_expr.InstanceExpression = new CompilerGeneratedThis (field_info.FieldType, Location);
7129 block = new ToplevelBlock (Compiler, ParameterInfo, Location);
7130 block.AddStatement (new StatementExpression (
7131 new CompoundAssign (Operation,
7132 f_expr,
7133 block.GetParameterReference (ParameterInfo[0].Name, Location))));
7136 base.Emit (parent);
7139 protected abstract Binary.Operator Operation { get; }
7142 sealed class AddDelegateMethod: EventFieldAccessor
7144 public AddDelegateMethod (Event method):
7145 base (method, AddPrefix)
7149 protected override Binary.Operator Operation {
7150 get { return Binary.Operator.Addition; }
7154 sealed class RemoveDelegateMethod: EventFieldAccessor
7156 public RemoveDelegateMethod (Event method):
7157 base (method, RemovePrefix)
7161 protected override Binary.Operator Operation {
7162 get { return Binary.Operator.Subtraction; }
7167 static readonly string[] attribute_targets = new string [] { "event", "field", "method" };
7168 static readonly string[] attribute_targets_interface = new string[] { "event", "method" };
7170 public Field BackingField;
7171 public Expression Initializer;
7173 public EventField (DeclSpace parent, FullNamedExpression type, int mod_flags, MemberName name, Attributes attrs)
7174 : base (parent, type, mod_flags, name, attrs)
7176 Add = new AddDelegateMethod (this);
7177 Remove = new RemoveDelegateMethod (this);
7180 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
7182 if (a.Target == AttributeTargets.Field) {
7183 BackingField.ApplyAttributeBuilder (a, cb, pa);
7184 return;
7187 if (a.Target == AttributeTargets.Method) {
7188 int errors = Report.Errors;
7189 Add.ApplyAttributeBuilder (a, cb, pa);
7190 if (errors == Report.Errors)
7191 Remove.ApplyAttributeBuilder (a, cb, pa);
7192 return;
7195 base.ApplyAttributeBuilder (a, cb, pa);
7198 public override bool Define()
7200 if (!base.Define ())
7201 return false;
7203 if (Initializer != null && (ModFlags & Modifiers.ABSTRACT) != 0) {
7204 Report.Error (74, Location, "`{0}': abstract event cannot have an initializer",
7205 GetSignatureForError ());
7208 if (!HasBackingField) {
7209 SetMemberIsUsed ();
7210 return true;
7213 // FIXME: We are unable to detect whether generic event is used because
7214 // we are using FieldExpr instead of EventExpr for event access in that
7215 // case. When this issue will be fixed this hack can be removed.
7216 if (TypeManager.IsGenericType (MemberType))
7217 SetMemberIsUsed ();
7219 if (Add.IsInterfaceImplementation)
7220 SetMemberIsUsed ();
7222 TypeManager.RegisterEventField (EventBuilder, this);
7224 BackingField = new Field (Parent,
7225 new TypeExpression (MemberType, Location),
7226 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
7227 MemberName, null);
7229 Parent.PartialContainer.AddField (BackingField);
7230 BackingField.Initializer = Initializer;
7231 BackingField.ModFlags &= ~Modifiers.COMPILER_GENERATED;
7233 // Call define because we passed fields definition
7234 return BackingField.Define ();
7237 bool HasBackingField {
7238 get {
7239 return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0;
7243 public override string[] ValidAttributeTargets
7245 get {
7246 return HasBackingField ? attribute_targets : attribute_targets_interface;
7251 public abstract class Event : PropertyBasedMember {
7252 public abstract class AEventAccessor : AbstractPropertyEventMethod
7254 protected readonly Event method;
7255 ImplicitParameter param_attr;
7257 static readonly string[] attribute_targets = new string [] { "method", "param", "return" };
7259 public const string AddPrefix = "add_";
7260 public const string RemovePrefix = "remove_";
7262 protected AEventAccessor (Event method, string prefix)
7263 : base (method, prefix)
7265 this.method = method;
7266 this.ModFlags = method.ModFlags;
7269 protected AEventAccessor (Event method, Accessor accessor, string prefix)
7270 : base (method, accessor, prefix)
7272 this.method = method;
7273 this.ModFlags = method.ModFlags;
7276 public bool IsInterfaceImplementation {
7277 get { return method_data.implementing != null; }
7280 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
7282 if (a.IsInternalMethodImplAttribute) {
7283 method.is_external_implementation = true;
7286 base.ApplyAttributeBuilder (a, cb, pa);
7289 protected override void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
7291 if (a.Target == AttributeTargets.Parameter) {
7292 if (param_attr == null)
7293 param_attr = new ImplicitParameter (method_data.MethodBuilder);
7295 param_attr.ApplyAttributeBuilder (a, cb, pa);
7296 return;
7299 base.ApplyAttributeBuilder (a, cb, pa);
7302 public override AttributeTargets AttributeTargets {
7303 get {
7304 return AttributeTargets.Method;
7308 public override bool IsClsComplianceRequired ()
7310 return method.IsClsComplianceRequired ();
7313 public virtual MethodBuilder Define (DeclSpace parent)
7315 method_data = new MethodData (method, method.ModFlags,
7316 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
7318 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
7319 return null;
7321 MethodBuilder mb = method_data.MethodBuilder;
7322 ParameterInfo.ApplyAttributes (mb);
7323 return mb;
7326 public override Type ReturnType {
7327 get {
7328 return TypeManager.void_type;
7332 public override ObsoleteAttribute GetObsoleteAttribute ()
7334 return method.GetObsoleteAttribute ();
7337 public override string[] ValidAttributeTargets {
7338 get {
7339 return attribute_targets;
7343 public override ParametersCompiled ParameterInfo {
7344 get {
7345 return method.parameters;
7351 const int AllowedModifiers =
7352 Modifiers.NEW |
7353 Modifiers.PUBLIC |
7354 Modifiers.PROTECTED |
7355 Modifiers.INTERNAL |
7356 Modifiers.PRIVATE |
7357 Modifiers.STATIC |
7358 Modifiers.VIRTUAL |
7359 Modifiers.SEALED |
7360 Modifiers.OVERRIDE |
7361 Modifiers.UNSAFE |
7362 Modifiers.ABSTRACT |
7363 Modifiers.EXTERN;
7365 const int AllowedInterfaceModifiers =
7366 Modifiers.NEW;
7368 public AEventAccessor Add, Remove;
7369 public MyEventBuilder EventBuilder;
7370 public MethodBuilder AddBuilder, RemoveBuilder;
7372 ParametersCompiled parameters;
7374 protected Event (DeclSpace parent, FullNamedExpression type, int mod_flags, MemberName name, Attributes attrs)
7375 : base (parent, null, type, mod_flags,
7376 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
7377 name, attrs)
7381 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
7383 if ((a.HasSecurityAttribute)) {
7384 a.Error_InvalidSecurityParent ();
7385 return;
7388 EventBuilder.SetCustomAttribute (cb);
7391 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
7393 return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
7396 public override AttributeTargets AttributeTargets {
7397 get {
7398 return AttributeTargets.Event;
7402 public override bool Define ()
7404 if (!base.Define ())
7405 return false;
7407 if (!TypeManager.IsDelegateType (MemberType)) {
7408 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
7411 parameters = ParametersCompiled.CreateFullyResolved (
7412 new Parameter (null, "value", Parameter.Modifier.NONE, null, Location), MemberType);
7414 if (!CheckBase ())
7415 return false;
7417 if (TypeManager.delegate_combine_delegate_delegate == null) {
7418 TypeManager.delegate_combine_delegate_delegate = TypeManager.GetPredefinedMethod (
7419 TypeManager.delegate_type, "Combine", Location,
7420 TypeManager.delegate_type, TypeManager.delegate_type);
7422 if (TypeManager.delegate_remove_delegate_delegate == null) {
7423 TypeManager.delegate_remove_delegate_delegate = TypeManager.GetPredefinedMethod (
7424 TypeManager.delegate_type, "Remove", Location,
7425 TypeManager.delegate_type, TypeManager.delegate_type);
7429 // Now define the accessors
7432 AddBuilder = Add.Define (Parent);
7433 if (AddBuilder == null)
7434 return false;
7436 RemoveBuilder = Remove.Define (Parent);
7437 if (RemoveBuilder == null)
7438 return false;
7440 EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, EventAttributes.None, MemberType);
7441 EventBuilder.SetAddOnMethod (AddBuilder);
7442 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
7444 Parent.MemberCache.AddMember (EventBuilder, this);
7445 Parent.MemberCache.AddMember (AddBuilder, Add);
7446 Parent.MemberCache.AddMember (RemoveBuilder, Remove);
7448 return true;
7451 public override void Emit ()
7453 if (OptAttributes != null) {
7454 OptAttributes.Emit ();
7457 Add.Emit (Parent);
7458 Remove.Emit (Parent);
7460 base.Emit ();
7463 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
7465 MethodInfo mi = (MethodInfo) Parent.PartialContainer.BaseCache.FindBaseEvent (
7466 Parent.TypeBuilder, Name);
7468 if (mi == null)
7469 return null;
7471 AParametersCollection pd = TypeManager.GetParameterData (mi);
7472 base_ret_type = pd.Types [0];
7473 return mi;
7477 // Represents header string for documentation comment.
7479 public override string DocCommentHeader {
7480 get { return "E:"; }
7485 public class Indexer : PropertyBase
7487 public class GetIndexerMethod : GetMethod
7489 ParametersCompiled parameters;
7491 public GetIndexerMethod (Indexer method):
7492 base (method)
7494 this.parameters = method.parameters;
7497 public GetIndexerMethod (PropertyBase method, Accessor accessor):
7498 base (method, accessor)
7500 parameters = accessor.Parameters;
7503 public override MethodBuilder Define (DeclSpace parent)
7505 parameters.Resolve (this);
7506 return base.Define (parent);
7509 public override bool EnableOverloadChecks (MemberCore overload)
7511 if (base.EnableOverloadChecks (overload)) {
7512 overload.caching_flags |= Flags.MethodOverloadsExist;
7513 return true;
7516 return false;
7519 public override ParametersCompiled ParameterInfo {
7520 get {
7521 return parameters;
7526 public class SetIndexerMethod: SetMethod
7528 public SetIndexerMethod (Indexer method):
7529 base (method)
7531 parameters = ParametersCompiled.MergeGenerated (Compiler, method.parameters, false, parameters [0], null);
7534 public SetIndexerMethod (PropertyBase method, Accessor accessor):
7535 base (method, accessor)
7537 parameters = method.Get.IsDummy ? accessor.Parameters : accessor.Parameters.Clone ();
7540 public override bool EnableOverloadChecks (MemberCore overload)
7542 if (base.EnableOverloadChecks (overload)) {
7543 overload.caching_flags |= Flags.MethodOverloadsExist;
7544 return true;
7547 return false;
7551 const int AllowedModifiers =
7552 Modifiers.NEW |
7553 Modifiers.PUBLIC |
7554 Modifiers.PROTECTED |
7555 Modifiers.INTERNAL |
7556 Modifiers.PRIVATE |
7557 Modifiers.VIRTUAL |
7558 Modifiers.SEALED |
7559 Modifiers.OVERRIDE |
7560 Modifiers.UNSAFE |
7561 Modifiers.EXTERN |
7562 Modifiers.ABSTRACT;
7564 const int AllowedInterfaceModifiers =
7565 Modifiers.NEW;
7567 public readonly ParametersCompiled parameters;
7569 public Indexer (DeclSpace parent, FullNamedExpression type, MemberName name, int mod,
7570 ParametersCompiled parameters, Attributes attrs,
7571 Accessor get_block, Accessor set_block, bool define_set_first)
7572 : base (parent, type, mod,
7573 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
7574 name, attrs, define_set_first)
7576 this.parameters = parameters;
7578 if (get_block == null)
7579 Get = new GetIndexerMethod (this);
7580 else
7581 Get = new GetIndexerMethod (this, get_block);
7583 if (set_block == null)
7584 Set = new SetIndexerMethod (this);
7585 else
7586 Set = new SetIndexerMethod (this, set_block);
7589 protected override bool CheckForDuplications ()
7591 return Parent.MemberCache.CheckExistingMembersOverloads (this, GetFullName (MemberName), parameters, Report);
7594 public override bool Define ()
7596 if (!base.Define ())
7597 return false;
7599 if (!DefineParameters (parameters))
7600 return false;
7602 if (OptAttributes != null) {
7603 Attribute indexer_attr = OptAttributes.Search (PredefinedAttributes.Get.IndexerName);
7604 if (indexer_attr != null) {
7605 // Remove the attribute from the list because it is not emitted
7606 OptAttributes.Attrs.Remove (indexer_attr);
7608 string name = indexer_attr.GetIndexerAttributeValue ();
7609 if (name == null)
7610 return false;
7612 ShortName = name;
7614 if (IsExplicitImpl) {
7615 Report.Error (415, indexer_attr.Location,
7616 "The `IndexerName' attribute is valid only on an " +
7617 "indexer that is not an explicit interface member declaration");
7618 return false;
7621 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
7622 Report.Error (609, indexer_attr.Location,
7623 "Cannot set the `IndexerName' attribute on an indexer marked override");
7624 return false;
7629 if (InterfaceType != null) {
7630 string base_IndexerName = TypeManager.IndexerPropertyName (InterfaceType);
7631 if (base_IndexerName != Name)
7632 ShortName = base_IndexerName;
7635 if (!Parent.PartialContainer.AddMember (this) ||
7636 !Parent.PartialContainer.AddMember (Get) || !Parent.PartialContainer.AddMember (Set))
7637 return false;
7639 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
7641 if (!DefineAccessors ())
7642 return false;
7644 if (!CheckBase ())
7645 return false;
7648 // Now name the parameters
7650 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
7651 GetFullName (MemberName), PropertyAttributes.None, MemberType, parameters.GetEmitTypes ());
7653 if (!Get.IsDummy) {
7654 PropertyBuilder.SetGetMethod (GetBuilder);
7655 Parent.MemberCache.AddMember (GetBuilder, Get);
7658 if (!Set.IsDummy) {
7659 PropertyBuilder.SetSetMethod (SetBuilder);
7660 Parent.MemberCache.AddMember (SetBuilder, Set);
7663 TypeManager.RegisterIndexer (PropertyBuilder, parameters);
7664 Parent.MemberCache.AddMember (PropertyBuilder, this);
7665 return true;
7668 public override bool EnableOverloadChecks (MemberCore overload)
7670 if (overload is Indexer) {
7671 caching_flags |= Flags.MethodOverloadsExist;
7672 return true;
7675 return base.EnableOverloadChecks (overload);
7678 public override string GetDocCommentName (DeclSpace ds)
7680 return DocUtil.GetMethodDocCommentName (this, parameters, ds);
7683 public override string GetSignatureForError ()
7685 StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
7686 if (MemberName.Left != null) {
7687 sb.Append ('.');
7688 sb.Append (MemberName.Left.GetSignatureForError ());
7691 sb.Append (".this");
7692 sb.Append (parameters.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
7693 return sb.ToString ();
7696 protected override PropertyInfo ResolveBaseProperty ()
7698 return Parent.PartialContainer.BaseCache.FindMemberToOverride (
7699 Parent.TypeBuilder, Name, parameters, null, true) as PropertyInfo;
7702 protected override bool VerifyClsCompliance ()
7704 if (!base.VerifyClsCompliance ())
7705 return false;
7707 parameters.VerifyClsCompliance (this);
7708 return true;
7712 public class Operator : MethodOrOperator {
7714 const int AllowedModifiers =
7715 Modifiers.PUBLIC |
7716 Modifiers.UNSAFE |
7717 Modifiers.EXTERN |
7718 Modifiers.STATIC;
7720 public enum OpType : byte {
7722 // Unary operators
7723 LogicalNot,
7724 OnesComplement,
7725 Increment,
7726 Decrement,
7727 True,
7728 False,
7730 // Unary and Binary operators
7731 Addition,
7732 Subtraction,
7734 UnaryPlus,
7735 UnaryNegation,
7737 // Binary operators
7738 Multiply,
7739 Division,
7740 Modulus,
7741 BitwiseAnd,
7742 BitwiseOr,
7743 ExclusiveOr,
7744 LeftShift,
7745 RightShift,
7746 Equality,
7747 Inequality,
7748 GreaterThan,
7749 LessThan,
7750 GreaterThanOrEqual,
7751 LessThanOrEqual,
7753 // Implicit and Explicit
7754 Implicit,
7755 Explicit,
7757 // Just because of enum
7761 public readonly OpType OperatorType;
7763 static readonly string [] [] names;
7765 static Operator ()
7767 names = new string[(int)OpType.TOP][];
7768 names [(int) OpType.LogicalNot] = new string [] { "!", "op_LogicalNot" };
7769 names [(int) OpType.OnesComplement] = new string [] { "~", "op_OnesComplement" };
7770 names [(int) OpType.Increment] = new string [] { "++", "op_Increment" };
7771 names [(int) OpType.Decrement] = new string [] { "--", "op_Decrement" };
7772 names [(int) OpType.True] = new string [] { "true", "op_True" };
7773 names [(int) OpType.False] = new string [] { "false", "op_False" };
7774 names [(int) OpType.Addition] = new string [] { "+", "op_Addition" };
7775 names [(int) OpType.Subtraction] = new string [] { "-", "op_Subtraction" };
7776 names [(int) OpType.UnaryPlus] = new string [] { "+", "op_UnaryPlus" };
7777 names [(int) OpType.UnaryNegation] = new string [] { "-", "op_UnaryNegation" };
7778 names [(int) OpType.Multiply] = new string [] { "*", "op_Multiply" };
7779 names [(int) OpType.Division] = new string [] { "/", "op_Division" };
7780 names [(int) OpType.Modulus] = new string [] { "%", "op_Modulus" };
7781 names [(int) OpType.BitwiseAnd] = new string [] { "&", "op_BitwiseAnd" };
7782 names [(int) OpType.BitwiseOr] = new string [] { "|", "op_BitwiseOr" };
7783 names [(int) OpType.ExclusiveOr] = new string [] { "^", "op_ExclusiveOr" };
7784 names [(int) OpType.LeftShift] = new string [] { "<<", "op_LeftShift" };
7785 names [(int) OpType.RightShift] = new string [] { ">>", "op_RightShift" };
7786 names [(int) OpType.Equality] = new string [] { "==", "op_Equality" };
7787 names [(int) OpType.Inequality] = new string [] { "!=", "op_Inequality" };
7788 names [(int) OpType.GreaterThan] = new string [] { ">", "op_GreaterThan" };
7789 names [(int) OpType.LessThan] = new string [] { "<", "op_LessThan" };
7790 names [(int) OpType.GreaterThanOrEqual] = new string [] { ">=", "op_GreaterThanOrEqual" };
7791 names [(int) OpType.LessThanOrEqual] = new string [] { "<=", "op_LessThanOrEqual" };
7792 names [(int) OpType.Implicit] = new string [] { "implicit", "op_Implicit" };
7793 names [(int) OpType.Explicit] = new string [] { "explicit", "op_Explicit" };
7796 public Operator (DeclSpace parent, OpType type, FullNamedExpression ret_type,
7797 int mod_flags, ParametersCompiled parameters,
7798 ToplevelBlock block, Attributes attrs, Location loc)
7799 : base (parent, null, ret_type, mod_flags, AllowedModifiers,
7800 new MemberName (GetMetadataName (type), loc), attrs, parameters)
7802 OperatorType = type;
7803 Block = block;
7806 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
7808 if (a.Type == pa.Conditional) {
7809 Error_ConditionalAttributeIsNotValid ();
7810 return;
7813 base.ApplyAttributeBuilder (a, cb, pa);
7816 public override bool Define ()
7818 const int RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
7819 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
7820 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
7823 if (!base.Define ())
7824 return false;
7826 // imlicit and explicit operator of same types are not allowed
7827 if (OperatorType == OpType.Explicit)
7828 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Implicit), Parameters, Report);
7829 else if (OperatorType == OpType.Implicit)
7830 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Explicit), Parameters, Report);
7832 Type declaring_type = MethodData.DeclaringType;
7833 Type return_type = MemberType;
7834 Type first_arg_type = ParameterTypes [0];
7836 Type first_arg_type_unwrap = first_arg_type;
7837 if (TypeManager.IsNullableType (first_arg_type))
7838 first_arg_type_unwrap = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (first_arg_type) [0]);
7840 Type return_type_unwrap = return_type;
7841 if (TypeManager.IsNullableType (return_type))
7842 return_type_unwrap = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (return_type) [0]);
7844 if (TypeManager.IsDynamicType (return_type) || TypeManager.IsDynamicType (first_arg_type)) {
7845 Report.Error (1964, Location,
7846 "User-defined operator `{0}' cannot convert to or from the dynamic type",
7847 GetSignatureForError ());
7849 return false;
7853 // Rules for conversion operators
7855 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7856 if (first_arg_type_unwrap == return_type_unwrap && first_arg_type_unwrap == declaring_type){
7857 Report.Error (555, Location,
7858 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
7859 return false;
7862 Type conv_type;
7863 if (TypeManager.IsEqual (declaring_type, return_type) || declaring_type == return_type_unwrap) {
7864 conv_type = first_arg_type;
7865 } else if (TypeManager.IsEqual (declaring_type, first_arg_type) || declaring_type == first_arg_type_unwrap) {
7866 conv_type = return_type;
7867 } else {
7868 Report.Error (556, Location,
7869 "User-defined conversion must convert to or from the enclosing type");
7870 return false;
7874 // Because IsInterface and IsClass are not supported
7876 if (!TypeManager.IsGenericParameter (conv_type)) {
7877 if (conv_type.IsInterface) {
7878 Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
7879 GetSignatureForError ());
7880 return false;
7883 if (conv_type.IsClass) {
7884 if (TypeManager.IsSubclassOf (declaring_type, conv_type)) {
7885 Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from a base class",
7886 GetSignatureForError ());
7887 return false;
7890 if (TypeManager.IsSubclassOf (conv_type, declaring_type)) {
7891 Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from a derived class",
7892 GetSignatureForError ());
7893 return false;
7897 } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
7898 if (first_arg_type != declaring_type || Parameters.Types [1] != TypeManager.int32_type) {
7899 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");
7900 return false;
7902 } else if (Parameters.Count == 1) {
7903 // Checks for Unary operators
7905 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
7906 if (return_type != declaring_type && !TypeManager.IsSubclassOf (return_type, declaring_type)) {
7907 Report.Error (448, Location,
7908 "The return type for ++ or -- operator must be the containing type or derived from the containing type");
7909 return false;
7911 if (first_arg_type != declaring_type) {
7912 Report.Error (
7913 559, Location, "The parameter type for ++ or -- operator must be the containing type");
7914 return false;
7918 if (!TypeManager.IsEqual (first_arg_type_unwrap, declaring_type)){
7919 Report.Error (562, Location,
7920 "The parameter type of a unary operator must be the containing type");
7921 return false;
7924 if (OperatorType == OpType.True || OperatorType == OpType.False) {
7925 if (return_type != TypeManager.bool_type){
7926 Report.Error (
7927 215, Location,
7928 "The return type of operator True or False " +
7929 "must be bool");
7930 return false;
7934 } else if (!TypeManager.IsEqual (first_arg_type_unwrap, declaring_type)) {
7935 // Checks for Binary operators
7937 var second_arg_type = ParameterTypes [1];
7938 if (TypeManager.IsNullableType (second_arg_type))
7939 second_arg_type = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (second_arg_type) [0]);
7941 if (!TypeManager.IsEqual (second_arg_type, declaring_type)) {
7942 Report.Error (563, Location,
7943 "One of the parameters of a binary operator must be the containing type");
7944 return false;
7948 return true;
7951 protected override bool ResolveMemberType ()
7953 if (!base.ResolveMemberType ())
7954 return false;
7956 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
7957 return true;
7960 // Operator cannot be override
7961 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
7963 return null;
7966 public static string GetName (OpType ot)
7968 return names [(int) ot] [0];
7971 public static string GetName (string metadata_name)
7973 for (int i = 0; i < names.Length; ++i) {
7974 if (names [i] [1] == metadata_name)
7975 return names [i] [0];
7977 return null;
7980 public static string GetMetadataName (OpType ot)
7982 return names [(int) ot] [1];
7985 public static string GetMetadataName (string name)
7987 for (int i = 0; i < names.Length; ++i) {
7988 if (names [i] [0] == name)
7989 return names [i] [1];
7991 return null;
7994 public OpType GetMatchingOperator ()
7996 switch (OperatorType) {
7997 case OpType.Equality:
7998 return OpType.Inequality;
7999 case OpType.Inequality:
8000 return OpType.Equality;
8001 case OpType.True:
8002 return OpType.False;
8003 case OpType.False:
8004 return OpType.True;
8005 case OpType.GreaterThan:
8006 return OpType.LessThan;
8007 case OpType.LessThan:
8008 return OpType.GreaterThan;
8009 case OpType.GreaterThanOrEqual:
8010 return OpType.LessThanOrEqual;
8011 case OpType.LessThanOrEqual:
8012 return OpType.GreaterThanOrEqual;
8013 default:
8014 return OpType.TOP;
8018 public override string GetSignatureForError ()
8020 StringBuilder sb = new StringBuilder ();
8021 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
8022 sb.AppendFormat ("{0}.{1} operator {2}",
8023 Parent.GetSignatureForError (), GetName (OperatorType), type_name.GetSignatureForError ());
8025 else {
8026 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
8029 sb.Append (Parameters.GetSignatureForError ());
8030 return sb.ToString ();
8035 // This is used to compare method signatures
8037 struct MethodSignature {
8038 public string Name;
8039 public Type RetType;
8040 public Type [] Parameters;
8042 /// <summary>
8043 /// This delegate is used to extract methods which have the
8044 /// same signature as the argument
8045 /// </summary>
8046 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
8048 public MethodSignature (string name, Type ret_type, Type [] parameters)
8050 Name = name;
8051 RetType = ret_type;
8053 if (parameters == null)
8054 Parameters = Type.EmptyTypes;
8055 else
8056 Parameters = parameters;
8059 public override string ToString ()
8061 string pars = "";
8062 if (Parameters.Length != 0){
8063 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
8064 for (int i = 0; i < Parameters.Length; i++){
8065 sb.Append (Parameters [i]);
8066 if (i+1 < Parameters.Length)
8067 sb.Append (", ");
8069 pars = sb.ToString ();
8072 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
8075 public override int GetHashCode ()
8077 return Name.GetHashCode ();
8080 public override bool Equals (Object o)
8082 MethodSignature other = (MethodSignature) o;
8084 if (other.Name != Name)
8085 return false;
8087 if (other.RetType != RetType)
8088 return false;
8090 if (Parameters == null){
8091 if (other.Parameters == null)
8092 return true;
8093 return false;
8096 if (other.Parameters == null)
8097 return false;
8099 int c = Parameters.Length;
8100 if (other.Parameters.Length != c)
8101 return false;
8103 for (int i = 0; i < c; i++)
8104 if (other.Parameters [i] != Parameters [i])
8105 return false;
8107 return true;
8110 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
8112 MethodSignature sig = (MethodSignature) filter_criteria;
8114 if (m.Name != sig.Name)
8115 return false;
8117 Type ReturnType;
8118 MethodInfo mi = m as MethodInfo;
8119 PropertyInfo pi = m as PropertyInfo;
8121 if (mi != null)
8122 ReturnType = mi.ReturnType;
8123 else if (pi != null)
8124 ReturnType = pi.PropertyType;
8125 else
8126 return false;
8129 // we use sig.RetType == null to mean `do not check the
8130 // method return value.
8132 if (sig.RetType != null) {
8133 if (!TypeManager.IsEqual (ReturnType, sig.RetType))
8134 return false;
8137 Type [] args;
8138 if (mi != null)
8139 args = TypeManager.GetParameterData (mi).Types;
8140 else
8141 args = TypeManager.GetParameterData (pi).Types;
8142 Type [] sigp = sig.Parameters;
8144 if (args.Length != sigp.Length)
8145 return false;
8147 for (int i = args.Length - 1; i >= 0; i--)
8148 if (!TypeManager.IsEqual (args [i], sigp [i]))
8149 return false;
8151 return true;