* DataGrid.cs: remove the XXX'ed check at the top of
[mcs.git] / mcs / class.cs
blob9402ad7686d48f2a88ec06d1d8126fefe6ffd8ba
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 // Licensed under the terms of the GNU GPL
9 //
10 // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // (C) 2004 Novell, Inc
14 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
16 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
17 // have fixed a remaining problem: not every AddXXXX was adding a
18 // fully qualified name.
20 // Now everyone registers a fully qualified name in the DeclSpace as
21 // being defined instead of the partial name.
23 // Downsides: we are slower than we need to be due to the excess
24 // copies and the names being registered this way.
26 // The reason for this is that we currently depend (on the corlib
27 // bootstrap for instance) that types are fully qualified, because
28 // we dump all the types in the namespace, and we should really have
29 // types inserted into the proper namespace, so we can only store the
30 // basenames in the defined_names array.
33 #define CACHE
34 using System;
35 using System.Collections;
36 using System.Collections.Specialized;
37 using System.Reflection;
38 using System.Reflection.Emit;
39 using System.Runtime.CompilerServices;
40 using System.Runtime.InteropServices;
41 using System.Security;
42 using System.Security.Permissions;
43 using System.Text;
45 #if BOOTSTRAP_WITH_OLDLIB
46 using XmlElement = System.Object;
47 #else
48 using System.Xml;
49 #endif
51 using Mono.CompilerServices.SymbolWriter;
53 namespace Mono.CSharp {
55 public enum Kind {
56 Root,
57 Struct,
58 Class,
59 Interface,
60 Enum
63 /// <summary>
64 /// This is the base class for structs and classes.
65 /// </summary>
66 public abstract class TypeContainer : DeclSpace, IMemberContainer {
68 public class MemberCoreArrayList: ArrayList
70 /// <summary>
71 /// Defines the MemberCore objects that are in this array
72 /// </summary>
73 public virtual void DefineContainerMembers ()
75 foreach (MemberCore mc in this) {
76 try {
77 mc.Define ();
78 } catch (Exception e) {
79 throw new InternalErrorException (mc, e);
84 public virtual void Emit ()
86 foreach (MemberCore mc in this)
87 mc.Emit ();
91 public class OperatorArrayList: MemberCoreArrayList
93 TypeContainer container;
95 public OperatorArrayList (TypeContainer container)
97 this.container = container;
101 // Operator pair checking
103 class OperatorEntry
105 public int flags;
106 public Type ret_type;
107 public Type type1, type2;
108 public Operator op;
109 public Operator.OpType ot;
111 public OperatorEntry (int f, Operator o)
113 flags = f;
115 ret_type = o.MemberType;
116 Type [] pt = o.ParameterTypes;
117 type1 = pt [0];
118 type2 = pt [1];
119 op = o;
120 ot = o.OperatorType;
123 public override int GetHashCode ()
125 return ret_type.GetHashCode ();
128 public override bool Equals (object o)
130 OperatorEntry other = (OperatorEntry) o;
132 if (other.ret_type != ret_type)
133 return false;
134 if (other.type1 != type1)
135 return false;
136 if (other.type2 != type2)
137 return false;
138 return true;
143 // Checks that some operators come in pairs:
144 // == and !=
145 // > and <
146 // >= and <=
147 // true and false
149 // They are matched based on the return type and the argument types
151 void CheckPairedOperators ()
153 IDictionary pairs = new HybridDictionary ();
154 Operator true_op = null;
155 Operator false_op = null;
156 bool has_equality_or_inequality = false;
158 // Register all the operators we care about.
159 foreach (Operator op in this){
160 int reg = 0;
162 // Skip erroneous code.
163 if (op.MethodBuilder == null)
164 continue;
166 switch (op.OperatorType){
167 case Operator.OpType.Equality:
168 reg = 1;
169 has_equality_or_inequality = true;
170 break;
171 case Operator.OpType.Inequality:
172 reg = 2;
173 has_equality_or_inequality = true;
174 break;
176 case Operator.OpType.True:
177 true_op = op;
178 break;
179 case Operator.OpType.False:
180 false_op = op;
181 break;
183 case Operator.OpType.GreaterThan:
184 reg = 1; break;
185 case Operator.OpType.LessThan:
186 reg = 2; break;
188 case Operator.OpType.GreaterThanOrEqual:
189 reg = 1; break;
190 case Operator.OpType.LessThanOrEqual:
191 reg = 2; break;
193 if (reg == 0)
194 continue;
196 OperatorEntry oe = new OperatorEntry (reg, op);
198 object o = pairs [oe];
199 if (o == null)
200 pairs [oe] = oe;
201 else {
202 oe = (OperatorEntry) o;
203 oe.flags |= reg;
207 if (true_op != null){
208 if (false_op == null)
209 Report.Error (216, true_op.Location, "The operator `{0}' requires a matching operator `false' to also be defined",
210 true_op.GetSignatureForError ());
211 } else if (false_op != null)
212 Report.Error (216, false_op.Location, "The operator `{0}' requires a matching operator `true' to also be defined",
213 false_op.GetSignatureForError ());
216 // Look for the mistakes.
218 foreach (DictionaryEntry de in pairs){
219 OperatorEntry oe = (OperatorEntry) de.Key;
221 if (oe.flags == 3)
222 continue;
224 string s = "";
225 switch (oe.ot){
226 case Operator.OpType.Equality:
227 s = "!=";
228 break;
229 case Operator.OpType.Inequality:
230 s = "==";
231 break;
232 case Operator.OpType.GreaterThan:
233 s = "<";
234 break;
235 case Operator.OpType.LessThan:
236 s = ">";
237 break;
238 case Operator.OpType.GreaterThanOrEqual:
239 s = "<=";
240 break;
241 case Operator.OpType.LessThanOrEqual:
242 s = ">=";
243 break;
245 Report.Error (216, oe.op.Location,
246 "The operator `{0}' requires a matching operator `{1}' to also be defined",
247 oe.op.GetSignatureForError (), s);
250 if (has_equality_or_inequality && (RootContext.WarningLevel > 2)) {
251 if (container.Methods == null || !container.HasEquals)
252 Report.Warning (660, 2, container.Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)", container.GetSignatureForError ());
254 if (container.Methods == null || !container.HasGetHashCode)
255 Report.Warning (661, 2, container.Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()", container.GetSignatureForError ());
259 public override void DefineContainerMembers ()
261 base.DefineContainerMembers ();
262 CheckPairedOperators ();
266 [Flags]
267 enum CachedMethods {
268 Equals = 1,
269 GetHashCode = 1 << 1
273 // Whether this is a struct, class or interface
274 public readonly Kind Kind;
276 // Holds a list of classes and structures
277 protected ArrayList types;
279 MemberCoreArrayList ordered_explicit_member_list;
280 MemberCoreArrayList ordered_member_list;
282 // Holds the list of properties
283 MemberCoreArrayList properties;
285 // Holds the list of delegates
286 MemberCoreArrayList delegates;
288 // Holds the list of constructors
289 protected MemberCoreArrayList instance_constructors;
291 // Holds the list of fields
292 MemberCoreArrayList fields;
294 // Holds a list of fields that have initializers
295 protected ArrayList initialized_fields;
297 // Holds a list of static fields that have initializers
298 protected ArrayList initialized_static_fields;
300 // Holds the list of constants
301 MemberCoreArrayList constants;
303 // Holds the methods.
304 MemberCoreArrayList methods;
306 // Holds the events
307 protected MemberCoreArrayList events;
309 // Holds the indexers
310 ArrayList indexers;
312 // Holds the operators
313 MemberCoreArrayList operators;
315 // Holds the compiler generated classes
316 ArrayList compiler_generated;
319 // Pointers to the default constructor and the default static constructor
321 protected Constructor default_constructor;
322 protected Constructor default_static_constructor;
325 // Points to the first non-static field added to the container.
327 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
328 // and the first one's as good as any.
330 FieldBase first_nonstatic_field = null;
333 // This one is computed after we can distinguish interfaces
334 // from classes from the arraylist `type_bases'
336 TypeExpr base_type;
337 TypeExpr[] iface_exprs;
338 Type GenericType;
340 ArrayList type_bases;
342 bool members_resolved;
343 bool members_resolved_ok;
344 bool members_defined;
345 bool members_defined_ok;
347 // The interfaces we implement.
348 protected Type[] ifaces;
350 // The base member cache and our member cache
351 MemberCache base_cache;
352 MemberCache member_cache;
354 public const string DefaultIndexerName = "Item";
356 private bool seen_normal_indexers = false;
357 private string indexer_name = DefaultIndexerName;
359 private CachedMethods cached_method;
361 #if GMCS_SOURCE
362 GenericTypeParameterBuilder[] gen_params;
363 #endif
365 ArrayList partial_parts;
367 /// <remarks>
368 /// The pending methods that need to be implemented
369 // (interfaces or abstract methods)
370 /// </remarks>
371 PendingImplementation pending;
373 public TypeContainer (NamespaceEntry ns, DeclSpace parent, MemberName name,
374 Attributes attrs, Kind kind)
375 : base (ns, parent, name, attrs)
377 if (parent != null && parent.NamespaceEntry != ns)
378 throw new InternalErrorException ("A nested type should be in the same NamespaceEntry as its enclosing class");
380 this.Kind = kind;
381 this.PartialContainer = this;
384 public bool AddMember (MemberCore symbol)
386 return AddToContainer (symbol, symbol.MemberName.MethodName);
389 protected virtual bool AddMemberType (DeclSpace ds)
391 return AddToContainer (ds, ds.Basename);
394 public void AddConstant (Const constant)
396 if (!AddMember (constant))
397 return;
399 if (constants == null)
400 constants = new MemberCoreArrayList ();
402 constants.Add (constant);
405 public TypeContainer AddTypeContainer (TypeContainer tc)
407 if (!AddMemberType (tc))
408 return tc;
410 if (types == null)
411 types = new MemberCoreArrayList ();
412 types.Add (tc);
414 return tc;
417 public virtual TypeContainer AddPartial (TypeContainer next_part)
419 return AddPartial (next_part, next_part.Basename);
422 protected TypeContainer AddPartial (TypeContainer next_part, string name)
424 next_part.ModFlags |= Modifiers.PARTIAL;
425 TypeContainer tc = defined_names [name] as TypeContainer;
427 if (tc == null)
428 return AddTypeContainer (next_part);
430 if ((tc.ModFlags & Modifiers.PARTIAL) == 0) {
431 Report.SymbolRelatedToPreviousError (tc);
432 Error_MissingPartialModifier (next_part);
433 return tc;
436 if (tc.Kind != next_part.Kind) {
437 Report.SymbolRelatedToPreviousError (tc);
438 Report.Error (261, next_part.Location,
439 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
440 next_part.GetSignatureForError ());
441 return tc;
444 if ((tc.ModFlags & Modifiers.Accessibility) != (next_part.ModFlags & Modifiers.Accessibility) &&
445 ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 &&
446 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
447 Report.SymbolRelatedToPreviousError (tc);
448 Report.Error (262, next_part.Location,
449 "Partial declarations of `{0}' have conflicting accessibility modifiers",
450 next_part.GetSignatureForError ());
451 return tc;
454 if (tc.MemberName.IsGeneric) {
455 TypeParameter[] tc_names = tc.TypeParameters;
456 TypeParameterName[] part_names = next_part.MemberName.TypeArguments.GetDeclarations ();
458 for (int i = 0; i < tc_names.Length; ++i) {
459 if (tc_names[i].Name == part_names[i].Name)
460 continue;
462 Report.SymbolRelatedToPreviousError (part_names[i].Location, "");
463 Report.Error (264, tc.Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
464 tc.GetSignatureForError ());
465 return tc;
469 if (tc.partial_parts == null)
470 tc.partial_parts = new ArrayList (1);
472 tc.ModFlags |= next_part.ModFlags;
473 if (next_part.attributes != null) {
474 if (tc.attributes == null)
475 tc.attributes = next_part.attributes;
476 else
477 tc.attributes.AddAttributes (next_part.attributes.Attrs);
480 next_part.PartialContainer = tc;
481 tc.partial_parts.Add (next_part);
482 return tc;
485 public void AddDelegate (Delegate d)
487 if (!AddMemberType (d))
488 return;
490 if (delegates == null)
491 delegates = new MemberCoreArrayList ();
493 delegates.Add (d);
496 private void AddMemberToList (MemberCore mc, ArrayList alist, bool isexplicit)
498 if (ordered_explicit_member_list == null) {
499 ordered_explicit_member_list = new MemberCoreArrayList ();
500 ordered_member_list = new MemberCoreArrayList ();
503 if(isexplicit) {
504 ordered_explicit_member_list.Add (mc);
505 alist.Insert (0, mc);
507 else {
508 ordered_member_list.Add (mc);
509 alist.Add (mc);
514 public void AddMethod (Method method)
516 if (!AddMember (method))
517 return;
519 if (methods == null)
520 methods = new MemberCoreArrayList ();
522 if (method.MemberName.Left != null)
523 AddMemberToList (method, methods, true);
524 else
525 AddMemberToList (method, methods, false);
529 // Do not use this method: use AddMethod.
531 // This is only used by iterators.
533 public void AppendMethod (Method method)
535 if (!AddMember (method))
536 return;
538 if (methods == null)
539 methods = new MemberCoreArrayList ();
541 AddMemberToList (method, methods, false);
544 public void AddConstructor (Constructor c)
546 if (c.Name != MemberName.Name) {
547 Report.Error (1520, c.Location, "Class, struct, or interface method must have a return type");
550 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
552 if (is_static){
553 if (default_static_constructor != null) {
554 Report.SymbolRelatedToPreviousError (default_static_constructor);
555 Report.Error (111, c.Location, Error111, c.GetSignatureForError ());
556 return;
559 default_static_constructor = c;
560 } else {
561 if (c.Parameters.Empty){
562 if (default_constructor != null) {
563 Report.SymbolRelatedToPreviousError (default_constructor);
564 Report.Error (111, c.Location, Error111, c.GetSignatureForError ());
565 return;
567 default_constructor = c;
570 if (instance_constructors == null)
571 instance_constructors = new MemberCoreArrayList ();
573 instance_constructors.Add (c);
577 internal static string Error111 {
578 get {
579 return "`{0}' is already defined. Rename this member or use different parameter types";
583 public void AddField (FieldBase field)
585 if (!AddMember (field))
586 return;
588 if (fields == null)
589 fields = new MemberCoreArrayList ();
591 fields.Add (field);
593 if ((field.ModFlags & Modifiers.STATIC) != 0)
594 return;
596 if (first_nonstatic_field == null) {
597 first_nonstatic_field = field;
598 return;
601 if (Kind == Kind.Struct &&
602 first_nonstatic_field.Parent != field.Parent &&
603 RootContext.WarningLevel >= 3) {
604 Report.SymbolRelatedToPreviousError (first_nonstatic_field.Parent);
605 Report.Warning (282, 3, field.Location,
606 "struct instance field `{0}' found in different declaration from instance field `{1}'",
607 field.GetSignatureForError (), first_nonstatic_field.GetSignatureForError ());
611 public void AddProperty (Property prop)
613 if (!AddMember (prop) ||
614 !AddMember (prop.Get) || !AddMember (prop.Set))
615 return;
617 if (properties == null)
618 properties = new MemberCoreArrayList ();
620 if (prop.MemberName.Left != null)
621 AddMemberToList (prop, properties, true);
622 else
623 AddMemberToList (prop, properties, false);
626 public void AddEvent (Event e)
628 if (!AddMember (e))
629 return;
631 if (e is EventProperty) {
632 if (!AddMember (e.Add))
633 return;
635 if (!AddMember (e.Remove))
636 return;
639 if (events == null)
640 events = new MemberCoreArrayList ();
642 events.Add (e);
645 /// <summary>
646 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
647 /// </summary>
648 public void AddIndexer (Indexer i)
650 if (indexers == null)
651 indexers = new ArrayList ();
653 if (i.IsExplicitImpl)
654 AddMemberToList (i, indexers, true);
655 else
656 AddMemberToList (i, indexers, false);
659 public void AddOperator (Operator op)
661 if (!AddMember (op))
662 return;
664 if (operators == null)
665 operators = new OperatorArrayList (this);
667 operators.Add (op);
670 public void AddCompilerGeneratedClass (CompilerGeneratedClass c)
672 Report.Debug (64, "ADD COMPILER GENERATED CLASS", this, c);
674 if (compiler_generated == null)
675 compiler_generated = new ArrayList ();
677 compiler_generated.Add (c);
680 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
682 if (a.Type == TypeManager.default_member_type) {
683 if (Indexers != null) {
684 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
685 return;
689 base.ApplyAttributeBuilder (a, cb);
692 public override AttributeTargets AttributeTargets {
693 get {
694 throw new NotSupportedException ();
698 public ArrayList Types {
699 get {
700 return types;
704 public MemberCoreArrayList Methods {
705 get {
706 return methods;
710 public ArrayList Constants {
711 get {
712 return constants;
716 public ArrayList CompilerGenerated {
717 get {
718 return compiler_generated;
722 protected Type BaseType {
723 get {
724 return TypeBuilder.BaseType;
728 public ArrayList Bases {
729 get {
730 return type_bases;
733 set {
734 type_bases = value;
738 public ArrayList Fields {
739 get {
740 return fields;
744 public ArrayList InstanceConstructors {
745 get {
746 return instance_constructors;
750 public ArrayList Properties {
751 get {
752 return properties;
756 public ArrayList Events {
757 get {
758 return events;
762 public ArrayList Indexers {
763 get {
764 return indexers;
768 public ArrayList Operators {
769 get {
770 return operators;
774 public ArrayList Delegates {
775 get {
776 return delegates;
780 protected override TypeAttributes TypeAttr {
781 get {
782 return Modifiers.TypeAttr (ModFlags, IsTopLevel) | base.TypeAttr;
786 public string IndexerName {
787 get {
788 return indexers == null ? DefaultIndexerName : indexer_name;
792 public bool IsComImport {
793 get {
794 if (OptAttributes == null)
795 return false;
797 return OptAttributes.Contains (TypeManager.comimport_attr_type);
801 public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
803 if ((field.ModFlags & Modifiers.STATIC) != 0){
804 if (initialized_static_fields == null)
805 initialized_static_fields = new ArrayList (4);
807 initialized_static_fields.Add (expression);
808 } else {
809 if (initialized_fields == null)
810 initialized_fields = new ArrayList (4);
812 initialized_fields.Add (expression);
817 // Emits the instance field initializers
819 public bool EmitFieldInitializers (EmitContext ec)
821 ArrayList fields;
823 if (ec.IsStatic){
824 fields = initialized_static_fields;
825 } else {
826 fields = initialized_fields;
829 if (fields == null)
830 return true;
832 foreach (FieldInitializer f in fields) {
833 f.EmitStatement (ec);
835 return true;
838 public override string DocComment {
839 get {
840 return comment;
842 set {
843 if (value == null)
844 return;
846 comment += value;
850 public PendingImplementation PendingImplementations {
851 get { return pending; }
854 public override bool GetClsCompliantAttributeValue ()
856 if (PartialContainer != this)
857 return PartialContainer.GetClsCompliantAttributeValue ();
859 return base.GetClsCompliantAttributeValue ();
862 public void AddBasesForPart (DeclSpace part, ArrayList bases)
864 // FIXME: get rid of partial_parts and store lists of bases of each part here
865 // assumed, not verified: 'part' is in 'partial_parts'
866 ((TypeContainer) part).Bases = bases;
869 TypeExpr[] GetNormalBases (out TypeExpr base_class)
871 base_class = null;
872 if (Bases == null)
873 return null;
875 int count = Bases.Count;
876 int start = 0, i, j;
878 if (Kind == Kind.Class){
879 TypeExpr name = ((Expression) Bases [0]).ResolveAsBaseTerminal (this, false);
881 if (name == null){
882 return null;
885 if (!name.IsInterface) {
886 // base_class could be a class, struct, enum, delegate.
887 // This is validated in GetClassBases.
888 base_class = name;
889 start = 1;
893 TypeExpr [] ifaces = new TypeExpr [count-start];
895 for (i = start, j = 0; i < count; i++, j++){
896 TypeExpr resolved = ((Expression) Bases [i]).ResolveAsBaseTerminal (this, false);
897 if (resolved == null) {
898 return null;
901 ifaces [j] = resolved;
904 return ifaces.Length == 0 ? null : ifaces;
908 TypeExpr[] GetNormalPartialBases (ref TypeExpr base_class)
910 ArrayList ifaces = new ArrayList (0);
911 if (iface_exprs != null)
912 ifaces.AddRange (iface_exprs);
914 foreach (TypeContainer part in partial_parts) {
915 TypeExpr new_base_class;
916 TypeExpr[] new_ifaces = part.GetClassBases (out new_base_class);
917 if (new_base_class != TypeManager.system_object_expr) {
918 if (base_class == TypeManager.system_object_expr)
919 base_class = new_base_class;
920 else {
921 if (new_base_class != null && !new_base_class.Equals (base_class)) {
922 Report.SymbolRelatedToPreviousError (base_class.Location, "");
923 Report.Error (263, part.Location,
924 "Partial declarations of `{0}' must not specify different base classes",
925 part.GetSignatureForError ());
927 return null;
932 if (new_ifaces == null)
933 continue;
935 foreach (TypeExpr iface in new_ifaces) {
936 if (ifaces.Contains (iface))
937 continue;
939 ifaces.Add (iface);
943 if (ifaces.Count == 0)
944 return null;
946 return (TypeExpr[])ifaces.ToArray (typeof (TypeExpr));
949 /// <summary>
950 /// This function computes the Base class and also the
951 /// list of interfaces that the class or struct @c implements.
952 ///
953 /// The return value is an array (might be null) of
954 /// interfaces implemented (as Types).
955 ///
956 /// The @base_class argument is set to the base object or null
957 /// if this is `System.Object'.
958 /// </summary>
959 public virtual TypeExpr [] GetClassBases (out TypeExpr base_class)
961 TypeExpr[] ifaces = GetNormalBases (out base_class);
963 if (ifaces == null)
964 return null;
966 int count = ifaces.Length;
968 for (int i = 0; i < count; i++) {
969 TypeExpr iface = (TypeExpr) ifaces [i];
971 if (!iface.IsInterface) {
972 if (Kind != Kind.Class) {
973 // TODO: location of symbol related ....
974 Error_TypeInListIsNotInterface (Location, iface.GetSignatureForError ());
976 else if (base_class != null)
977 Report.Error (1721, Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
978 GetSignatureForError (), base_class.GetSignatureForError (), iface.GetSignatureForError ());
979 else {
980 Report.Error (1722, Location, "`{0}': Base class `{1}' must be specified as first",
981 GetSignatureForError (), iface.GetSignatureForError ());
983 return null;
986 for (int x = 0; x < i; x++) {
987 if (iface.Equals (ifaces [x])) {
988 Report.Error (528, Location,
989 "`{0}' is already listed in " +
990 "interface list", iface.GetSignatureForError ());
991 return null;
995 if ((Kind == Kind.Interface) &&
996 !iface.AsAccessible (Parent, ModFlags)) {
997 Report.Error (61, Location,
998 "Inconsistent accessibility: base " +
999 "interface `{0}' is less accessible " +
1000 "than interface `{1}'", iface.Name,
1001 Name);
1002 return null;
1005 return ifaces;
1008 bool CheckGenericInterfaces (Type[] ifaces)
1010 #if GMCS_SOURCE
1011 ArrayList already_checked = new ArrayList ();
1013 for (int i = 0; i < ifaces.Length; i++) {
1014 Type iface = ifaces [i];
1015 foreach (Type t in already_checked) {
1016 if (iface == t)
1017 continue;
1019 Type[] inferred = new Type [CountTypeParameters];
1020 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t, inferred, null))
1021 continue;
1023 Report.Error (695, Location,
1024 "`{0}' cannot implement both `{1}' and `{2}' " +
1025 "because they may unify for some type parameter substitutions",
1026 TypeManager.CSharpName (TypeBuilder), TypeManager.CSharpName (iface),
1027 TypeManager.CSharpName (t));
1028 return false;
1031 already_checked.Add (iface);
1033 #endif
1035 return true;
1038 bool error = false;
1040 protected void Error_TypeInListIsNotInterface (Location loc, string type)
1042 Report.Error (527, loc, "Type `{0}' in interface list is not an interface", type);
1045 bool CreateTypeBuilder ()
1047 try {
1048 Type default_parent = null;
1049 if (Kind == Kind.Struct)
1050 default_parent = TypeManager.value_type;
1051 else if (Kind == Kind.Enum)
1052 default_parent = TypeManager.enum_type;
1054 if (IsTopLevel){
1055 if (TypeManager.NamespaceClash (Name, Location)) {
1056 return false;
1059 ModuleBuilder builder = CodeGen.Module.Builder;
1060 TypeBuilder = builder.DefineType (
1061 Name, TypeAttr, default_parent, null);
1062 } else {
1063 TypeBuilder builder = Parent.TypeBuilder;
1065 TypeBuilder = builder.DefineNestedType (
1066 Basename, TypeAttr, default_parent, null);
1068 } catch (ArgumentException) {
1069 Report.RuntimeMissingSupport (Location, "static classes");
1070 return false;
1073 TypeManager.AddUserType (this);
1075 #if GMCS_SOURCE
1076 if (IsGeneric) {
1077 string[] param_names = new string [TypeParameters.Length];
1078 for (int i = 0; i < TypeParameters.Length; i++)
1079 param_names [i] = TypeParameters [i].Name;
1081 gen_params = TypeBuilder.DefineGenericParameters (param_names);
1083 int offset = CountTypeParameters - CurrentTypeParameters.Length;
1084 for (int i = offset; i < gen_params.Length; i++)
1085 CurrentTypeParameters [i - offset].Define (gen_params [i]);
1087 #endif
1089 return true;
1092 bool DefineBaseTypes ()
1094 iface_exprs = GetClassBases (out base_type);
1095 if (partial_parts != null) {
1096 iface_exprs = GetNormalPartialBases (ref base_type);
1100 // GetClassBases calls ResolveBaseTypeExpr() on the various type expressions involved,
1101 // which in turn should have called DefineType()s on base types if necessary.
1103 // None of the code below should trigger DefineType()s on classes that we depend on.
1104 // Thus, we are eligible to be on the topological sort `type_container_resolve_order'.
1106 // Let's do it as soon as possible, since code below can call DefineType() on classes
1107 // that depend on us to be populated before they are.
1109 if (!(this is CompilerGeneratedClass))
1110 RootContext.RegisterOrder (this);
1112 if (IsGeneric && base_type != null && TypeManager.IsAttributeType (base_type.Type)) {
1113 Report.Error (698, base_type.Location,
1114 "A generic type cannot derive from `{0}' because it is an attribute class",
1115 base_type.Name);
1116 return false;
1119 if (!CheckRecursiveDefinition (this))
1120 return false;
1122 if (base_type != null) {
1123 TypeBuilder.SetParent (base_type.Type);
1125 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (base_type.Type);
1126 if (obsolete_attr != null && !IsInObsoleteScope)
1127 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), Location);
1130 // add interfaces that were not added at type creation
1131 if (iface_exprs != null) {
1132 ifaces = TypeManager.ExpandInterfaces (iface_exprs);
1133 if (ifaces == null)
1134 return false;
1136 foreach (Type itype in ifaces)
1137 TypeBuilder.AddInterfaceImplementation (itype);
1139 foreach (TypeExpr ie in iface_exprs) {
1140 ObsoleteAttribute oa = AttributeTester.GetObsoleteAttribute (ie.Type);
1141 if ((oa != null) && !IsInObsoleteScope)
1142 AttributeTester.Report_ObsoleteMessage (
1143 oa, ie.GetSignatureForError (), Location);
1146 if (!CheckGenericInterfaces (ifaces))
1147 return false;
1149 TypeManager.RegisterBuilder (TypeBuilder, ifaces);
1152 return true;
1156 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1158 public TypeBuilder CreateType ()
1160 if (TypeBuilder != null)
1161 return TypeBuilder;
1163 if (error)
1164 return null;
1166 if (!CreateTypeBuilder ()) {
1167 error = true;
1168 return null;
1171 if (partial_parts != null) {
1172 foreach (TypeContainer part in partial_parts)
1173 part.TypeBuilder = TypeBuilder;
1176 if (Types != null) {
1177 foreach (TypeContainer tc in Types) {
1178 if (tc.CreateType () == null) {
1179 error = true;
1180 return null;
1185 return TypeBuilder;
1188 bool type_defined;
1190 public override TypeBuilder DefineType ()
1192 if (error)
1193 return null;
1194 if (type_defined)
1195 return TypeBuilder;
1197 type_defined = true;
1199 if (CreateType () == null) {
1200 error = true;
1201 return null;
1204 if (!DefineBaseTypes ()) {
1205 error = true;
1206 return null;
1209 if (!(this is CompilerGeneratedClass)) {
1210 if (!ResolveMembers ()) {
1211 error = true;
1212 return null;
1216 if (!DefineNestedTypes ()) {
1217 error = true;
1218 return null;
1221 return TypeBuilder;
1224 public bool ResolveMembers ()
1226 if (members_resolved)
1227 return members_resolved_ok;
1229 members_resolved_ok = DoResolveMembers ();
1230 members_resolved = true;
1232 return members_resolved_ok;
1235 protected virtual bool DoResolveMembers ()
1237 if (methods != null) {
1238 foreach (Method method in methods) {
1239 if (!method.ResolveMembers ())
1240 return false;
1244 if (instance_constructors != null) {
1245 foreach (Constructor c in instance_constructors) {
1246 if (!c.ResolveMembers ())
1247 return false;
1251 if (default_static_constructor != null) {
1252 if (!default_static_constructor.ResolveMembers ())
1253 return false;
1256 if (operators != null) {
1257 foreach (Operator o in operators) {
1258 if (!o.ResolveMembers ())
1259 return false;
1263 if (properties != null) {
1264 foreach (PropertyBase p in properties) {
1265 if (!p.Get.IsDummy && !p.Get.ResolveMembers ())
1266 return false;
1267 if (!p.Set.IsDummy && !p.Set.ResolveMembers ())
1268 return false;
1272 if (indexers != null) {
1273 foreach (PropertyBase p in indexers) {
1274 if (!p.Get.IsDummy && !p.Get.ResolveMembers ())
1275 return false;
1276 if (!p.Set.IsDummy && !p.Set.ResolveMembers ())
1277 return false;
1281 if (events != null) {
1282 foreach (Event e in events) {
1283 if (!e.Add.ResolveMembers ())
1284 return false;
1285 if (!e.Remove.ResolveMembers ())
1286 return false;
1290 if (compiler_generated != null) {
1291 foreach (CompilerGeneratedClass c in compiler_generated) {
1292 if (c.DefineType () == null)
1293 return false;
1297 return true;
1300 Constraints [] constraints;
1301 public override void SetParameterInfo (ArrayList constraints_list)
1303 if (PartialContainer == this) {
1304 base.SetParameterInfo (constraints_list);
1305 return;
1308 if (constraints_list == null)
1309 return;
1311 constraints = new Constraints [PartialContainer.CountCurrentTypeParameters];
1313 TypeParameter[] current_params = PartialContainer.CurrentTypeParameters;
1314 for (int i = 0; i < constraints.Length; i++) {
1315 foreach (Constraints constraint in constraints_list) {
1316 if (constraint.TypeParameter == current_params [i].Name) {
1317 constraints [i] = constraint;
1318 break;
1324 bool UpdateTypeParameterConstraints ()
1326 if (constraints == null)
1327 return true;
1329 TypeParameter[] current_params = PartialContainer.CurrentTypeParameters;
1330 for (int i = 0; i < current_params.Length; i++) {
1331 if (!current_params [i].UpdateConstraints (this, constraints [i])) {
1332 Report.SymbolRelatedToPreviousError (Location, "");
1333 Report.Error (265, PartialContainer.Location,
1334 "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'",
1335 PartialContainer.GetSignatureForError (), current_params [i].Name);
1336 return false;
1340 return true;
1343 public bool ResolveType ()
1345 if (!DoResolveType ())
1346 return false;
1348 if (compiler_generated != null) {
1349 foreach (CompilerGeneratedClass c in compiler_generated)
1350 if (!c.ResolveType ())
1351 return false;
1354 return true;
1357 protected virtual bool DoResolveType ()
1359 if ((base_type != null) &&
1360 (base_type.ResolveAsTypeTerminal (this, false) == null)) {
1361 error = true;
1362 return false;
1365 if (!IsGeneric)
1366 return true;
1368 if (PartialContainer != this)
1369 throw new InternalErrorException ();
1371 TypeExpr current_type = null;
1373 foreach (TypeParameter type_param in CurrentTypeParameters) {
1374 if (!type_param.Resolve (this)) {
1375 error = true;
1376 return false;
1380 if (partial_parts != null) {
1381 foreach (TypeContainer part in partial_parts) {
1382 if (!part.UpdateTypeParameterConstraints ()) {
1383 error = true;
1384 return false;
1389 foreach (TypeParameter type_param in TypeParameters) {
1390 if (!type_param.DefineType (this)) {
1391 error = true;
1392 return false;
1396 current_type = new ConstructedType (TypeBuilder, TypeParameters, Location);
1398 foreach (TypeParameter type_param in TypeParameters)
1399 if (!type_param.CheckDependencies ()) {
1400 error = true;
1401 return false;
1404 if (current_type != null) {
1405 current_type = current_type.ResolveAsTypeTerminal (this, false);
1406 if (current_type == null) {
1407 error = true;
1408 return false;
1411 CurrentType = current_type.Type;
1414 return true;
1417 protected virtual bool DefineNestedTypes ()
1419 if (Types != null) {
1420 foreach (TypeContainer tc in Types)
1421 if (tc.DefineType () == null)
1422 return false;
1425 if (Delegates != null) {
1426 foreach (Delegate d in Delegates)
1427 if (d.DefineType () == null)
1428 return false;
1431 return true;
1434 TypeContainer InTransit;
1436 protected bool CheckRecursiveDefinition (TypeContainer tc)
1438 if (InTransit != null) {
1439 Report.SymbolRelatedToPreviousError (this);
1440 if (this is Interface)
1441 Report.Error (
1442 529, tc.Location, "Inherited interface `{0}' causes a " +
1443 "cycle in the interface hierarchy of `{1}'",
1444 GetSignatureForError (), tc.GetSignatureForError ());
1445 else
1446 Report.Error (
1447 146, tc.Location, "Circular base class dependency " +
1448 "involving `{0}' and `{1}'",
1449 tc.GetSignatureForError (), GetSignatureForError ());
1450 return false;
1453 InTransit = tc;
1455 if (base_type != null) {
1456 Type t = TypeManager.DropGenericTypeArguments (base_type.Type);
1457 TypeContainer ptc = TypeManager.LookupTypeContainer (t);
1458 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1459 return false;
1462 if (iface_exprs != null) {
1463 foreach (TypeExpr iface in iface_exprs) {
1464 Type itype = TypeManager.DropGenericTypeArguments (iface.Type);
1465 TypeContainer ptc = TypeManager.LookupTypeContainer (itype);
1466 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1467 return false;
1471 if (!IsTopLevel && !Parent.PartialContainer.CheckRecursiveDefinition (this))
1472 return false;
1474 InTransit = null;
1475 return true;
1478 public static void Error_KeywordNotAllowed (Location loc)
1480 Report.Error (1530, loc, "Keyword `new' is not allowed on namespace elements");
1483 /// <summary>
1484 /// Populates our TypeBuilder with fields and methods
1485 /// </summary>
1486 public override bool DefineMembers ()
1488 if (members_defined)
1489 return members_defined_ok;
1491 if (!base.DefineMembers ())
1492 return false;
1494 members_defined_ok = DoDefineMembers ();
1495 members_defined = true;
1497 return members_defined_ok;
1500 protected virtual bool DoDefineMembers ()
1502 if (iface_exprs != null) {
1503 foreach (TypeExpr iface in iface_exprs) {
1504 ConstructedType ct = iface as ConstructedType;
1505 if ((ct != null) && !ct.CheckConstraints (this))
1506 return false;
1510 if (base_type != null) {
1511 ConstructedType ct = base_type as ConstructedType;
1512 if ((ct != null) && !ct.CheckConstraints (this))
1513 return false;
1516 if (!IsTopLevel) {
1517 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Basename, false);
1518 if (conflict_symbol == null) {
1519 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0))
1520 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
1521 } else {
1522 if ((ModFlags & Modifiers.NEW) == 0) {
1523 Report.SymbolRelatedToPreviousError (conflict_symbol);
1524 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
1525 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
1530 DefineContainerMembers (constants);
1531 DefineContainerMembers (fields);
1533 if (Kind == Kind.Struct || Kind == Kind.Class) {
1534 pending = PendingImplementation.GetPendingImplementations (this);
1538 // Constructors are not in the defined_names array
1540 DefineContainerMembers (instance_constructors);
1542 DefineContainerMembers (events);
1543 DefineContainerMembers (ordered_explicit_member_list);
1544 DefineContainerMembers (ordered_member_list);
1546 DefineContainerMembers (operators);
1547 DefineContainerMembers (delegates);
1549 ComputeIndexerName();
1550 CheckEqualsAndGetHashCode();
1552 if (CurrentType != null) {
1553 GenericType = CurrentType;
1556 #if CACHE
1557 member_cache = new MemberCache (this);
1558 if (partial_parts != null) {
1559 foreach (TypeContainer part in partial_parts)
1560 part.member_cache = member_cache;
1562 #endif
1564 return true;
1567 protected virtual void DefineContainerMembers (MemberCoreArrayList mcal)
1569 if (mcal != null)
1570 mcal.DefineContainerMembers ();
1573 protected virtual void ComputeIndexerName ()
1575 if (indexers == null)
1576 return;
1578 string class_indexer_name = null;
1581 // If there's both an explicit and an implicit interface implementation, the
1582 // explicit one actually implements the interface while the other one is just
1583 // a normal indexer. See bug #37714.
1586 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
1587 foreach (Indexer i in indexers) {
1588 if (i.InterfaceType != null) {
1589 if (seen_normal_indexers)
1590 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
1591 continue;
1594 seen_normal_indexers = true;
1596 if (class_indexer_name == null) {
1597 class_indexer_name = i.ShortName;
1598 continue;
1601 if (i.ShortName != class_indexer_name)
1602 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");
1605 if (class_indexer_name != null)
1606 indexer_name = class_indexer_name;
1609 protected virtual void EmitIndexerName ()
1611 if (!seen_normal_indexers)
1612 return;
1614 CustomAttributeBuilder cb = new CustomAttributeBuilder (TypeManager.default_member_ctor, new string [] { IndexerName });
1615 TypeBuilder.SetCustomAttribute (cb);
1618 protected virtual void CheckEqualsAndGetHashCode ()
1620 if (methods == null)
1621 return;
1623 if (HasEquals && !HasGetHashCode) {
1624 Report.Warning (659, 3, this.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", this.GetSignatureForError ());
1628 public override bool Define ()
1630 if (compiler_generated != null) {
1631 foreach (CompilerGeneratedClass c in compiler_generated) {
1632 if (!c.Define ())
1633 return false;
1637 return true;
1640 public MemberInfo FindBaseMemberWithSameName (string name, bool ignore_methods)
1642 return BaseCache == null ? null : BaseCache.FindMemberWithSameName (name, ignore_methods, null);
1645 /// <summary>
1646 /// This function is based by a delegate to the FindMembers routine
1647 /// </summary>
1648 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1650 return true;
1653 /// <summary>
1654 /// This filter is used by FindMembers, and we just keep
1655 /// a global for the filter to `AlwaysAccept'
1656 /// </summary>
1657 static MemberFilter accepting_filter;
1660 static TypeContainer ()
1662 accepting_filter = new MemberFilter (AlwaysAccept);
1665 public MethodInfo[] GetMethods ()
1667 ArrayList members = new ArrayList ();
1669 DefineMembers ();
1671 if (methods != null) {
1672 int len = methods.Count;
1673 for (int i = 0; i < len; i++) {
1674 Method m = (Method) methods [i];
1676 members.Add (m.MethodBuilder);
1680 if (operators != null) {
1681 int len = operators.Count;
1682 for (int i = 0; i < len; i++) {
1683 Operator o = (Operator) operators [i];
1685 members.Add (o.MethodBuilder);
1689 if (properties != null) {
1690 int len = properties.Count;
1691 for (int i = 0; i < len; i++) {
1692 Property p = (Property) properties [i];
1694 if (p.GetBuilder != null)
1695 members.Add (p.GetBuilder);
1696 if (p.SetBuilder != null)
1697 members.Add (p.SetBuilder);
1701 if (indexers != null) {
1702 int len = indexers.Count;
1703 for (int i = 0; i < len; i++) {
1704 Indexer ix = (Indexer) indexers [i];
1706 if (ix.GetBuilder != null)
1707 members.Add (ix.GetBuilder);
1708 if (ix.SetBuilder != null)
1709 members.Add (ix.SetBuilder);
1713 if (events != null) {
1714 int len = events.Count;
1715 for (int i = 0; i < len; i++) {
1716 Event e = (Event) events [i];
1718 if (e.AddBuilder != null)
1719 members.Add (e.AddBuilder);
1720 if (e.RemoveBuilder != null)
1721 members.Add (e.RemoveBuilder);
1725 MethodInfo[] retMethods = new MethodInfo [members.Count];
1726 members.CopyTo (retMethods, 0);
1727 return retMethods;
1730 // Indicated whether container has StructLayout attribute set Explicit
1731 public bool HasExplicitLayout {
1732 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
1733 set { caching_flags |= Flags.HasExplicitLayout; }
1737 // Return the nested type with name @name. Ensures that the nested type
1738 // is defined if necessary. Do _not_ use this when you have a MemberCache handy.
1740 public Type FindNestedType (string name)
1742 if (PartialContainer != this)
1743 throw new InternalErrorException ("should not happen");
1745 ArrayList [] lists = { types, delegates };
1747 for (int j = 0; j < lists.Length; ++j) {
1748 ArrayList list = lists [j];
1749 if (list == null)
1750 continue;
1752 int len = list.Count;
1753 for (int i = 0; i < len; ++i) {
1754 DeclSpace ds = (DeclSpace) list [i];
1755 if (ds.Basename == name) {
1756 return ds.DefineType ();
1761 return null;
1764 private void FindMembers_NestedTypes (int modflags,
1765 BindingFlags bf, MemberFilter filter, object criteria,
1766 ref ArrayList members)
1768 ArrayList [] lists = { types, delegates };
1770 for (int j = 0; j < lists.Length; ++j) {
1771 ArrayList list = lists [j];
1772 if (list == null)
1773 continue;
1775 int len = list.Count;
1776 for (int i = 0; i < len; i++) {
1777 DeclSpace ds = (DeclSpace) list [i];
1779 if ((ds.ModFlags & modflags) == 0)
1780 continue;
1782 TypeBuilder tb = ds.TypeBuilder;
1783 if (tb == null) {
1784 if (!(criteria is string) || ds.Basename.Equals (criteria))
1785 tb = ds.DefineType ();
1788 if (tb != null && (filter (tb, criteria) == true)) {
1789 if (members == null)
1790 members = new ArrayList ();
1792 members.Add (tb);
1798 /// <summary>
1799 /// This method returns the members of this type just like Type.FindMembers would
1800 /// Only, we need to use this for types which are _being_ defined because MS'
1801 /// implementation can't take care of that.
1802 /// </summary>
1804 // FIXME: return an empty static array instead of null, that cleans up
1805 // some code and is consistent with some coding conventions I just found
1806 // out existed ;-)
1809 // Notice that in various cases we check if our field is non-null,
1810 // something that would normally mean that there was a bug elsewhere.
1812 // The problem happens while we are defining p-invoke methods, as those
1813 // will trigger a FindMembers, but this happens before things are defined
1815 // Since the whole process is a no-op, it is fine to check for null here.
1817 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1818 MemberFilter filter, object criteria)
1820 ArrayList members = null;
1822 int modflags = 0;
1823 if ((bf & BindingFlags.Public) != 0)
1824 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1825 Modifiers.INTERNAL;
1826 if ((bf & BindingFlags.NonPublic) != 0)
1827 modflags |= Modifiers.PRIVATE;
1829 int static_mask = 0, static_flags = 0;
1830 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1831 case BindingFlags.Static:
1832 static_mask = static_flags = Modifiers.STATIC;
1833 break;
1835 case BindingFlags.Instance:
1836 static_mask = Modifiers.STATIC;
1837 static_flags = 0;
1838 break;
1840 default:
1841 static_mask = static_flags = 0;
1842 break;
1845 Timer.StartTimer (TimerType.TcFindMembers);
1847 if (filter == null)
1848 filter = accepting_filter;
1850 if ((mt & MemberTypes.Field) != 0) {
1851 if (fields != null) {
1852 int len = fields.Count;
1853 for (int i = 0; i < len; i++) {
1854 FieldBase f = (FieldBase) fields [i];
1856 if ((f.ModFlags & modflags) == 0)
1857 continue;
1858 if ((f.ModFlags & static_mask) != static_flags)
1859 continue;
1861 FieldBuilder fb = f.FieldBuilder;
1862 if (fb != null && filter (fb, criteria) == true) {
1863 if (members == null)
1864 members = new ArrayList ();
1866 members.Add (fb);
1871 if (constants != null) {
1872 int len = constants.Count;
1873 for (int i = 0; i < len; i++) {
1874 Const con = (Const) constants [i];
1876 if ((con.ModFlags & modflags) == 0)
1877 continue;
1878 if ((con.ModFlags & static_mask) != static_flags)
1879 continue;
1881 FieldBuilder fb = con.FieldBuilder;
1882 if (fb == null) {
1883 if (con.Define ())
1884 fb = con.FieldBuilder;
1886 if (fb != null && filter (fb, criteria) == true) {
1887 if (members == null)
1888 members = new ArrayList ();
1890 members.Add (fb);
1896 if ((mt & MemberTypes.Method) != 0) {
1897 if (methods != null) {
1898 int len = methods.Count;
1899 for (int i = 0; i < len; i++) {
1900 Method m = (Method) methods [i];
1902 if ((m.ModFlags & modflags) == 0)
1903 continue;
1904 if ((m.ModFlags & static_mask) != static_flags)
1905 continue;
1907 MethodBuilder mb = m.MethodBuilder;
1909 if (mb != null && filter (mb, criteria) == true) {
1910 if (members == null)
1911 members = new ArrayList ();
1913 members.Add (mb);
1918 if (operators != null) {
1919 int len = operators.Count;
1920 for (int i = 0; i < len; i++) {
1921 Operator o = (Operator) operators [i];
1923 if ((o.ModFlags & modflags) == 0)
1924 continue;
1925 if ((o.ModFlags & static_mask) != static_flags)
1926 continue;
1928 MethodBuilder ob = o.MethodBuilder;
1929 if (ob != null && filter (ob, criteria) == true) {
1930 if (members == null)
1931 members = new ArrayList ();
1933 members.Add (ob);
1938 if (events != null) {
1939 foreach (Event e in events) {
1940 if ((e.ModFlags & modflags) == 0)
1941 continue;
1942 if ((e.ModFlags & static_mask) != static_flags)
1943 continue;
1945 MethodBuilder b = e.AddBuilder;
1946 if (b != null && filter (b, criteria)) {
1947 if (members == null)
1948 members = new ArrayList (4);
1950 members.Add (b);
1953 b = e.RemoveBuilder;
1954 if (b != null && filter (b, criteria)) {
1955 if (members == null)
1956 members = new ArrayList (4);
1958 members.Add (b);
1963 if (properties != null) {
1964 int len = properties.Count;
1965 for (int i = 0; i < len; i++) {
1966 Property p = (Property) properties [i];
1968 if ((p.ModFlags & modflags) == 0)
1969 continue;
1970 if ((p.ModFlags & static_mask) != static_flags)
1971 continue;
1973 MethodBuilder b;
1975 b = p.GetBuilder;
1976 if (b != null && filter (b, criteria) == true) {
1977 if (members == null)
1978 members = new ArrayList ();
1980 members.Add (b);
1983 b = p.SetBuilder;
1984 if (b != null && filter (b, criteria) == true) {
1985 if (members == null)
1986 members = new ArrayList ();
1988 members.Add (b);
1993 if (indexers != null) {
1994 int len = indexers.Count;
1995 for (int i = 0; i < len; i++) {
1996 Indexer ix = (Indexer) indexers [i];
1998 if ((ix.ModFlags & modflags) == 0)
1999 continue;
2000 if ((ix.ModFlags & static_mask) != static_flags)
2001 continue;
2003 MethodBuilder b;
2005 b = ix.GetBuilder;
2006 if (b != null && filter (b, criteria) == true) {
2007 if (members == null)
2008 members = new ArrayList ();
2010 members.Add (b);
2013 b = ix.SetBuilder;
2014 if (b != null && filter (b, criteria) == true) {
2015 if (members == null)
2016 members = new ArrayList ();
2018 members.Add (b);
2024 if ((mt & MemberTypes.Event) != 0) {
2025 if (events != null) {
2026 int len = events.Count;
2027 for (int i = 0; i < len; i++) {
2028 Event e = (Event) events [i];
2030 if ((e.ModFlags & modflags) == 0)
2031 continue;
2032 if ((e.ModFlags & static_mask) != static_flags)
2033 continue;
2035 MemberInfo eb = e.EventBuilder;
2036 if (eb != null && filter (eb, criteria) == true) {
2037 if (members == null)
2038 members = new ArrayList ();
2040 members.Add (e.EventBuilder);
2046 if ((mt & MemberTypes.Property) != 0){
2047 if (properties != null) {
2048 int len = properties.Count;
2049 for (int i = 0; i < len; i++) {
2050 Property p = (Property) properties [i];
2052 if ((p.ModFlags & modflags) == 0)
2053 continue;
2054 if ((p.ModFlags & static_mask) != static_flags)
2055 continue;
2057 MemberInfo pb = p.PropertyBuilder;
2058 if (pb != null && filter (pb, criteria) == true) {
2059 if (members == null)
2060 members = new ArrayList ();
2062 members.Add (p.PropertyBuilder);
2067 if (indexers != null) {
2068 int len = indexers.Count;
2069 for (int i = 0; i < len; i++) {
2070 Indexer ix = (Indexer) indexers [i];
2072 if ((ix.ModFlags & modflags) == 0)
2073 continue;
2074 if ((ix.ModFlags & static_mask) != static_flags)
2075 continue;
2077 MemberInfo ib = ix.PropertyBuilder;
2078 if (ib != null && filter (ib, criteria) == true) {
2079 if (members == null)
2080 members = new ArrayList ();
2082 members.Add (ix.PropertyBuilder);
2088 if ((mt & MemberTypes.NestedType) != 0)
2089 FindMembers_NestedTypes (modflags, bf, filter, criteria, ref members);
2091 if ((mt & MemberTypes.Constructor) != 0){
2092 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
2093 int len = instance_constructors.Count;
2094 for (int i = 0; i < len; i++) {
2095 Constructor c = (Constructor) instance_constructors [i];
2097 ConstructorBuilder cb = c.ConstructorBuilder;
2098 if (cb != null && filter (cb, criteria) == true) {
2099 if (members == null)
2100 members = new ArrayList ();
2102 members.Add (cb);
2107 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
2108 ConstructorBuilder cb =
2109 default_static_constructor.ConstructorBuilder;
2111 if (cb != null && filter (cb, criteria) == true) {
2112 if (members == null)
2113 members = new ArrayList ();
2115 members.Add (cb);
2121 // Lookup members in base if requested.
2123 if ((bf & BindingFlags.DeclaredOnly) == 0) {
2124 if (TypeBuilder.BaseType != null) {
2125 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
2126 if (list.Count > 0) {
2127 if (members == null)
2128 members = new ArrayList ();
2130 members.AddRange (list);
2135 Timer.StopTimer (TimerType.TcFindMembers);
2137 if (members == null)
2138 return MemberList.Empty;
2139 else
2140 return new MemberList (members);
2143 public override MemberCache MemberCache {
2144 get {
2145 return member_cache;
2149 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
2150 MemberFilter filter, object criteria)
2152 DeclSpace ds = TypeManager.LookupDeclSpace (t);
2154 if (ds != null)
2155 return ds.FindMembers (mt, bf, filter, criteria);
2156 else
2157 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
2160 /// <summary>
2161 /// Emits the values for the constants
2162 /// </summary>
2163 public void EmitConstants ()
2165 if (constants != null)
2166 foreach (Const con in constants)
2167 con.Emit ();
2168 return;
2171 static void CheckMemberUsage (MemberCoreArrayList al, string member_type)
2173 if (al == null)
2174 return;
2176 foreach (MemberCore mc in al) {
2177 if ((mc.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
2178 continue;
2180 if (!mc.IsUsed) {
2181 Report.Warning (169, 3, mc.Location, "The private {0} `{1}' is never used", member_type, mc.GetSignatureForError ());
2186 public virtual void VerifyMembers ()
2189 // Check for internal or private fields that were never assigned
2191 if (RootContext.WarningLevel >= 3) {
2192 CheckMemberUsage (properties, "property");
2193 CheckMemberUsage (methods, "method");
2194 CheckMemberUsage (constants, "constant");
2196 if (fields != null){
2197 foreach (FieldBase f in fields) {
2198 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
2199 continue;
2201 if (!f.IsUsed){
2202 if ((f.caching_flags & Flags.IsAssigned) == 0)
2203 Report.Warning (169, 3, f.Location, "The private field `{0}' is never used", f.GetSignatureForError ());
2204 else {
2205 #if NET_2_0
2206 const int error_code = 414;
2207 #else
2208 const int error_code = 169;
2209 #endif
2210 Report.Warning (error_code, 3, f.Location, "The private field `{0}' is assigned but its value is never used",
2211 f.GetSignatureForError ());
2213 continue;
2217 // Only report 649 on level 4
2219 if (RootContext.WarningLevel < 4)
2220 continue;
2222 if ((f.caching_flags & Flags.IsAssigned) != 0)
2223 continue;
2225 Constant c = New.Constantify (f.Type.Type);
2226 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value `{1}'",
2227 f.GetSignatureForError (), c == null ? "null" : c.AsString ());
2233 // TODO: move to ClassOrStruct
2234 void EmitConstructors ()
2236 if (instance_constructors == null)
2237 return;
2239 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && RootContext.VerifyClsCompliance && IsClsComplianceRequired ()) {
2240 bool has_compliant_args = false;
2242 foreach (Constructor c in instance_constructors) {
2243 try {
2244 c.Emit ();
2246 catch (Exception e) {
2247 throw new InternalErrorException (c, e);
2250 if (has_compliant_args)
2251 continue;
2253 has_compliant_args = c.HasCompliantArgs;
2255 if (!has_compliant_args)
2256 Report.Error (3015, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2257 } else {
2258 foreach (Constructor c in instance_constructors) {
2259 try {
2260 c.Emit ();
2262 catch (Exception e) {
2263 throw new InternalErrorException (c, e);
2269 /// <summary>
2270 /// Emits the code, this step is performed after all
2271 /// the types, enumerations, constructors
2272 /// </summary>
2273 public virtual void EmitType ()
2275 if (OptAttributes != null)
2276 OptAttributes.Emit ();
2278 #if GMCS_SOURCE
2279 if (IsGeneric) {
2280 int offset = CountTypeParameters - CurrentTypeParameters.Length;
2281 for (int i = offset; i < gen_params.Length; i++)
2282 CurrentTypeParameters [i - offset].EmitAttributes ();
2284 #endif
2287 // Structs with no fields need to have at least one byte.
2288 // The right thing would be to set the PackingSize in a DefineType
2289 // but there are no functions that allow interfaces *and* the size to
2290 // be specified.
2293 if (Kind == Kind.Struct && first_nonstatic_field == null){
2294 FieldBuilder fb = TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
2295 FieldAttributes.Private);
2297 if (HasExplicitLayout){
2298 object [] ctor_args = new object [1];
2299 ctor_args [0] = 0;
2301 CustomAttributeBuilder cba = new CustomAttributeBuilder (
2302 TypeManager.field_offset_attribute_ctor, ctor_args);
2303 fb.SetCustomAttribute (cba);
2307 Emit ();
2309 EmitConstructors ();
2311 // Can not continue if constants are broken
2312 EmitConstants ();
2313 if (Report.Errors > 0)
2314 return;
2316 if (default_static_constructor != null)
2317 default_static_constructor.Emit ();
2319 if (methods != null){
2320 for (int i = 0; i < methods.Count; ++i)
2321 ((Method)methods[i]).Emit ();
2324 if (operators != null)
2325 foreach (Operator o in operators)
2326 o.Emit ();
2328 if (properties != null)
2329 foreach (Property p in properties)
2330 p.Emit ();
2332 if (indexers != null) {
2333 foreach (Indexer indx in indexers)
2334 indx.Emit ();
2335 EmitIndexerName ();
2338 if (fields != null)
2339 foreach (FieldBase f in fields)
2340 f.Emit ();
2342 if (events != null){
2343 foreach (Event e in Events)
2344 e.Emit ();
2347 if (delegates != null) {
2348 foreach (Delegate d in Delegates) {
2349 d.Emit ();
2353 if (pending != null)
2354 if (pending.VerifyPendingMethods ())
2355 return;
2357 if (Report.Errors > 0)
2358 return;
2360 if (compiler_generated != null) {
2361 foreach (CompilerGeneratedClass c in compiler_generated) {
2362 if (!c.DefineMembers ())
2363 throw new InternalErrorException ();
2365 foreach (CompilerGeneratedClass c in compiler_generated)
2366 c.EmitType ();
2370 public override void CloseType ()
2372 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2373 return;
2375 try {
2376 caching_flags |= Flags.CloseTypeCreated;
2377 TypeBuilder.CreateType ();
2378 } catch (TypeLoadException){
2380 // This is fine, the code still created the type
2382 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
2383 // Console.WriteLine (e.Message);
2384 } catch (Exception e) {
2385 throw new InternalErrorException (this, e);
2388 if (Types != null){
2389 foreach (TypeContainer tc in Types)
2390 if (tc.Kind == Kind.Struct)
2391 tc.CloseType ();
2393 foreach (TypeContainer tc in Types)
2394 if (tc.Kind != Kind.Struct)
2395 tc.CloseType ();
2398 if (Delegates != null)
2399 foreach (Delegate d in Delegates)
2400 d.CloseType ();
2402 if (CompilerGenerated != null)
2403 foreach (CompilerGeneratedClass c in CompilerGenerated)
2404 c.CloseType ();
2406 types = null;
2407 properties = null;
2408 delegates = null;
2409 fields = null;
2410 initialized_fields = null;
2411 initialized_static_fields = null;
2412 constants = null;
2413 ordered_explicit_member_list = null;
2414 ordered_member_list = null;
2415 methods = null;
2416 events = null;
2417 indexers = null;
2418 operators = null;
2419 compiler_generated = null;
2420 default_constructor = null;
2421 default_static_constructor = null;
2422 type_bases = null;
2423 OptAttributes = null;
2424 ifaces = null;
2425 base_cache = null;
2426 member_cache = null;
2430 // Performs the validation on a Method's modifiers (properties have
2431 // the same properties).
2433 public bool MethodModifiersValid (MemberCore mc)
2435 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2436 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2437 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2438 bool ok = true;
2439 int flags = mc.ModFlags;
2442 // At most one of static, virtual or override
2444 if ((flags & Modifiers.STATIC) != 0){
2445 if ((flags & vao) != 0){
2446 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2447 mc.GetSignatureForError ());
2448 ok = false;
2452 if (Kind == Kind.Struct){
2453 if ((flags & va) != 0){
2454 Modifiers.Error_InvalidModifier (mc.Location, "virtual or abstract");
2455 ok = false;
2459 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2460 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2461 mc.GetSignatureForError ());
2462 ok = false;
2466 // If the declaration includes the abstract modifier, then the
2467 // declaration does not include static, virtual or extern
2469 if ((flags & Modifiers.ABSTRACT) != 0){
2470 if ((flags & Modifiers.EXTERN) != 0){
2471 Report.Error (
2472 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2473 ok = false;
2476 if ((flags & Modifiers.SEALED) != 0) {
2477 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2478 ok = false;
2481 if ((flags & Modifiers.VIRTUAL) != 0){
2482 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2483 ok = false;
2486 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2487 Report.SymbolRelatedToPreviousError (this);
2488 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2489 mc.GetSignatureForError (), GetSignatureForError ());
2490 ok = false;
2494 if ((flags & Modifiers.PRIVATE) != 0){
2495 if ((flags & vao) != 0){
2496 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2497 ok = false;
2501 if ((flags & Modifiers.SEALED) != 0){
2502 if ((flags & Modifiers.OVERRIDE) == 0){
2503 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2504 ok = false;
2508 return ok;
2511 public Constructor DefaultStaticConstructor {
2512 get { return default_static_constructor; }
2515 protected override bool VerifyClsCompliance ()
2517 if (!base.VerifyClsCompliance ())
2518 return false;
2520 VerifyClsName ();
2522 Type base_type = TypeBuilder.BaseType;
2523 if (base_type != null && !AttributeTester.IsClsCompliant (base_type)) {
2524 Report.Error (3009, Location, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (base_type));
2526 return true;
2530 /// <summary>
2531 /// Checks whether container name is CLS Compliant
2532 /// </summary>
2533 void VerifyClsName ()
2535 Hashtable base_members = base_cache == null ?
2536 new Hashtable () :
2537 base_cache.GetPublicMembers ();
2538 Hashtable this_members = new Hashtable ();
2540 foreach (DictionaryEntry entry in defined_names) {
2541 MemberCore mc = (MemberCore)entry.Value;
2542 if (!mc.IsClsComplianceRequired ())
2543 continue;
2545 string name = (string) entry.Key;
2546 string basename = name.Substring (name.LastIndexOf ('.') + 1);
2548 string lcase = basename.ToLower (System.Globalization.CultureInfo.InvariantCulture);
2549 object found = base_members [lcase];
2550 if (found == null) {
2551 found = this_members [lcase];
2552 if (found == null) {
2553 this_members.Add (lcase, mc);
2554 continue;
2558 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
2559 continue;
2561 if (found is MemberInfo) {
2562 if (basename == ((MemberInfo) found).Name)
2563 continue;
2564 Report.SymbolRelatedToPreviousError ((MemberInfo) found);
2565 } else {
2566 Report.SymbolRelatedToPreviousError ((MemberCore) found);
2568 #if GMCS_SOURCE
2569 Report.Warning (3005, 1, mc.Location, "Identifier `{0}' differing only in case is not CLS-compliant", mc.GetSignatureForError ());
2570 #else
2571 Report.Error (3005, mc.Location, "Identifier `{0}' differing only in case is not CLS-compliant", mc.GetSignatureForError ());
2572 #endif
2577 /// <summary>
2578 /// Performs checks for an explicit interface implementation. First it
2579 /// checks whether the `interface_type' is a base inteface implementation.
2580 /// Then it checks whether `name' exists in the interface type.
2581 /// </summary>
2582 public virtual bool VerifyImplements (InterfaceMemberBase mb)
2584 if (ifaces != null) {
2585 foreach (Type t in ifaces){
2586 if (t == mb.InterfaceType)
2587 return true;
2591 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2592 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2593 mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType));
2594 return false;
2597 public override Type LookupAnyGeneric (string typeName)
2599 if (types != null) {
2600 foreach (TypeContainer tc in types) {
2601 if (!tc.IsGeneric)
2602 continue;
2604 int pos = tc.Basename.LastIndexOf ('`');
2605 if (pos == typeName.Length && String.Compare (typeName, 0, tc.Basename, 0, pos) == 0)
2606 return tc.TypeBuilder;
2610 return base.LookupAnyGeneric (typeName);
2613 public void Mark_HasEquals ()
2615 cached_method |= CachedMethods.Equals;
2618 public void Mark_HasGetHashCode ()
2620 cached_method |= CachedMethods.GetHashCode;
2623 /// <summary>
2624 /// Method container contains Equals method
2625 /// </summary>
2626 public bool HasEquals {
2627 get {
2628 return (cached_method & CachedMethods.Equals) != 0;
2632 /// <summary>
2633 /// Method container contains GetHashCode method
2634 /// </summary>
2635 public bool HasGetHashCode {
2636 get {
2637 return (cached_method & CachedMethods.GetHashCode) != 0;
2642 // IMemberContainer
2645 string IMemberContainer.Name {
2646 get {
2647 return Name;
2651 Type IMemberContainer.Type {
2652 get {
2653 return TypeBuilder;
2657 MemberCache IMemberContainer.MemberCache {
2658 get {
2659 return member_cache;
2663 bool IMemberContainer.IsInterface {
2664 get {
2665 return Kind == Kind.Interface;
2669 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2671 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2673 if (GenericType != null)
2674 return TypeManager.FindMembers (GenericType, mt, new_bf,
2675 null, null);
2676 else
2677 return FindMembers (mt, new_bf, null, null);
2681 // Generates xml doc comments (if any), and if required,
2682 // handle warning report.
2684 internal override void GenerateDocComment (DeclSpace ds)
2686 DocUtil.GenerateTypeDocComment (this, ds);
2689 public override string DocCommentHeader {
2690 get { return "T:"; }
2693 public virtual MemberCache BaseCache {
2694 get {
2695 if (base_cache != null)
2696 return base_cache;
2697 if (TypeBuilder.BaseType != null)
2698 base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
2699 if (TypeBuilder.IsInterface)
2700 base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
2701 return base_cache;
2705 private IDictionary anonymous_types;
2706 public IDictionary AnonymousTypes {
2707 get {
2708 if (anonymous_types == null)
2709 anonymous_types = new HybridDictionary();
2710 return anonymous_types;
2715 public abstract class ClassOrStruct : TypeContainer {
2716 ListDictionary declarative_security;
2718 public ClassOrStruct (NamespaceEntry ns, DeclSpace parent,
2719 MemberName name, Attributes attrs, Kind kind)
2720 : base (ns, parent, name, attrs, kind)
2724 protected override bool AddToContainer (MemberCore symbol, string name)
2726 if (name == MemberName.Name) {
2727 if (symbol is TypeParameter) {
2728 Report.Error (694, symbol.Location,
2729 "Type parameter `{0}' has same name as " +
2730 "containing type, or method", name);
2731 return false;
2734 Report.SymbolRelatedToPreviousError (this);
2735 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2736 symbol.GetSignatureForError ());
2737 return false;
2740 return base.AddToContainer (symbol, name);
2743 public override void VerifyMembers ()
2745 base.VerifyMembers ();
2747 if ((events != null) && (RootContext.WarningLevel >= 3)) {
2748 foreach (Event e in events){
2749 if ((e.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
2750 continue;
2752 if ((e.caching_flags & Flags.IsUsed) == 0)
2753 Report.Warning (67, 3, e.Location, "The event `{0}' is never used", e.GetSignatureForError ());
2758 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2760 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
2761 if (declarative_security == null)
2762 declarative_security = new ListDictionary ();
2764 a.ExtractSecurityPermissionSet (declarative_security);
2765 return;
2768 if (a.Type == TypeManager.struct_layout_attribute_type && a.GetLayoutKindValue () == LayoutKind.Explicit) {
2769 HasExplicitLayout = true;
2772 base.ApplyAttributeBuilder (a, cb);
2775 /// <summary>
2776 /// Defines the default constructors
2777 /// </summary>
2778 protected void DefineDefaultConstructor (bool is_static)
2780 // The default instance constructor is public
2781 // If the class is abstract, the default constructor is protected
2782 // The default static constructor is private
2784 int mods;
2785 if (is_static) {
2786 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2787 } else {
2788 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2791 Constructor c = new Constructor (this, MemberName.Name, mods,
2792 Parameters.EmptyReadOnlyParameters,
2793 new GeneratedBaseInitializer (Location),
2794 Location);
2796 AddConstructor (c);
2797 c.Block = new ToplevelBlock (null, Location);
2800 void DefineFieldInitializers ()
2802 if (initialized_fields != null) {
2803 for (int i = 0; i < initialized_fields.Count; ++i) {
2804 FieldInitializer fi = (FieldInitializer)initialized_fields[i];
2806 EmitContext ec = new EmitContext (fi.TypeContainer, fi.TypeContainer,
2807 Location, null, null, ModFlags);
2808 ec.IsFieldInitializer = true;
2810 fi.ResolveStatement (ec);
2811 if (fi.IsDefaultInitializer && RootContext.Optimize) {
2812 // Field is re-initialized to its default value => removed
2813 initialized_fields.RemoveAt (i);
2814 --i;
2819 if (initialized_static_fields != null) {
2820 bool has_complex_initializer = false;
2822 foreach (FieldInitializer fi in initialized_static_fields) {
2823 EmitContext ec = new EmitContext (fi.TypeContainer, fi.TypeContainer,
2824 Location, null, null, ModFlags);
2825 ec.IsStatic = true;
2826 ec.IsFieldInitializer = true;
2828 fi.ResolveStatement (ec);
2829 if (!fi.IsComplexInitializer)
2830 continue;
2832 has_complex_initializer = true;
2835 // Need special check to not optimize code like this
2836 // static int a = b = 5;
2837 // static int b = 0;
2838 if (!has_complex_initializer && RootContext.Optimize) {
2839 for (int i = 0; i < initialized_static_fields.Count; ++i) {
2840 FieldInitializer fi = (FieldInitializer)initialized_static_fields[i];
2841 if (fi.IsDefaultInitializer) {
2842 initialized_static_fields.RemoveAt (i);
2843 --i;
2848 if (default_static_constructor == null && initialized_static_fields.Count > 0) {
2849 DefineDefaultConstructor (true);
2855 public override bool Define ()
2857 DefineFieldInitializers ();
2859 if (default_static_constructor != null)
2860 default_static_constructor.Define ();
2862 return base.Define ();
2865 public override void Emit ()
2867 base.Emit ();
2869 if (declarative_security != null) {
2870 foreach (DictionaryEntry de in declarative_security) {
2871 TypeBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
2876 public override ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name)
2878 return NamespaceEntry.LookupExtensionMethod (extensionType, this, name);
2881 protected override TypeAttributes TypeAttr {
2882 get {
2883 if (default_static_constructor == null)
2884 return base.TypeAttr | TypeAttributes.BeforeFieldInit;
2886 return base.TypeAttr;
2892 // TODO: should be sealed
2893 public class Class : ClassOrStruct {
2894 const int AllowedModifiers =
2895 Modifiers.NEW |
2896 Modifiers.PUBLIC |
2897 Modifiers.PROTECTED |
2898 Modifiers.INTERNAL |
2899 Modifiers.PRIVATE |
2900 Modifiers.ABSTRACT |
2901 Modifiers.SEALED |
2902 Modifiers.STATIC |
2903 Modifiers.UNSAFE;
2905 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2907 public Class (NamespaceEntry ns, DeclSpace parent, MemberName name, int mod,
2908 Attributes attrs)
2909 : base (ns, parent, name, attrs, Kind.Class)
2911 int accmods = Parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2912 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, Location);
2914 if (IsStatic && RootContext.Version == LanguageVersion.ISO_1) {
2915 Report.FeatureIsNotISO1 (Location, "static classes");
2919 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
2921 if (a.Type == TypeManager.attribute_usage_type) {
2922 if (BaseType != TypeManager.attribute_type && !BaseType.IsSubclassOf (TypeManager.attribute_type) &&
2923 TypeBuilder.FullName != "System.Attribute") {
2924 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2928 if (a.Type == TypeManager.conditional_attribute_type &&
2929 !(BaseType == TypeManager.attribute_type || BaseType.IsSubclassOf (TypeManager.attribute_type))) {
2930 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2931 return;
2934 if (a.Type == TypeManager.comimport_attr_type &&
2935 !attributes.Contains (TypeManager.guid_attr_type)) {
2936 a.Error_MissingGuidAttribute ();
2937 return;
2940 if (a.Type == TypeManager.extension_attribute_type) {
2941 a.Error_MisusedExtensionAttribute ();
2942 return;
2945 if (AttributeTester.IsAttributeExcluded (a.Type))
2946 return;
2948 base.ApplyAttributeBuilder (a, cb);
2951 public override AttributeTargets AttributeTargets {
2952 get {
2953 return AttributeTargets.Class;
2957 protected override void DefineContainerMembers (MemberCoreArrayList list)
2959 if (list == null)
2960 return;
2962 if (!IsStatic) {
2963 base.DefineContainerMembers (list);
2964 return;
2967 foreach (MemberCore m in list) {
2968 if (m is Operator) {
2969 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2970 continue;
2973 if (m is Destructor) {
2974 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2975 continue;
2978 if ((m.ModFlags & Modifiers.PROTECTED) != 0) {
2979 Report.Error (1057, m.Location, "`{0}': Static classes cannot contain protected members", m.GetSignatureForError ());
2980 continue;
2983 if (m is Indexer) {
2984 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2985 continue;
2988 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is Enum || m is Delegate)
2989 continue;
2991 if (m is Constructor) {
2992 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2993 continue;
2996 Method method = m as Method;
2997 if (method != null && method.Parameters.HasExtensionMethodType) {
2998 Report.Error (1105, m.Location, "`{0}': Extension methods must be declared static", m.GetSignatureForError ());
2999 continue;
3002 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
3005 base.DefineContainerMembers (list);
3008 public override TypeBuilder DefineType ()
3010 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
3011 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
3012 return null;
3015 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
3016 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
3017 return null;
3020 return base.DefineType ();
3023 protected override bool DoDefineMembers ()
3025 if (InstanceConstructors == null && !IsStatic)
3026 DefineDefaultConstructor (false);
3028 return base.DoDefineMembers ();
3031 public override void Emit ()
3033 base.Emit ();
3035 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
3036 TypeBuilder.SetCustomAttribute (TypeManager.extension_attribute_attr);
3039 public override TypeExpr[] GetClassBases (out TypeExpr base_class)
3041 TypeExpr[] ifaces = base.GetClassBases (out base_class);
3043 if (base_class == null) {
3044 if (RootContext.StdLib)
3045 base_class = TypeManager.system_object_expr;
3046 else if (Name != "System.Object")
3047 base_class = TypeManager.system_object_expr;
3048 } else {
3049 if (Kind == Kind.Class && base_class is TypeParameterExpr){
3050 Report.Error (
3051 689, base_class.Location,
3052 "Cannot derive from `{0}' because it is a type parameter",
3053 base_class.GetSignatureForError ());
3054 return ifaces;
3057 if (base_class.Type.IsArray || base_class.Type.IsPointer) {
3058 Report.Error (1521, base_class.Location, "Invalid base type");
3059 return ifaces;
3062 if (base_class.IsSealed){
3063 Report.SymbolRelatedToPreviousError (base_class.Type);
3064 if (base_class.Type.IsAbstract) {
3065 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
3066 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
3067 } else {
3068 Report.Error (509, Location, "`{0}': cannot derive from sealed class `{1}'",
3069 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
3071 return ifaces;
3074 if (!base_class.CanInheritFrom ()){
3075 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
3076 GetSignatureForError (), base_class.GetSignatureForError ());
3077 return ifaces;
3080 if (!base_class.AsAccessible (this, ModFlags)) {
3081 Report.SymbolRelatedToPreviousError (base_class.Type);
3082 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
3083 TypeManager.CSharpName (base_class.Type), GetSignatureForError ());
3087 if (IsStatic) {
3088 if (base_class != TypeManager.system_object_expr) {
3089 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
3090 GetSignatureForError (), base_class.GetSignatureForError ());
3091 return ifaces;
3094 if (ifaces != null) {
3095 foreach (TypeExpr t in ifaces)
3096 Report.SymbolRelatedToPreviousError (t.Type);
3097 Report.Error (714, Location, "`{0}': static classes cannot implement interfaces", GetSignatureForError ());
3101 return ifaces;
3104 /// Search for at least one defined condition in ConditionalAttribute of attribute class
3105 /// Valid only for attribute classes.
3106 public bool IsExcluded ()
3108 if ((caching_flags & Flags.Excluded_Undetected) == 0)
3109 return (caching_flags & Flags.Excluded) != 0;
3111 caching_flags &= ~Flags.Excluded_Undetected;
3113 if (OptAttributes == null)
3114 return false;
3116 Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type);
3118 if (attrs == null)
3119 return false;
3121 foreach (Attribute a in attrs) {
3122 string condition = a.GetConditionalAttributeValue ();
3123 if (RootContext.AllDefines.Contains (condition))
3124 return false;
3127 caching_flags |= Flags.Excluded;
3128 return true;
3131 bool IsStatic {
3132 get {
3133 return (ModFlags & Modifiers.STATIC) != 0;
3138 // FIXME: How do we deal with the user specifying a different
3139 // layout?
3141 protected override TypeAttributes TypeAttr {
3142 get {
3143 TypeAttributes ta = base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
3144 if (IsStatic)
3145 ta |= StaticClassAttribute;
3146 return ta;
3151 public sealed class Struct : ClassOrStruct {
3152 // <summary>
3153 // Modifiers allowed in a struct declaration
3154 // </summary>
3155 const int AllowedModifiers =
3156 Modifiers.NEW |
3157 Modifiers.PUBLIC |
3158 Modifiers.PROTECTED |
3159 Modifiers.INTERNAL |
3160 Modifiers.UNSAFE |
3161 Modifiers.PRIVATE;
3163 public Struct (NamespaceEntry ns, DeclSpace parent, MemberName name,
3164 int mod, Attributes attrs)
3165 : base (ns, parent, name, attrs, Kind.Struct)
3167 int accmods;
3169 if (parent.Parent == null)
3170 accmods = Modifiers.INTERNAL;
3171 else
3172 accmods = Modifiers.PRIVATE;
3174 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, Location);
3176 this.ModFlags |= Modifiers.SEALED;
3179 public override AttributeTargets AttributeTargets {
3180 get {
3181 return AttributeTargets.Struct;
3185 const TypeAttributes DefaultTypeAttributes =
3186 TypeAttributes.SequentialLayout |
3187 TypeAttributes.Sealed |
3188 TypeAttributes.BeforeFieldInit;
3191 public override TypeExpr[] GetClassBases (out TypeExpr base_class)
3193 TypeExpr[] ifaces = base.GetClassBases (out base_class);
3195 // If we are compiling our runtime,
3196 // and we are defining ValueType, then our
3197 // base is `System.Object'.
3199 if (base_class == null) {
3200 if (!RootContext.StdLib && Name == "System.ValueType")
3201 base_class = TypeManager.system_object_expr;
3202 else
3203 base_class = TypeManager.system_valuetype_expr;
3206 return ifaces;
3210 // FIXME: Allow the user to specify a different set of attributes
3211 // in some cases (Sealed for example is mandatory for a class,
3212 // but what SequentialLayout can be changed
3214 protected override TypeAttributes TypeAttr {
3215 get {
3216 return base.TypeAttr | DefaultTypeAttributes;
3220 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
3222 if ((field.ModFlags & Modifiers.STATIC) == 0) {
3223 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
3224 field.GetSignatureForError ());
3225 return;
3227 base.RegisterFieldForInitialization (field, expression);
3232 /// <summary>
3233 /// Interfaces
3234 /// </summary>
3235 public sealed class Interface : TypeContainer, IMemberContainer {
3237 /// <summary>
3238 /// Modifiers allowed in a class declaration
3239 /// </summary>
3240 public const int AllowedModifiers =
3241 Modifiers.NEW |
3242 Modifiers.PUBLIC |
3243 Modifiers.PROTECTED |
3244 Modifiers.INTERNAL |
3245 Modifiers.UNSAFE |
3246 Modifiers.PRIVATE;
3248 public Interface (NamespaceEntry ns, DeclSpace parent, MemberName name, int mod,
3249 Attributes attrs)
3250 : base (ns, parent, name, attrs, Kind.Interface)
3252 int accmods;
3254 if (parent.Parent == null)
3255 accmods = Modifiers.INTERNAL;
3256 else
3257 accmods = Modifiers.PRIVATE;
3259 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, name.Location);
3262 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3264 if (a.Type == TypeManager.comimport_attr_type &&
3265 !attributes.Contains (TypeManager.guid_attr_type)) {
3266 a.Error_MissingGuidAttribute ();
3267 return;
3269 base.ApplyAttributeBuilder (a, cb);
3273 public override AttributeTargets AttributeTargets {
3274 get {
3275 return AttributeTargets.Interface;
3279 const TypeAttributes DefaultTypeAttributes =
3280 TypeAttributes.AutoLayout |
3281 TypeAttributes.Abstract |
3282 TypeAttributes.Interface;
3284 protected override TypeAttributes TypeAttr {
3285 get {
3286 return base.TypeAttr | DefaultTypeAttributes;
3290 protected override bool VerifyClsCompliance ()
3292 if (!base.VerifyClsCompliance ())
3293 return false;
3295 if (ifaces != null) {
3296 foreach (Type t in ifaces) {
3297 if (AttributeTester.IsClsCompliant (t))
3298 continue;
3300 Report.SymbolRelatedToPreviousError (t);
3301 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3302 GetSignatureForError (), TypeManager.CSharpName (t));
3306 return true;
3310 // It is used as a base class for all property based members
3311 // This includes properties, indexers, and events
3312 public abstract class PropertyBasedMember : InterfaceMemberBase
3314 public PropertyBasedMember (DeclSpace parent, GenericMethod generic,
3315 Expression type, int mod, int allowed_mod, bool is_iface,
3316 MemberName name, Attributes attrs)
3317 : base (parent, generic, type, mod, allowed_mod, is_iface, name, attrs)
3321 protected override bool CheckForDuplications ()
3323 throw new NotSupportedException ();
3326 protected override bool VerifyClsCompliance ()
3328 if (!base.VerifyClsCompliance ())
3329 return false;
3331 if (!AttributeTester.IsClsCompliant (MemberType)) {
3332 Report.Error (3003, Location, "Type of `{0}' is not CLS-compliant",
3333 GetSignatureForError ());
3335 return true;
3341 public abstract class MethodCore : InterfaceMemberBase
3343 public readonly Parameters Parameters;
3344 protected ToplevelBlock block;
3346 public MethodCore (DeclSpace parent, GenericMethod generic,
3347 Expression type, int mod, int allowed_mod, bool is_iface,
3348 MemberName name, Attributes attrs, Parameters parameters)
3349 : base (parent, generic, type, mod, allowed_mod, is_iface, name, attrs)
3351 Parameters = parameters;
3355 // Returns the System.Type array for the parameters of this method
3357 public Type [] ParameterTypes {
3358 get {
3359 return Parameters.Types;
3363 public Parameters ParameterInfo
3365 get {
3366 return Parameters;
3370 public ToplevelBlock Block {
3371 get {
3372 return block;
3375 set {
3376 block = value;
3380 protected override bool CheckBase ()
3382 // Check whether arguments were correct.
3383 if (!DefineParameters (Parameters))
3384 return false;
3386 if (!base.CheckBase ())
3387 return false;
3389 return true;
3392 // TODO: create a special method for operators only to make code better
3393 protected bool IsDuplicateImplementation (MethodCore method)
3395 if (method == this)
3396 return false;
3398 Operator op2 = null;
3399 Operator op1 = null;
3401 if (!(method.MemberName.Equals (MemberName)))
3403 op1 = this as Operator;
3404 if (op1 == null || !(op1.OperatorType == Operator.OpType.Explicit || op1.OperatorType == Operator.OpType.Implicit))
3405 return false;
3407 op2 = method as Operator;
3408 if (op2 == null || !(op2.OperatorType == Operator.OpType.Explicit || op2.OperatorType == Operator.OpType.Implicit))
3409 return false;
3410 } else {
3411 op1 = this as Operator;
3412 op2 = method as Operator;
3415 Type[] param_types = method.ParameterTypes;
3416 // This never happen. Rewrite this as Equal
3417 if (param_types == null && ParameterTypes == null)
3418 return true;
3419 if (param_types == null || ParameterTypes == null)
3420 return false;
3422 if (param_types.Length != ParameterTypes.Length)
3423 return false;
3425 if (method.Parameters.HasArglist != Parameters.HasArglist)
3426 return false;
3428 bool equal = true;
3430 for (int i = 0; i < param_types.Length; i++) {
3431 if (param_types [i] != ParameterTypes [i])
3432 equal = false;
3435 if (IsExplicitImpl && (method.InterfaceType != InterfaceType))
3436 equal = false;
3438 // TODO: make operator compatible with MethodCore to avoid this
3439 if (op1 != null && op2 != null) {
3440 if (MemberType != method.MemberType)
3441 equal = false;
3444 if (equal) {
3446 // Try to report 663: method only differs on out/ref
3448 Parameters info = ParameterInfo;
3449 Parameters other_info = method.ParameterInfo;
3450 for (int i = 0; i < info.Count; i++){
3451 if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
3452 Report.SymbolRelatedToPreviousError (method);
3453 Report.Error (663, Location, "`{0}': Methods cannot differ only on their use of ref and out on a parameters",
3454 GetSignatureForError ());
3455 return false;
3459 Report.SymbolRelatedToPreviousError (method);
3460 if (this is Operator && method is Operator)
3461 Report.Error (557, Location, "Duplicate user-defined conversion in type `{0}'", Parent.Name);
3462 else
3463 Report.Error (111, Location, TypeContainer.Error111, GetSignatureForError ());
3465 return true;
3468 return false;
3472 // Returns a string that represents the signature for this
3473 // member which should be used in XML documentation.
3475 public override string GetDocCommentName (DeclSpace ds)
3477 return DocUtil.GetMethodDocCommentName (this, Parameters, ds);
3481 // Raised (and passed an XmlElement that contains the comment)
3482 // when GenerateDocComment is writing documentation expectedly.
3484 // FIXME: with a few effort, it could be done with XmlReader,
3485 // that means removal of DOM use.
3487 internal override void OnGenerateDocComment (XmlElement el)
3489 DocUtil.OnMethodGenerateDocComment (this, el);
3493 // Represents header string for documentation comment.
3495 public override string DocCommentHeader
3497 get { return "M:"; }
3500 public virtual void SetYields ()
3502 ModFlags |= Modifiers.METHOD_YIELDS;
3505 protected override bool VerifyClsCompliance ()
3507 if (!base.VerifyClsCompliance ())
3508 return false;
3510 if (Parameters.HasArglist) {
3511 Report.Error (3000, Location, "Methods with variable arguments are not CLS-compliant");
3514 if (!AttributeTester.IsClsCompliant (MemberType)) {
3515 Report.Error (3002, Location, "Return type of `{0}' is not CLS-compliant",
3516 GetSignatureForError ());
3519 Parameters.VerifyClsCompliance ();
3520 return true;
3525 public abstract class InterfaceMemberBase : MemberBase {
3527 // Whether this is an interface member.
3529 public bool IsInterface;
3532 // If true, this is an explicit interface implementation
3534 public bool IsExplicitImpl;
3536 protected bool is_external_implementation;
3539 // The interface type we are explicitly implementing
3541 public Type InterfaceType;
3544 // The method we're overriding if this is an override method.
3546 protected MethodInfo base_method;
3548 readonly int explicit_mod_flags;
3549 public MethodAttributes flags;
3551 public InterfaceMemberBase (DeclSpace parent, GenericMethod generic,
3552 Expression type, int mod, int allowed_mod, bool is_iface,
3553 MemberName name, Attributes attrs)
3554 : base (parent, generic, type, mod, allowed_mod, Modifiers.PRIVATE,
3555 name, attrs)
3557 IsInterface = is_iface;
3558 IsExplicitImpl = (MemberName.Left != null);
3559 explicit_mod_flags = mod;
3562 protected override bool CheckBase ()
3564 if (!base.CheckBase ())
3565 return false;
3567 if ((caching_flags & Flags.TestMethodDuplication) != 0 && !CheckForDuplications ())
3568 return false;
3570 if (IsExplicitImpl)
3571 return true;
3573 // Is null for System.Object while compiling corlib and base interfaces
3574 if (Parent.PartialContainer.BaseCache == null) {
3575 if ((ModFlags & Modifiers.NEW) != 0) {
3576 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3578 return true;
3581 Type base_ret_type = null;
3582 base_method = FindOutBaseMethod (ref base_ret_type);
3584 // method is override
3585 if (base_method != null) {
3586 if (!CheckMethodAgainstBase (base_ret_type))
3587 return false;
3589 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3590 ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (base_method);
3591 if (oa != null) {
3592 if (OptAttributes == null || !OptAttributes.Contains (TypeManager.obsolete_attribute_type)) {
3593 Report.SymbolRelatedToPreviousError (base_method);
3594 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3595 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3597 } else {
3598 if (OptAttributes != null && OptAttributes.Contains (TypeManager.obsolete_attribute_type)) {
3599 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3600 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3604 return true;
3607 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Name, !((this is Event) || (this is Property)));
3608 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3609 if (conflict_symbol != null) {
3610 Report.SymbolRelatedToPreviousError (conflict_symbol);
3611 if (this is Event)
3612 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3613 else if (this is PropertyBase)
3614 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3615 else
3616 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3617 } else {
3618 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3619 GetSignatureForError (), SimpleName.GetMemberType (this));
3621 return false;
3624 if (conflict_symbol == null) {
3625 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
3626 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3628 return true;
3631 if ((ModFlags & Modifiers.NEW) == 0) {
3632 if (this is Method && conflict_symbol is MethodBase)
3633 return true;
3635 Report.SymbolRelatedToPreviousError (conflict_symbol);
3636 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3637 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3640 return true;
3644 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3645 // that have been defined.
3647 // `name' is the user visible name for reporting errors (this is used to
3648 // provide the right name regarding method names and properties)
3650 bool CheckMethodAgainstBase (Type base_method_type)
3652 bool ok = true;
3654 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3655 if (!(base_method.IsAbstract || base_method.IsVirtual)){
3656 Report.Error (506, Location,
3657 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3658 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3659 ok = false;
3662 // Now we check that the overriden method is not final
3664 if (base_method.IsFinal) {
3665 Report.SymbolRelatedToPreviousError (base_method);
3666 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3667 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3668 ok = false;
3671 // Check that the permissions are not being changed
3673 MethodAttributes thisp = flags & MethodAttributes.MemberAccessMask;
3674 MethodAttributes base_classp = base_method.Attributes & MethodAttributes.MemberAccessMask;
3676 if (!CheckAccessModifiers (thisp, base_classp, base_method)) {
3677 Error_CannotChangeAccessModifiers (base_method, base_classp, null);
3678 ok = false;
3681 if (!TypeManager.IsEqual (MemberType, TypeManager.TypeToCoreType (base_method_type))) {
3682 Report.SymbolRelatedToPreviousError (base_method);
3683 if (this is PropertyBasedMember) {
3684 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3685 GetSignatureForError (), TypeManager.CSharpName (base_method_type), TypeManager.CSharpSignature (base_method));
3687 else {
3688 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3689 GetSignatureForError (), TypeManager.CSharpName (base_method_type), TypeManager.CSharpSignature (base_method));
3691 ok = false;
3695 if ((ModFlags & Modifiers.NEW) == 0) {
3696 if ((ModFlags & Modifiers.OVERRIDE) == 0 && Name != "Finalize") {
3697 ModFlags |= Modifiers.NEW;
3698 Report.SymbolRelatedToPreviousError (base_method);
3699 if (!IsInterface && (base_method.IsVirtual || base_method.IsAbstract)) {
3700 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",
3701 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3702 } else {
3703 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3704 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3707 } else {
3708 if (base_method.IsAbstract && !IsInterface) {
3709 Report.SymbolRelatedToPreviousError (base_method);
3710 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3711 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3712 return ok = false;
3716 return ok;
3719 protected bool CheckAccessModifiers (MethodAttributes thisp, MethodAttributes base_classp, MethodInfo base_method)
3721 if ((base_classp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3723 // when overriding protected internal, the method can be declared
3724 // protected internal only within the same assembly
3727 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3728 if (Parent.TypeBuilder.Assembly != base_method.DeclaringType.Assembly){
3730 // assemblies differ - report an error
3733 return false;
3734 } else if (thisp != base_classp) {
3736 // same assembly, but other attributes differ - report an error
3739 return false;
3741 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3743 // if it's not "protected internal", it must be "protected"
3746 return false;
3747 } else if (Parent.TypeBuilder.Assembly == base_method.DeclaringType.Assembly) {
3749 // protected within the same assembly - an error
3751 return false;
3752 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3753 (base_classp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3755 // protected ok, but other attributes differ - report an error
3757 return false;
3759 return true;
3760 } else {
3761 return (thisp == base_classp);
3765 public bool CheckAbstractAndExtern (bool has_block)
3767 if (Parent.PartialContainer.Kind == Kind.Interface)
3768 return true;
3770 if (has_block) {
3771 if ((ModFlags & Modifiers.EXTERN) != 0) {
3772 Report.Error (179, Location, "`{0}' cannot declare a body because it is marked extern",
3773 GetSignatureForError ());
3774 return false;
3777 if ((ModFlags & Modifiers.ABSTRACT) != 0) {
3778 Report.Error (500, Location, "`{0}' cannot declare a body because it is marked abstract",
3779 GetSignatureForError ());
3780 return false;
3782 } else {
3783 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
3784 Report.Error (501, Location, "`{0}' must declare a body because it is not marked abstract or extern",
3785 GetSignatureForError ());
3786 return false;
3790 return true;
3793 protected bool DefineParameters (Parameters parameters)
3795 IResolveContext rc = GenericMethod == null ? this : (IResolveContext)ds;
3797 if (!parameters.Resolve (rc))
3798 return false;
3800 bool error = false;
3801 foreach (Parameter p in parameters.FixedParameters) {
3802 if (p.CheckAccessibility (this))
3803 continue;
3805 Report.SymbolRelatedToPreviousError (p.ParameterType);
3806 if (this is Indexer)
3807 Report.Error (55, Location,
3808 "Inconsistent accessibility: parameter type `" +
3809 TypeManager.CSharpName (p.ParameterType) + "' is less " +
3810 "accessible than indexer `" + GetSignatureForError () + "'");
3811 else if (this is Operator)
3812 Report.Error (57, Location,
3813 "Inconsistent accessibility: parameter type `" +
3814 TypeManager.CSharpName (p.ParameterType) + "' is less " +
3815 "accessible than operator `" + GetSignatureForError () + "'");
3816 else
3817 Report.Error (51, Location,
3818 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3819 TypeManager.CSharpName (p.ParameterType), GetSignatureForError ());
3820 error = true;
3822 return !error;
3825 protected override bool DoDefine()
3827 if (!base.DoDefine ())
3828 return false;
3830 if (IsExplicitImpl) {
3831 Expression expr = MemberName.Left.GetTypeExpression ();
3832 TypeExpr texpr = expr.ResolveAsTypeTerminal (this, false);
3833 if (texpr == null)
3834 return false;
3836 InterfaceType = texpr.Type;
3838 if (!InterfaceType.IsInterface) {
3839 Report.Error (538, Location, "`{0}' in explicit interface declaration is not an interface", TypeManager.CSharpName (InterfaceType));
3840 return false;
3843 if (!Parent.PartialContainer.VerifyImplements (this))
3844 return false;
3847 return true;
3850 protected virtual bool DoDefineBase ()
3852 if (Name == null)
3853 throw new InternalErrorException ();
3855 if (IsInterface) {
3856 ModFlags = Modifiers.PUBLIC |
3857 Modifiers.ABSTRACT |
3858 Modifiers.VIRTUAL | (ModFlags & Modifiers.UNSAFE) | (ModFlags & Modifiers.NEW);
3860 flags = MethodAttributes.Public |
3861 MethodAttributes.Abstract |
3862 MethodAttributes.HideBySig |
3863 MethodAttributes.NewSlot |
3864 MethodAttributes.Virtual;
3865 } else {
3866 if (!Parent.PartialContainer.MethodModifiersValid (this))
3867 return false;
3869 flags = Modifiers.MethodAttr (ModFlags);
3872 if (IsExplicitImpl) {
3873 Expression expr = MemberName.Left.GetTypeExpression ();
3874 TypeExpr iface_texpr = expr.ResolveAsTypeTerminal (this, false);
3875 if (iface_texpr == null)
3876 return false;
3878 InterfaceType = iface_texpr.Type;
3880 if (!InterfaceType.IsInterface) {
3881 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", TypeManager.CSharpName (InterfaceType));
3882 return false;
3885 if (!Parent.PartialContainer.VerifyImplements (this))
3886 return false;
3888 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
3891 return true;
3894 public override void Emit()
3896 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3897 // We are more strict than Microsoft and report CS0626 as error
3898 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation) {
3899 Report.Error (626, Location,
3900 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3901 GetSignatureForError ());
3904 base.Emit ();
3907 protected void Error_CannotChangeAccessModifiers (MemberInfo base_method, MethodAttributes ma, string suffix)
3909 Report.SymbolRelatedToPreviousError (base_method);
3910 string base_name = TypeManager.GetFullNameSignature (base_method);
3911 string this_name = GetSignatureForError ();
3912 if (suffix != null) {
3913 base_name += suffix;
3914 this_name += suffix;
3917 Report.Error (507, Location, "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3918 this_name, Modifiers.GetDescription (ma), base_name);
3921 protected static string Error722 {
3922 get {
3923 return "`{0}': static types cannot be used as return types";
3927 /// <summary>
3928 /// For custom member duplication search in a container
3929 /// </summary>
3930 protected abstract bool CheckForDuplications ();
3932 /// <summary>
3933 /// Gets base method and its return type
3934 /// </summary>
3935 protected abstract MethodInfo FindOutBaseMethod (ref Type base_ret_type);
3938 // The "short" name of this property / indexer / event. This is the
3939 // name without the explicit interface.
3941 public string ShortName
3943 get { return MemberName.Name; }
3944 set { SetMemberName (new MemberName (MemberName.Left, value, Location)); }
3947 protected override bool VerifyClsCompliance ()
3949 if (!base.VerifyClsCompliance ()) {
3950 if (IsInterface && HasClsCompliantAttribute && Parent.IsClsComplianceRequired ()) {
3951 Report.Error (3010, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
3954 if ((ModFlags & Modifiers.ABSTRACT) != 0 && Parent.TypeBuilder.IsClass && IsExposedFromAssembly () && Parent.IsClsComplianceRequired ()) {
3955 Report.Error (3011, Location, "`{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
3957 return false;
3960 if (GenericMethod != null)
3961 GenericMethod.VerifyClsCompliance ();
3963 return true;
3966 public override bool IsUsed
3968 get { return IsExplicitImpl || base.IsUsed; }
3973 public abstract class MethodOrOperator : MethodCore, IMethodData
3975 public MethodBuilder MethodBuilder;
3976 ReturnParameter return_attributes;
3977 ListDictionary declarative_security;
3978 protected MethodData MethodData;
3980 Iterator iterator;
3981 ArrayList anonymous_methods;
3983 static string[] attribute_targets = new string [] { "method", "return" };
3985 protected MethodOrOperator (DeclSpace parent, GenericMethod generic, Expression type, int mod,
3986 int allowed_mod, bool is_interface, MemberName name,
3987 Attributes attrs, Parameters parameters)
3988 : base (parent, generic, type, mod, allowed_mod, is_interface, name,
3989 attrs, parameters)
3993 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3995 if (a.Target == AttributeTargets.ReturnValue) {
3996 if (return_attributes == null)
3997 return_attributes = new ReturnParameter (MethodBuilder, Location);
3999 return_attributes.ApplyAttributeBuilder (a, cb);
4000 return;
4003 if (a.IsInternalMethodImplAttribute) {
4004 is_external_implementation = true;
4007 if (a.Type == TypeManager.dllimport_type) {
4008 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
4009 if ((ModFlags & extern_static) != extern_static) {
4010 Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
4012 is_external_implementation = true;
4015 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
4016 if (declarative_security == null)
4017 declarative_security = new ListDictionary ();
4018 a.ExtractSecurityPermissionSet (declarative_security);
4019 return;
4022 MethodBuilder.SetCustomAttribute (cb);
4025 public override AttributeTargets AttributeTargets {
4026 get {
4027 return AttributeTargets.Method;
4031 public virtual EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
4033 return new EmitContext (
4034 this, tc, this.ds, Location, ig, MemberType, ModFlags, false);
4037 public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
4039 if (anonymous_methods == null)
4040 anonymous_methods = new ArrayList ();
4041 anonymous_methods.Add (anonymous);
4044 protected bool DefineGenericMethod ()
4046 if (!DoDefineBase ())
4047 return false;
4049 #if GMCS_SOURCE
4050 if (GenericMethod != null) {
4051 string method_name = MemberName.Name;
4053 if (IsExplicitImpl) {
4054 method_name = TypeManager.CSharpName (InterfaceType) +
4055 '.' + method_name;
4058 #if MS_COMPATIBLE
4059 MethodBuilder = Parent.TypeBuilder.DefineMethod (method_name, flags, ReturnType, null);
4060 #else
4061 MethodBuilder = Parent.TypeBuilder.DefineMethod (method_name, flags);
4062 #endif
4064 if (!GenericMethod.Define (MethodBuilder, block))
4065 return false;
4067 #endif
4069 return true;
4072 public bool ResolveMembers ()
4074 if (!DefineGenericMethod ())
4075 return false;
4077 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0) {
4078 iterator = Iterator.CreateIterator (this, Parent, GenericMethod, ModFlags);
4079 if (iterator == null)
4080 return false;
4083 if (anonymous_methods != null) {
4084 foreach (AnonymousMethodExpression ame in anonymous_methods) {
4085 if (!ame.CreateAnonymousHelpers ())
4086 return false;
4090 return true;
4093 public override bool Define ()
4095 if (!DoDefine ())
4096 return false;
4098 if (!CheckAbstractAndExtern (block != null))
4099 return false;
4101 if (!CheckBase ())
4102 return false;
4104 MethodData = new MethodData (
4105 this, ModFlags, flags, this, MethodBuilder, GenericMethod, base_method);
4107 if (!MethodData.Define (Parent.PartialContainer))
4108 return false;
4110 MethodBuilder = MethodData.MethodBuilder;
4112 if (!TypeManager.IsGenericParameter (MemberType)) {
4113 if (MemberType.IsAbstract && MemberType.IsSealed) {
4114 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
4115 return false;
4119 return true;
4122 public override void Emit ()
4124 #if GMCS_SOURCE
4125 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0)
4126 MethodBuilder.SetCustomAttribute (TypeManager.compiler_generated_attr);
4127 #endif
4128 if (OptAttributes != null)
4129 OptAttributes.Emit ();
4131 if (declarative_security != null) {
4132 foreach (DictionaryEntry de in declarative_security) {
4133 MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
4137 base.Emit ();
4140 protected void Error_ConditionalAttributeIsNotValid ()
4142 Report.Error (577, Location,
4143 "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
4144 GetSignatureForError ());
4147 public override bool MarkForDuplicationCheck ()
4149 caching_flags |= Flags.TestMethodDuplication;
4150 return true;
4153 public override string[] ValidAttributeTargets {
4154 get {
4155 return attribute_targets;
4159 #region IMethodData Members
4161 public CallingConventions CallingConventions {
4162 get {
4163 CallingConventions cc = Parameters.CallingConvention;
4164 if (Parameters.HasArglist && block != null)
4165 block.HasVarargs = true;
4167 if (!IsInterface)
4168 if ((ModFlags & Modifiers.STATIC) == 0)
4169 cc |= CallingConventions.HasThis;
4171 // FIXME: How is `ExplicitThis' used in C#?
4173 return cc;
4177 public Type ReturnType {
4178 get {
4179 return MemberType;
4183 public MemberName MethodName {
4184 get {
4185 return MemberName;
4189 public Iterator Iterator {
4190 get { return iterator; }
4193 public new Location Location {
4194 get {
4195 return base.Location;
4199 protected override bool CheckBase ()
4201 if (!base.CheckBase ())
4202 return false;
4204 // TODO: Destructor should derive from MethodCore
4205 if (base_method != null && (ModFlags & Modifiers.OVERRIDE) != 0 && Name == "Finalize" &&
4206 base_method.DeclaringType == TypeManager.object_type && !(this is Destructor)) {
4207 Report.Error (249, Location, "Do not override object.Finalize. Instead, provide a destructor");
4208 return false;
4211 return true;
4214 /// <summary>
4215 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
4216 /// </summary>
4217 public bool IsExcluded () {
4218 if ((caching_flags & Flags.Excluded_Undetected) == 0)
4219 return (caching_flags & Flags.Excluded) != 0;
4221 caching_flags &= ~Flags.Excluded_Undetected;
4223 if (base_method == null) {
4224 if (OptAttributes == null)
4225 return false;
4227 Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type);
4229 if (attrs == null)
4230 return false;
4232 foreach (Attribute a in attrs) {
4233 string condition = a.GetConditionalAttributeValue ();
4234 if (condition == null)
4235 return false;
4237 if (RootContext.AllDefines.Contains (condition))
4238 return false;
4241 caching_flags |= Flags.Excluded;
4242 return true;
4245 IMethodData md = TypeManager.GetMethod (base_method);
4246 if (md == null) {
4247 if (AttributeTester.IsConditionalMethodExcluded (base_method)) {
4248 caching_flags |= Flags.Excluded;
4249 return true;
4251 return false;
4254 if (md.IsExcluded ()) {
4255 caching_flags |= Flags.Excluded;
4256 return true;
4258 return false;
4261 GenericMethod IMethodData.GenericMethod {
4262 get {
4263 return GenericMethod;
4267 #endregion
4271 public class SourceMethod : ISourceMethod
4273 DeclSpace parent;
4274 MethodBase builder;
4276 protected SourceMethod (DeclSpace parent, MethodBase builder,
4277 ISourceFile file, Location start, Location end)
4279 this.parent = parent;
4280 this.builder = builder;
4282 CodeGen.SymbolWriter.OpenMethod (file, this, start.Row, start.Column, end.Row, start.Column);
4285 public string Name {
4286 get { return builder.Name; }
4289 public int NamespaceID {
4290 get { return parent.NamespaceEntry.SymbolFileID; }
4293 public int Token {
4294 get {
4295 if (builder is MethodBuilder)
4296 return ((MethodBuilder) builder).GetToken ().Token;
4297 else if (builder is ConstructorBuilder)
4298 return ((ConstructorBuilder) builder).GetToken ().Token;
4299 else
4300 throw new NotSupportedException ();
4304 public void CloseMethod ()
4306 if (CodeGen.SymbolWriter != null)
4307 CodeGen.SymbolWriter.CloseMethod ();
4310 public static SourceMethod Create (DeclSpace parent, MethodBase builder, Block block)
4312 if (CodeGen.SymbolWriter == null)
4313 return null;
4314 if (block == null)
4315 return null;
4317 Location start_loc = block.StartLocation;
4318 if (start_loc.IsNull)
4319 return null;
4321 Location end_loc = block.EndLocation;
4322 if (end_loc.IsNull)
4323 return null;
4325 ISourceFile file = start_loc.SourceFile;
4326 if (file == null)
4327 return null;
4329 return new SourceMethod (
4330 parent, builder, file, start_loc, end_loc);
4334 public class Method : MethodOrOperator, IAnonymousHost {
4336 /// <summary>
4337 /// Modifiers allowed in a class declaration
4338 /// </summary>
4339 const int AllowedModifiers =
4340 Modifiers.NEW |
4341 Modifiers.PUBLIC |
4342 Modifiers.PROTECTED |
4343 Modifiers.INTERNAL |
4344 Modifiers.PRIVATE |
4345 Modifiers.STATIC |
4346 Modifiers.VIRTUAL |
4347 Modifiers.SEALED |
4348 Modifiers.OVERRIDE |
4349 Modifiers.ABSTRACT |
4350 Modifiers.UNSAFE |
4351 Modifiers.METHOD_YIELDS |
4352 Modifiers.EXTERN;
4354 const int AllowedInterfaceModifiers =
4355 Modifiers.NEW | Modifiers.UNSAFE;
4358 // return_type can be "null" for VOID values.
4360 public Method (DeclSpace parent, GenericMethod generic,
4361 Expression return_type, int mod, bool is_iface,
4362 MemberName name, Parameters parameters, Attributes attrs)
4363 : base (parent, generic, return_type, mod,
4364 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
4365 is_iface, name, attrs, parameters)
4369 public override string GetSignatureForError()
4371 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
4374 void Error_DuplicateEntryPoint (MethodInfo b, Location location)
4376 Report.Error (17, location,
4377 "Program `{0}' has more than one entry point defined: `{1}'",
4378 CodeGen.FileName, TypeManager.CSharpSignature(b));
4381 bool IsEntryPoint ()
4383 if (ReturnType != TypeManager.void_type &&
4384 ReturnType != TypeManager.int32_type)
4385 return false;
4387 if (Parameters.Count == 0)
4388 return true;
4390 if (Parameters.Count > 1)
4391 return false;
4393 Type t = Parameters.ParameterType (0);
4394 return t.IsArray && t.GetArrayRank () == 1 &&
4395 TypeManager.GetElementType (t) == TypeManager.string_type &&
4396 (Parameters[0].ModFlags & ~Parameter.Modifier.PARAMS) == Parameter.Modifier.NONE;
4399 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4401 if (a.Type == TypeManager.conditional_attribute_type) {
4402 if (IsExplicitImpl) {
4403 Error_ConditionalAttributeIsNotValid ();
4404 return;
4407 if (ReturnType != TypeManager.void_type) {
4408 Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ());
4409 return;
4412 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
4413 Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ());
4414 return;
4417 if (IsInterface) {
4418 Report.Error (582, Location, "Conditional not valid on interface members");
4419 return;
4422 if (MethodData.implementing != null) {
4423 Report.SymbolRelatedToPreviousError (MethodData.implementing.DeclaringType);
4424 Report.Error (629, Location, "Conditional member `{0}' cannot implement interface member `{1}'",
4425 GetSignatureForError (), TypeManager.CSharpSignature (MethodData.implementing));
4426 return;
4429 for (int i = 0; i < Parameters.Count; ++i) {
4430 if ((Parameters.ParameterModifier (i) & Parameter.Modifier.OUTMASK) != 0) {
4431 Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
4432 return;
4437 if (a.Type == TypeManager.extension_attribute_type) {
4438 a.Error_MisusedExtensionAttribute ();
4439 return;
4442 base.ApplyAttributeBuilder (a, cb);
4445 protected override bool CheckForDuplications ()
4447 ArrayList ar = Parent.PartialContainer.Methods;
4448 if (ar != null) {
4449 int arLen = ar.Count;
4451 for (int i = 0; i < arLen; i++) {
4452 Method m = (Method) ar [i];
4453 if (IsDuplicateImplementation (m))
4454 return false;
4458 ar = Parent.PartialContainer.Properties;
4459 if (ar != null) {
4460 for (int i = 0; i < ar.Count; ++i) {
4461 PropertyBase pb = (PropertyBase) ar [i];
4462 if (pb.AreAccessorsDuplicateImplementation (this))
4463 return false;
4467 ar = Parent.PartialContainer.Indexers;
4468 if (ar != null) {
4469 for (int i = 0; i < ar.Count; ++i) {
4470 PropertyBase pb = (PropertyBase) ar [i];
4471 if (pb.AreAccessorsDuplicateImplementation (this))
4472 return false;
4476 ar = Parent.PartialContainer.Events;
4477 if (ar != null) {
4478 for (int i = 0; i < ar.Count; ++i) {
4479 Event ev = (Event) ar [i];
4480 if (ev.AreAccessorsDuplicateImplementation (this))
4481 return false;
4485 return true;
4489 // Creates the type
4491 public override bool Define ()
4493 if (!base.Define ())
4494 return false;
4496 if (RootContext.StdLib && (ReturnType == TypeManager.arg_iterator_type || ReturnType == TypeManager.typed_reference_type)) {
4497 Error1599 (Location, ReturnType);
4498 return false;
4501 if (ReturnType == TypeManager.void_type && ParameterTypes.Length == 0 &&
4502 Name == "Finalize" && !(this is Destructor)) {
4503 Report.Warning (465, 1, Location, "Introducing a 'Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
4506 if (base_method != null && (ModFlags & Modifiers.NEW) == 0) {
4507 if (Parameters.Count == 1 && ParameterTypes [0] == TypeManager.object_type && Name == "Equals")
4508 Parent.PartialContainer.Mark_HasEquals ();
4509 else if (Parameters.Empty && Name == "GetHashCode")
4510 Parent.PartialContainer.Mark_HasGetHashCode ();
4513 if ((ModFlags & Modifiers.STATIC) == 0)
4514 return true;
4516 if (Parameters.HasExtensionMethodType) {
4517 if (Parent.IsStaticClass && !Parent.IsGeneric) {
4518 if (!Parent.IsTopLevel)
4519 Report.Error (1109, Location, "`{0}': Extension methods cannot be defined in a nested class",
4520 GetSignatureForError ());
4522 if (TypeManager.extension_attribute_type == null)
4523 Report.Error (1110, Location,
4524 "`{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",
4525 GetSignatureForError ());
4527 ModFlags |= Modifiers.METHOD_EXTENSION;
4528 Parent.ModFlags |= Modifiers.METHOD_EXTENSION;
4529 CodeGen.Assembly.HasExtensionMethods = true;
4530 } else {
4531 Report.Error (1106, Location, "`{0}': Extension methods must be defined in a non-generic static class",
4532 GetSignatureForError ());
4537 // This is used to track the Entry Point,
4539 if (RootContext.NeedsEntryPoint &&
4540 Name == "Main" &&
4541 (RootContext.MainClass == null ||
4542 RootContext.MainClass == Parent.TypeBuilder.FullName)){
4543 if (IsEntryPoint ()) {
4545 if (RootContext.EntryPoint == null) {
4546 if (Parent.IsGeneric || MemberName.IsGeneric) {
4547 Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type",
4548 GetSignatureForError ());
4549 } else {
4550 IMethodData md = TypeManager.GetMethod (MethodBuilder);
4551 md.SetMemberIsUsed ();
4553 RootContext.EntryPoint = MethodBuilder;
4554 RootContext.EntryPointLocation = Location;
4556 } else {
4557 Error_DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
4558 Error_DuplicateEntryPoint (MethodBuilder, Location);
4560 } else {
4561 Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point",
4562 GetSignatureForError ());
4566 return true;
4570 // Emits the code
4572 public override void Emit ()
4574 Report.Debug (64, "METHOD EMIT", this, MethodBuilder, Location, Block, MethodData);
4575 MethodData.Emit (Parent);
4576 base.Emit ();
4578 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
4579 MethodBuilder.SetCustomAttribute (TypeManager.extension_attribute_attr);
4581 Block = null;
4582 MethodData = null;
4585 public static void Error1599 (Location loc, Type t)
4587 Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t));
4590 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
4592 MethodInfo mi = (MethodInfo) Parent.PartialContainer.BaseCache.FindMemberToOverride (
4593 Parent.TypeBuilder, Name, ParameterTypes, GenericMethod, false);
4595 if (mi == null)
4596 return null;
4598 if (mi.IsSpecialName)
4599 return null;
4601 base_ret_type = mi.ReturnType;
4602 return mi;
4605 protected override bool VerifyClsCompliance ()
4607 if (!base.VerifyClsCompliance ())
4608 return false;
4610 if (ParameterInfo.Count > 0) {
4611 ArrayList al = (ArrayList)Parent.PartialContainer.MemberCache.Members [Name];
4612 if (al.Count > 1)
4613 MemberCache.VerifyClsParameterConflict (al, this, MethodBuilder);
4616 return true;
4620 public abstract class ConstructorInitializer {
4621 ArrayList argument_list;
4622 protected ConstructorInfo base_constructor;
4623 Location loc;
4625 public ConstructorInitializer (ArrayList argument_list, Location loc)
4627 this.argument_list = argument_list;
4628 this.loc = loc;
4631 public ArrayList Arguments {
4632 get {
4633 return argument_list;
4637 public bool Resolve (ConstructorBuilder caller_builder, Block block, EmitContext ec)
4639 Expression base_constructor_group;
4640 Type t;
4641 bool error = false;
4643 ec.CurrentBlock = block;
4645 if (argument_list != null){
4646 foreach (Argument a in argument_list){
4647 if (!a.Resolve (ec, loc))
4648 return false;
4651 ec.CurrentBlock = null;
4653 if (this is ConstructorBaseInitializer) {
4654 if (ec.ContainerType.BaseType == null)
4655 return true;
4657 t = ec.ContainerType.BaseType;
4658 if (ec.ContainerType.IsValueType) {
4659 Report.Error (522, loc,
4660 "`{0}': Struct constructors cannot call base constructors", TypeManager.CSharpSignature (caller_builder));
4661 return false;
4663 } else {
4665 // It is legal to have "this" initializers that take no arguments
4666 // in structs, they are just no-ops.
4668 // struct D { public D (int a) : this () {}
4670 if (ec.ContainerType.IsValueType && argument_list == null)
4671 return true;
4673 t = ec.ContainerType;
4676 base_constructor_group = Expression.MemberLookup (
4677 ec.ContainerType, t, ".ctor", MemberTypes.Constructor,
4678 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
4679 loc);
4681 if (base_constructor_group == null){
4682 error = true;
4683 base_constructor_group = Expression.MemberLookup (
4684 t, null, t, ".ctor", MemberTypes.Constructor,
4685 BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
4686 loc);
4689 int errors = Report.Errors;
4690 if (base_constructor_group != null)
4691 base_constructor = (ConstructorInfo)
4692 ((MethodGroupExpr) base_constructor_group).OverloadResolve (
4693 ec, argument_list,
4694 false, loc);
4696 if (base_constructor == null) {
4697 if (errors == Report.Errors)
4698 Invocation.Error_WrongNumArguments (loc, TypeManager.CSharpSignature (caller_builder),
4699 argument_list == null ? 0 : argument_list.Count);
4700 return false;
4703 if (error) {
4704 Report.SymbolRelatedToPreviousError (base_constructor);
4705 Expression.ErrorIsInaccesible (loc, TypeManager.CSharpSignature (base_constructor));
4706 base_constructor = null;
4707 return false;
4710 if (base_constructor == caller_builder){
4711 Report.Error (516, loc, "Constructor `{0}' cannot call itself", TypeManager.CSharpSignature (caller_builder));
4712 return false;
4715 return true;
4718 public virtual void Emit (EmitContext ec)
4720 if (base_constructor != null){
4721 ec.Mark (loc, false);
4722 if (ec.IsStatic)
4723 Invocation.EmitCall (ec, true, true, null, base_constructor, argument_list, loc);
4724 else
4725 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), base_constructor, argument_list, loc);
4730 public class ConstructorBaseInitializer : ConstructorInitializer {
4731 public ConstructorBaseInitializer (ArrayList argument_list, Location l) :
4732 base (argument_list, l)
4737 class GeneratedBaseInitializer: ConstructorBaseInitializer {
4738 public GeneratedBaseInitializer (Location loc):
4739 base (null, loc)
4744 public class ConstructorThisInitializer : ConstructorInitializer {
4745 public ConstructorThisInitializer (ArrayList argument_list, Location l) :
4746 base (argument_list, l)
4751 public class Constructor : MethodCore, IMethodData, IAnonymousHost {
4752 public ConstructorBuilder ConstructorBuilder;
4753 public ConstructorInitializer Initializer;
4754 ListDictionary declarative_security;
4755 ArrayList anonymous_methods;
4757 // <summary>
4758 // Modifiers allowed for a constructor.
4759 // </summary>
4760 public const int AllowedModifiers =
4761 Modifiers.PUBLIC |
4762 Modifiers.PROTECTED |
4763 Modifiers.INTERNAL |
4764 Modifiers.STATIC |
4765 Modifiers.UNSAFE |
4766 Modifiers.EXTERN |
4767 Modifiers.PRIVATE;
4769 static string[] attribute_targets = new string [] { "method" };
4771 public Iterator Iterator {
4772 get { return null; }
4775 bool has_compliant_args = false;
4777 // The spec claims that static is not permitted, but
4778 // my very own code has static constructors.
4780 public Constructor (DeclSpace parent, string name, int mod, Parameters args,
4781 ConstructorInitializer init, Location loc)
4782 : base (parent, null, null, mod, AllowedModifiers, false,
4783 new MemberName (name, loc), null, args)
4785 Initializer = init;
4788 public bool HasCompliantArgs {
4789 get { return has_compliant_args; }
4792 public override AttributeTargets AttributeTargets {
4793 get { return AttributeTargets.Constructor; }
4798 // Returns true if this is a default constructor
4800 public bool IsDefault ()
4802 if ((ModFlags & Modifiers.STATIC) != 0)
4803 return Parameters.Empty;
4805 return Parameters.Empty &&
4806 (Initializer is ConstructorBaseInitializer) &&
4807 (Initializer.Arguments == null);
4810 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4812 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
4813 if (declarative_security == null) {
4814 declarative_security = new ListDictionary ();
4816 a.ExtractSecurityPermissionSet (declarative_security);
4817 return;
4820 if (a.IsInternalMethodImplAttribute) {
4821 is_external_implementation = true;
4824 ConstructorBuilder.SetCustomAttribute (cb);
4827 public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
4829 if (anonymous_methods == null)
4830 anonymous_methods = new ArrayList ();
4831 anonymous_methods.Add (anonymous);
4834 public bool ResolveMembers ()
4836 if (anonymous_methods != null) {
4837 foreach (AnonymousMethodExpression ame in anonymous_methods) {
4838 if (!ame.CreateAnonymousHelpers ())
4839 return false;
4843 return true;
4846 protected override bool CheckForDuplications ()
4848 ArrayList ar = Parent.PartialContainer.InstanceConstructors;
4849 if (ar != null) {
4850 int arLen = ar.Count;
4852 for (int i = 0; i < arLen; i++) {
4853 Constructor m = (Constructor) ar [i];
4854 if (IsDuplicateImplementation (m))
4855 return false;
4858 return true;
4861 protected override bool CheckBase ()
4863 if ((ModFlags & Modifiers.STATIC) != 0) {
4864 if (!Parameters.Empty) {
4865 Report.Error (132, Location, "`{0}': The static constructor must be parameterless",
4866 GetSignatureForError ());
4867 return false;
4870 // the rest can be ignored
4871 return true;
4874 // Check whether arguments were correct.
4875 if (!DefineParameters (Parameters))
4876 return false;
4878 if (!CheckForDuplications ())
4879 return false;
4881 if (Parent.PartialContainer.Kind == Kind.Struct) {
4882 if (ParameterTypes.Length == 0) {
4883 Report.Error (568, Location,
4884 "Structs cannot contain explicit parameterless constructors");
4885 return false;
4888 if ((ModFlags & Modifiers.PROTECTED) != 0) {
4889 Report.Error (666, Location, "`{0}': new protected member declared in struct", GetSignatureForError ());
4890 return false;
4894 if ((RootContext.WarningLevel >= 4) && ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.PROTECTED) != 0)) {
4895 Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class", GetSignatureForError ());
4898 return true;
4902 // Creates the ConstructorBuilder
4904 public override bool Define ()
4906 if (ConstructorBuilder != null)
4907 return true;
4909 MethodAttributes ca = (MethodAttributes.RTSpecialName |
4910 MethodAttributes.SpecialName);
4912 if ((ModFlags & Modifiers.STATIC) != 0) {
4913 ca |= MethodAttributes.Static | MethodAttributes.Private;
4914 } else {
4915 ca |= MethodAttributes.HideBySig;
4917 if ((ModFlags & Modifiers.PUBLIC) != 0)
4918 ca |= MethodAttributes.Public;
4919 else if ((ModFlags & Modifiers.PROTECTED) != 0){
4920 if ((ModFlags & Modifiers.INTERNAL) != 0)
4921 ca |= MethodAttributes.FamORAssem;
4922 else
4923 ca |= MethodAttributes.Family;
4924 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
4925 ca |= MethodAttributes.Assembly;
4926 else
4927 ca |= MethodAttributes.Private;
4930 if (!CheckAbstractAndExtern (block != null))
4931 return false;
4933 // Check if arguments were correct.
4934 if (!CheckBase ())
4935 return false;
4937 ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
4938 ca, CallingConventions,
4939 ParameterTypes);
4941 if ((ModFlags & Modifiers.UNSAFE) != 0)
4942 ConstructorBuilder.InitLocals = false;
4944 if (Parent.PartialContainer.IsComImport) {
4945 if (!IsDefault ()) {
4946 Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
4947 Parent.GetSignatureForError ());
4948 return false;
4950 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
4953 TypeManager.AddMethod (ConstructorBuilder, this);
4955 return true;
4959 // Emits the code
4961 public override void Emit ()
4963 if (OptAttributes != null)
4964 OptAttributes.Emit ();
4966 EmitContext ec = CreateEmitContext (null, null);
4968 if (block != null) {
4969 // If this is a non-static `struct' constructor and doesn't have any
4970 // initializer, it must initialize all of the struct's fields.
4971 if ((Parent.PartialContainer.Kind == Kind.Struct) &&
4972 ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
4973 block.AddThisVariable (Parent, Location);
4975 if (!block.ResolveMeta (ec, ParameterInfo))
4976 block = null;
4979 if ((ModFlags & Modifiers.STATIC) == 0){
4980 if (Parent.PartialContainer.Kind == Kind.Class && Initializer == null)
4981 Initializer = new GeneratedBaseInitializer (Location);
4985 // Spec mandates that Initializers will not have
4986 // `this' access
4988 ec.IsStatic = true;
4989 if ((Initializer != null) &&
4990 !Initializer.Resolve (ConstructorBuilder, block, ec))
4991 return;
4992 ec.IsStatic = false;
4995 Parameters.ApplyAttributes (ConstructorBuilder);
4997 SourceMethod source = SourceMethod.Create (
4998 Parent, ConstructorBuilder, block);
5001 // Classes can have base initializers and instance field initializers.
5003 if (Parent.PartialContainer.Kind == Kind.Class){
5004 if ((ModFlags & Modifiers.STATIC) == 0){
5007 // If we use a "this (...)" constructor initializer, then
5008 // do not emit field initializers, they are initialized in the other constructor
5010 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
5011 Parent.PartialContainer.EmitFieldInitializers (ec);
5015 bool unreachable = false;
5016 if (block != null) {
5017 if (!ec.ResolveTopBlock (null, block, ParameterInfo, this, out unreachable))
5018 return;
5019 ec.EmitMeta (block);
5021 if (block.ScopeInfo != null) {
5022 ExpressionStatement init = block.ScopeInfo.GetScopeInitializer (ec);
5023 init.EmitStatement (ec);
5027 if (Initializer != null) {
5028 Initializer.Emit (ec);
5031 if ((ModFlags & Modifiers.STATIC) != 0)
5032 Parent.PartialContainer.EmitFieldInitializers (ec);
5034 if (block != null)
5035 ec.EmitResolvedTopBlock (block, unreachable);
5037 if (source != null)
5038 source.CloseMethod ();
5040 base.Emit ();
5042 if (declarative_security != null) {
5043 foreach (DictionaryEntry de in declarative_security) {
5044 ConstructorBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
5048 block = null;
5051 // Is never override
5052 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
5054 return null;
5057 public override string GetSignatureForError()
5059 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
5062 public override string[] ValidAttributeTargets {
5063 get {
5064 return attribute_targets;
5068 protected override bool VerifyClsCompliance ()
5070 if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
5071 return false;
5074 if (ParameterInfo.Count > 0) {
5075 ArrayList al = (ArrayList)Parent.MemberCache.Members [".ctor"];
5076 if (al.Count > 3)
5077 MemberCache.VerifyClsParameterConflict (al, this, ConstructorBuilder);
5079 if (Parent.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
5080 foreach (Type param in ParameterTypes) {
5081 if (param.IsArray) {
5082 return true;
5087 has_compliant_args = true;
5088 return true;
5091 #region IMethodData Members
5093 public System.Reflection.CallingConventions CallingConventions {
5094 get {
5095 CallingConventions cc = Parameters.CallingConvention;
5097 if (Parent.PartialContainer.Kind == Kind.Class)
5098 if ((ModFlags & Modifiers.STATIC) == 0)
5099 cc |= CallingConventions.HasThis;
5101 // FIXME: How is `ExplicitThis' used in C#?
5103 return cc;
5107 public new Location Location {
5108 get {
5109 return base.Location;
5113 public MemberName MethodName {
5114 get {
5115 return MemberName;
5119 public Type ReturnType {
5120 get {
5121 return MemberType;
5125 public EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
5127 ILGenerator ig_ = ConstructorBuilder.GetILGenerator ();
5128 return new EmitContext (this, Parent, Location, ig_, null, ModFlags, true);
5131 public bool IsExcluded()
5133 return false;
5136 GenericMethod IMethodData.GenericMethod {
5137 get {
5138 return null;
5142 #endregion
5145 /// <summary>
5146 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
5147 /// </summary>
5148 public interface IMethodData
5150 CallingConventions CallingConventions { get; }
5151 Location Location { get; }
5152 MemberName MethodName { get; }
5153 Type ReturnType { get; }
5154 GenericMethod GenericMethod { get; }
5155 Parameters ParameterInfo { get; }
5157 Iterator Iterator { get; }
5159 Attributes OptAttributes { get; }
5160 ToplevelBlock Block { get; set; }
5162 EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig);
5163 ObsoleteAttribute GetObsoleteAttribute ();
5164 string GetSignatureForError ();
5165 bool IsExcluded ();
5166 bool IsClsComplianceRequired ();
5167 void SetMemberIsUsed ();
5171 // Encapsulates most of the Method's state
5173 public class MethodData {
5175 readonly IMethodData method;
5177 public readonly GenericMethod GenericMethod;
5180 // Are we implementing an interface ?
5182 public MethodInfo implementing;
5185 // Protected data.
5187 protected InterfaceMemberBase member;
5188 protected int modifiers;
5189 protected MethodAttributes flags;
5190 protected Type declaring_type;
5191 protected MethodInfo parent_method;
5193 MethodBuilder builder = null;
5194 public MethodBuilder MethodBuilder {
5195 get {
5196 return builder;
5200 public Type DeclaringType {
5201 get {
5202 return declaring_type;
5206 public MethodData (InterfaceMemberBase member,
5207 int modifiers, MethodAttributes flags, IMethodData method)
5209 this.member = member;
5210 this.modifiers = modifiers;
5211 this.flags = flags;
5213 this.method = method;
5216 public MethodData (InterfaceMemberBase member,
5217 int modifiers, MethodAttributes flags,
5218 IMethodData method, MethodBuilder builder,
5219 GenericMethod generic, MethodInfo parent_method)
5220 : this (member, modifiers, flags, method)
5222 this.builder = builder;
5223 this.GenericMethod = generic;
5224 this.parent_method = parent_method;
5227 public bool Define (DeclSpace parent)
5229 string name = method.MethodName.Basename;
5230 string method_name = method.MethodName.FullName;
5232 TypeContainer container = parent.PartialContainer;
5234 PendingImplementation pending = container.PendingImplementations;
5235 if (pending != null){
5236 if (member is Indexer) // TODO: test it, but it should work without this IF
5237 implementing = pending.IsInterfaceIndexer (
5238 member.InterfaceType, method.ReturnType, method.ParameterInfo);
5239 else
5240 implementing = pending.IsInterfaceMethod (
5241 member.InterfaceType, name, method.ReturnType, method.ParameterInfo);
5243 if (member.InterfaceType != null){
5244 if (implementing == null){
5245 if (member is PropertyBase) {
5246 Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'",
5247 method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType),
5248 member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
5250 } else {
5251 Report.Error (539, method.Location,
5252 "`{0}.{1}' in explicit interface declaration is not a member of interface",
5253 TypeManager.CSharpName (member.InterfaceType), member.ShortName);
5255 return false;
5257 if (implementing.IsSpecialName && !(method is AbstractPropertyEventMethod)) {
5258 Report.SymbolRelatedToPreviousError (implementing);
5259 Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
5260 member.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
5261 return false;
5264 method_name = member.InterfaceType.FullName +
5265 '.' + method_name;
5266 } else {
5267 if (implementing != null) {
5268 AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod;
5269 if (prop_method == null) {
5270 if (implementing.IsSpecialName) {
5271 Report.SymbolRelatedToPreviousError (implementing);
5272 Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}.{2}'",
5273 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing),
5274 implementing.Name.StartsWith ("get_") ? "get" : "set");
5275 return false;
5277 } else if (implementing.DeclaringType.IsInterface) {
5278 if (!implementing.IsSpecialName) {
5279 Report.SymbolRelatedToPreviousError (implementing);
5280 Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
5281 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
5282 return false;
5284 PropertyBase.PropertyMethod pm = prop_method as PropertyBase.PropertyMethod;
5285 if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
5286 Report.SymbolRelatedToPreviousError (implementing);
5287 Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'",
5288 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing, true));
5289 return false;
5297 // For implicit implementations, make sure we are public, for
5298 // explicit implementations, make sure we are private.
5300 if (implementing != null){
5302 // Setting null inside this block will trigger a more
5303 // verbose error reporting for missing interface implementations
5305 // The "candidate" function has been flagged already
5306 // but it wont get cleared
5308 if (member.IsExplicitImpl){
5309 if (method.ParameterInfo.HasParams && !TypeManager.GetParameterData (implementing).HasParams) {
5310 Report.SymbolRelatedToPreviousError (implementing);
5311 Report.Error (466, method.Location, "`{0}': the explicit interface implementation cannot introduce the params modifier",
5312 method.GetSignatureForError ());
5313 return false;
5315 } else {
5316 if (implementing.DeclaringType.IsInterface) {
5318 // If this is an interface method implementation,
5319 // check for public accessibility
5321 if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
5323 implementing = null;
5325 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
5326 // We may never be private.
5327 implementing = null;
5329 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
5331 // We may be protected if we're overriding something.
5333 implementing = null;
5338 // Static is not allowed
5340 if ((modifiers & Modifiers.STATIC) != 0){
5341 implementing = null;
5346 // If implementing is still valid, set flags
5348 if (implementing != null){
5350 // When implementing interface methods, set NewSlot
5351 // unless, we are overwriting a method.
5353 if (implementing.DeclaringType.IsInterface){
5354 if ((modifiers & Modifiers.OVERRIDE) == 0)
5355 flags |= MethodAttributes.NewSlot;
5357 flags |=
5358 MethodAttributes.Virtual |
5359 MethodAttributes.HideBySig;
5361 // Set Final unless we're virtual, abstract or already overriding a method.
5362 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
5363 flags |= MethodAttributes.Final;
5366 EmitContext ec = method.CreateEmitContext (container, null);
5368 DefineMethodBuilder (container, method_name, method.ParameterInfo.Types);
5370 if (builder == null)
5371 return false;
5373 if (container.CurrentType != null)
5374 declaring_type = container.CurrentType;
5375 else
5376 declaring_type = container.TypeBuilder;
5378 if ((modifiers & Modifiers.UNSAFE) != 0)
5379 builder.InitLocals = false;
5382 if (implementing != null){
5384 // clear the pending implemntation flag
5386 if (member is Indexer) {
5387 pending.ImplementIndexer (
5388 member.InterfaceType, builder, method.ReturnType,
5389 method.ParameterInfo, member.IsExplicitImpl);
5390 } else
5391 pending.ImplementMethod (
5392 member.InterfaceType, name, method.ReturnType,
5393 method.ParameterInfo, member.IsExplicitImpl);
5395 if (member.IsExplicitImpl)
5396 container.TypeBuilder.DefineMethodOverride (
5397 builder, implementing);
5400 TypeManager.AddMethod (builder, method);
5402 if (GenericMethod != null) {
5403 bool is_override = member.IsExplicitImpl |
5404 ((modifiers & Modifiers.OVERRIDE) != 0);
5406 if (implementing != null)
5407 parent_method = implementing;
5409 if (!GenericMethod.DefineType (ec, builder, parent_method, is_override))
5410 return false;
5413 return true;
5417 /// <summary>
5418 /// Create the MethodBuilder for the method
5419 /// </summary>
5420 void DefineMethodBuilder (TypeContainer container, string method_name, Type[] ParameterTypes)
5422 if (builder == null) {
5423 builder = container.TypeBuilder.DefineMethod (
5424 method_name, flags, method.CallingConventions,
5425 method.ReturnType, ParameterTypes);
5426 return;
5429 #if GMCS_SOURCE && !MS_COMPATIBLE
5430 builder.SetGenericMethodSignature (
5431 flags, method.CallingConventions,
5432 method.ReturnType, ParameterTypes);
5433 #endif
5437 // Emits the code
5439 public void Emit (DeclSpace parent)
5441 ToplevelBlock block = method.Block;
5443 EmitContext ec;
5444 if (block != null)
5445 ec = method.CreateEmitContext (parent, builder.GetILGenerator ());
5446 else
5447 ec = method.CreateEmitContext (parent, null);
5449 method.ParameterInfo.ApplyAttributes (MethodBuilder);
5451 if (GenericMethod != null)
5452 GenericMethod.EmitAttributes ();
5454 SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
5457 // Handle destructors specially
5459 // FIXME: This code generates buggy code
5461 if (member is Destructor)
5462 EmitDestructor (ec, block);
5463 else
5464 ec.EmitTopBlock (method, block);
5466 if (source != null)
5467 source.CloseMethod ();
5470 void EmitDestructor (EmitContext ec, ToplevelBlock block)
5472 ILGenerator ig = ec.ig;
5474 Label finish = ig.DefineLabel ();
5476 block.SetDestructor ();
5478 ig.BeginExceptionBlock ();
5479 ec.ReturnLabel = finish;
5480 ec.HasReturnLabel = true;
5481 ec.EmitTopBlock (method, block);
5483 // ig.MarkLabel (finish);
5484 ig.BeginFinallyBlock ();
5486 if (ec.ContainerType.BaseType != null) {
5487 Expression member_lookup = Expression.MemberLookup (
5488 ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
5489 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, method.Location);
5491 if (member_lookup != null){
5492 MethodGroupExpr base_destructor = ((MethodGroupExpr) member_lookup);
5494 ig.Emit (OpCodes.Ldarg_0);
5495 ig.Emit (OpCodes.Call, (MethodInfo) base_destructor.Methods [0]);
5499 ig.EndExceptionBlock ();
5500 //ig.MarkLabel (ec.ReturnLabel);
5501 ig.Emit (OpCodes.Ret);
5505 // TODO: Should derive from MethodCore
5506 public class Destructor : Method {
5508 static string[] attribute_targets = new string [] { "method" };
5510 public Destructor (DeclSpace parent, Expression return_type, int mod,
5511 string name, Parameters parameters, Attributes attrs,
5512 Location l)
5513 : base (parent, null, return_type, mod, false, new MemberName (name, l),
5514 parameters, attrs)
5517 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5519 if (a.Type == TypeManager.conditional_attribute_type) {
5520 Error_ConditionalAttributeIsNotValid ();
5521 return;
5524 base.ApplyAttributeBuilder (a, cb);
5527 public override string GetSignatureForError ()
5529 return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
5532 public override string[] ValidAttributeTargets {
5533 get {
5534 return attribute_targets;
5539 abstract public class MemberBase : MemberCore {
5540 public Expression Type;
5541 public readonly DeclSpace ds;
5542 public readonly GenericMethod GenericMethod;
5545 // The type of this property / indexer / event
5547 protected Type member_type;
5548 public Type MemberType {
5549 get {
5550 if (member_type == null && Type != null) {
5551 IResolveContext rc = GenericMethod == null ? this : (IResolveContext)ds;
5552 Type = Type.ResolveAsTypeTerminal (rc, false);
5553 if (Type != null) {
5554 member_type = Type.Type;
5557 return member_type;
5562 // The constructor is only exposed to our children
5564 protected MemberBase (DeclSpace parent, GenericMethod generic,
5565 Expression type, int mod, int allowed_mod, int def_mod,
5566 MemberName name, Attributes attrs)
5567 : base (parent, name, attrs)
5569 this.ds = generic != null ? generic : (DeclSpace) parent;
5570 Type = type;
5571 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, Location);
5572 GenericMethod = generic;
5573 if (GenericMethod != null)
5574 GenericMethod.ModFlags = ModFlags;
5577 protected virtual bool CheckBase ()
5579 if ((ModFlags & Modifiers.PROTECTED) != 0 && Parent.PartialContainer.Kind == Kind.Struct) {
5580 Report.Error (666, Location, "`{0}': new protected member declared in struct", GetSignatureForError ());
5581 return false;
5584 if ((RootContext.WarningLevel >= 4) &&
5585 ((Parent.ModFlags & Modifiers.SEALED) != 0) &&
5586 ((ModFlags & Modifiers.PROTECTED) != 0) &&
5587 ((ModFlags & Modifiers.OVERRIDE) == 0) && (Name != "Finalize")) {
5588 Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class", GetSignatureForError ());
5590 return true;
5593 protected virtual bool DoDefine ()
5595 if (MemberType == null)
5596 return false;
5598 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
5599 (ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0) {
5600 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
5601 GetSignatureForError (), Parent.GetSignatureForError ());
5602 return false;
5605 // verify accessibility
5606 if (!Parent.AsAccessible (MemberType, ModFlags)) {
5607 Report.SymbolRelatedToPreviousError (MemberType);
5608 if (this is Property)
5609 Report.Error (53, Location,
5610 "Inconsistent accessibility: property type `" +
5611 TypeManager.CSharpName (MemberType) + "' is less " +
5612 "accessible than property `" + GetSignatureForError () + "'");
5613 else if (this is Indexer)
5614 Report.Error (54, Location,
5615 "Inconsistent accessibility: indexer return type `" +
5616 TypeManager.CSharpName (MemberType) + "' is less " +
5617 "accessible than indexer `" + GetSignatureForError () + "'");
5618 else if (this is MethodCore) {
5619 if (this is Operator)
5620 Report.Error (56, Location,
5621 "Inconsistent accessibility: return type `" +
5622 TypeManager.CSharpName (MemberType) + "' is less " +
5623 "accessible than operator `" + GetSignatureForError () + "'");
5624 else
5625 Report.Error (50, Location,
5626 "Inconsistent accessibility: return type `" +
5627 TypeManager.CSharpName (MemberType) + "' is less " +
5628 "accessible than method `" + GetSignatureForError () + "'");
5629 } else {
5630 Report.Error (52, Location,
5631 "Inconsistent accessibility: field type `" +
5632 TypeManager.CSharpName (MemberType) + "' is less " +
5633 "accessible than field `" + GetSignatureForError () + "'");
5635 return false;
5638 return true;
5641 protected bool IsTypePermitted ()
5643 if (MemberType == TypeManager.arg_iterator_type || MemberType == TypeManager.typed_reference_type) {
5644 Report.Error (610, Location, "Field or property cannot be of type `{0}'", TypeManager.CSharpName (MemberType));
5645 return false;
5647 return true;
5652 // Abstract class for all fields
5654 abstract public class FieldBase : MemberBase {
5655 public FieldBuilder FieldBuilder;
5656 public Status status;
5657 protected Expression initializer;
5659 [Flags]
5660 public enum Status : byte {
5661 HAS_OFFSET = 4 // Used by FieldMember.
5664 static readonly string[] attribute_targets = new string [] { "field" };
5666 protected FieldBase (DeclSpace parent, Expression type, int mod,
5667 int allowed_mod, MemberName name, Attributes attrs)
5668 : base (parent, null, type, mod, allowed_mod | Modifiers.ABSTRACT, Modifiers.PRIVATE,
5669 name, attrs)
5671 if ((mod & Modifiers.ABSTRACT) != 0)
5672 Report.Error (681, Location, "The modifier 'abstract' is not valid on fields. Try using a property instead");
5675 public override AttributeTargets AttributeTargets {
5676 get {
5677 return AttributeTargets.Field;
5681 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5683 if (a.Type == TypeManager.field_offset_attribute_type) {
5684 status |= Status.HAS_OFFSET;
5686 if (!Parent.PartialContainer.HasExplicitLayout) {
5687 Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)");
5688 return;
5691 if ((ModFlags & Modifiers.STATIC) != 0 || this is Const) {
5692 Report.Error (637, Location, "The FieldOffset attribute is not allowed on static or const fields");
5693 return;
5697 #if NET_2_0
5698 if (a.Type == TypeManager.fixed_buffer_attr_type) {
5699 Report.Error (1716, Location, "Do not use 'System.Runtime.CompilerServices.FixedBuffer' attribute. Use the 'fixed' field modifier instead");
5700 return;
5702 #endif
5704 if (a.Type == TypeManager.marshal_as_attr_type) {
5705 UnmanagedMarshal marshal = a.GetMarshal (this);
5706 if (marshal != null) {
5707 FieldBuilder.SetMarshal (marshal);
5709 return;
5712 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
5713 a.Error_InvalidSecurityParent ();
5714 return;
5717 FieldBuilder.SetCustomAttribute (cb);
5720 protected override bool CheckBase ()
5722 if (!base.CheckBase ())
5723 return false;
5725 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Name, false);
5726 if (conflict_symbol == null) {
5727 if ((ModFlags & Modifiers.NEW) != 0) {
5728 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
5730 return true;
5733 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0) {
5734 Report.SymbolRelatedToPreviousError (conflict_symbol);
5735 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
5736 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
5739 return true;
5742 public override bool Define()
5744 if (MemberType == null || Type == null)
5745 return false;
5747 if (TypeManager.IsGenericParameter (MemberType))
5748 return true;
5750 if (MemberType == TypeManager.void_type) {
5751 // TODO: wrong location
5752 Expression.Error_VoidInvalidInTheContext (Location);
5753 return false;
5756 if (MemberType.IsSealed && MemberType.IsAbstract) {
5757 Error_VariableOfStaticClass (Location, GetSignatureForError (), MemberType);
5758 return false;
5761 if (!CheckBase ())
5762 return false;
5764 if (!Parent.AsAccessible (MemberType, ModFlags)) {
5765 Report.Error (52, Location,
5766 "Inconsistent accessibility: field type `" +
5767 TypeManager.CSharpName (MemberType) + "' is less " +
5768 "accessible than field `" + GetSignatureForError () + "'");
5769 return false;
5772 if (!IsTypePermitted ())
5773 return false;
5775 return true;
5779 // Represents header string for documentation comment.
5781 public override string DocCommentHeader {
5782 get { return "F:"; }
5785 public override void Emit ()
5787 #if GMCS_SOURCE
5788 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0) {
5789 FieldBuilder.SetCustomAttribute (TypeManager.compiler_generated_attr);
5791 #endif
5793 if (OptAttributes != null) {
5794 OptAttributes.Emit ();
5797 if (((status & Status.HAS_OFFSET) == 0) && (ModFlags & Modifiers.STATIC) == 0 && Parent.PartialContainer.HasExplicitLayout) {
5798 Report.Error (625, Location, "`{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute.", GetSignatureForError ());
5801 base.Emit ();
5804 public static void Error_VariableOfStaticClass (Location loc, string variable_name, Type static_class)
5806 Report.SymbolRelatedToPreviousError (static_class);
5807 Report.Error (723, loc, "`{0}': cannot declare variables of static types",
5808 variable_name);
5811 public Expression Initializer {
5812 set {
5813 if (value != null) {
5814 this.initializer = value;
5819 protected virtual bool IsFieldClsCompliant {
5820 get {
5821 if (FieldBuilder == null)
5822 return true;
5824 return AttributeTester.IsClsCompliant (FieldBuilder.FieldType);
5828 public override string[] ValidAttributeTargets
5830 get {
5831 return attribute_targets;
5835 protected override bool VerifyClsCompliance ()
5837 if (!base.VerifyClsCompliance ())
5838 return false;
5840 if (!IsFieldClsCompliant) {
5841 Report.Error (3003, Location, "Type of `{0}' is not CLS-compliant", GetSignatureForError ());
5843 return true;
5846 public void SetAssigned ()
5848 caching_flags |= Flags.IsAssigned;
5852 interface IFixedBuffer
5854 FieldInfo Element { get; }
5855 Type ElementType { get; }
5858 public class FixedFieldExternal: IFixedBuffer
5860 FieldInfo element_field;
5862 public FixedFieldExternal (FieldInfo fi)
5864 element_field = fi.FieldType.GetField (FixedField.FixedElementName);
5867 #region IFixedField Members
5869 public FieldInfo Element {
5870 get {
5871 return element_field;
5875 public Type ElementType {
5876 get {
5877 return element_field.FieldType;
5881 #endregion
5884 /// <summary>
5885 /// Fixed buffer implementation
5886 /// </summary>
5887 public class FixedField : FieldBase, IFixedBuffer
5889 public const string FixedElementName = "FixedElementField";
5890 static int GlobalCounter = 0;
5891 static object[] ctor_args = new object[] { (short)LayoutKind.Sequential };
5892 static FieldInfo[] fi;
5894 TypeBuilder fixed_buffer_type;
5895 FieldBuilder element;
5896 Expression size_expr;
5897 int buffer_size;
5899 const int AllowedModifiers =
5900 Modifiers.NEW |
5901 Modifiers.PUBLIC |
5902 Modifiers.PROTECTED |
5903 Modifiers.INTERNAL |
5904 Modifiers.PRIVATE;
5906 public FixedField (DeclSpace parent, Expression type, int mod, string name,
5907 Expression size_expr, Attributes attrs, Location loc):
5908 base (parent, type, mod, AllowedModifiers, new MemberName (name, loc), attrs)
5910 if (RootContext.Version == LanguageVersion.ISO_1)
5911 Report.FeatureIsNotISO1 (loc, "fixed size buffers");
5913 this.size_expr = size_expr;
5916 public override bool Define()
5918 #if !NET_2_0
5919 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) != 0)
5920 Report.Warning (-23, 1, Location, "Only private or internal fixed sized buffers are supported by .NET 1.x");
5921 #endif
5923 if (Parent.PartialContainer.Kind != Kind.Struct) {
5924 Report.Error (1642, Location, "`{0}': Fixed size buffer fields may only be members of structs",
5925 GetSignatureForError ());
5926 return false;
5929 if (!base.Define ())
5930 return false;
5932 if (!TypeManager.IsPrimitiveType (MemberType)) {
5933 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",
5934 GetSignatureForError ());
5935 return false;
5938 EmitContext ec = new EmitContext (this, Parent, Location, null, null, ModFlags);
5939 Constant c = size_expr.ResolveAsConstant (ec, this);
5940 if (c == null)
5941 return false;
5943 IntConstant buffer_size_const = c.ImplicitConversionRequired (TypeManager.int32_type, Location) as IntConstant;
5944 if (buffer_size_const == null)
5945 return false;
5947 buffer_size = buffer_size_const.Value;
5949 if (buffer_size <= 0) {
5950 Report.Error (1665, Location, "`{0}': Fixed size buffers must have a length greater than zero", GetSignatureForError ());
5951 return false;
5954 int type_size = Expression.GetTypeSize (MemberType);
5956 if (buffer_size > int.MaxValue / type_size) {
5957 Report.Error (1664, Location, "Fixed size buffer `{0}' of length `{1}' and type `{2}' exceeded 2^31 limit",
5958 GetSignatureForError (), buffer_size.ToString (), TypeManager.CSharpName (MemberType));
5959 return false;
5962 buffer_size *= type_size;
5964 // Define nested
5965 string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++);
5967 fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name,
5968 TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, TypeManager.value_type);
5969 element = fixed_buffer_type.DefineField (FixedElementName, MemberType, FieldAttributes.Public);
5970 RootContext.RegisterCompilerGeneratedType (fixed_buffer_type);
5972 FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, Modifiers.FieldAttr (ModFlags));
5973 TypeManager.RegisterFieldBase (FieldBuilder, this);
5975 return true;
5978 public override void Emit()
5980 if (fi == null)
5981 fi = new FieldInfo [] { TypeManager.struct_layout_attribute_type.GetField ("Size") };
5983 object[] fi_val = new object[1];
5984 fi_val [0] = buffer_size;
5986 CustomAttributeBuilder cab = new CustomAttributeBuilder (TypeManager.struct_layout_attribute_ctor,
5987 ctor_args, fi, fi_val);
5988 fixed_buffer_type.SetCustomAttribute (cab);
5990 #if NET_2_0
5991 cab = new CustomAttributeBuilder (TypeManager.fixed_buffer_attr_ctor, new object[] { MemberType, buffer_size } );
5992 FieldBuilder.SetCustomAttribute (cab);
5993 #endif
5994 base.Emit ();
5997 protected override bool IsFieldClsCompliant {
5998 get {
5999 return false;
6003 #region IFixedField Members
6005 public FieldInfo Element {
6006 get {
6007 return element;
6011 public Type ElementType {
6012 get {
6013 return MemberType;
6017 #endregion
6021 // The Field class is used to represents class/struct fields during parsing.
6023 public class Field : FieldBase {
6024 // <summary>
6025 // Modifiers allowed in a class declaration
6026 // </summary>
6027 const int AllowedModifiers =
6028 Modifiers.NEW |
6029 Modifiers.PUBLIC |
6030 Modifiers.PROTECTED |
6031 Modifiers.INTERNAL |
6032 Modifiers.PRIVATE |
6033 Modifiers.STATIC |
6034 Modifiers.VOLATILE |
6035 Modifiers.UNSAFE |
6036 Modifiers.READONLY;
6038 public Field (DeclSpace parent, Expression type, int mod, string name,
6039 Attributes attrs, Location loc)
6040 : base (parent, type, mod, AllowedModifiers, new MemberName (name, loc),
6041 attrs)
6045 public override bool Define ()
6047 if (!base.Define ())
6048 return false;
6050 if (RootContext.WarningLevel > 1){
6051 Type ptype = Parent.TypeBuilder.BaseType;
6053 // ptype is only null for System.Object while compiling corlib.
6054 if (ptype != null){
6055 TypeContainer.FindMembers (
6056 ptype, MemberTypes.Method,
6057 BindingFlags.Public |
6058 BindingFlags.Static | BindingFlags.Instance,
6059 System.Type.FilterName, Name);
6063 if ((ModFlags & Modifiers.VOLATILE) != 0){
6064 if (!MemberType.IsClass){
6065 Type vt = MemberType;
6067 if (TypeManager.IsEnumType (vt))
6068 vt = TypeManager.EnumToUnderlying (MemberType);
6070 if (!((vt == TypeManager.bool_type) ||
6071 (vt == TypeManager.sbyte_type) ||
6072 (vt == TypeManager.byte_type) ||
6073 (vt == TypeManager.short_type) ||
6074 (vt == TypeManager.ushort_type) ||
6075 (vt == TypeManager.int32_type) ||
6076 (vt == TypeManager.uint32_type) ||
6077 (vt == TypeManager.char_type) ||
6078 (vt == TypeManager.float_type) ||
6079 (!vt.IsValueType))){
6080 Report.Error (677, Location, "`{0}': A volatile field cannot be of the type `{1}'",
6081 GetSignatureForError (), TypeManager.CSharpName (vt));
6082 return false;
6086 if ((ModFlags & Modifiers.READONLY) != 0){
6087 Report.Error (678, Location, "`{0}': A field cannot be both volatile and readonly",
6088 GetSignatureForError ());
6089 return false;
6093 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
6095 if (Parent.PartialContainer.Kind == Kind.Struct &&
6096 ((fa & FieldAttributes.Static) == 0) &&
6097 MemberType == Parent.TypeBuilder &&
6098 !TypeManager.IsBuiltinType (MemberType)){
6099 Report.Error (523, Location, "Struct member `" + Parent.Name + "." + Name +
6100 "' causes a cycle in the structure layout");
6101 return false;
6104 try {
6105 FieldBuilder = Parent.TypeBuilder.DefineField (
6106 Name, MemberType, Modifiers.FieldAttr (ModFlags));
6108 TypeManager.RegisterFieldBase (FieldBuilder, this);
6110 catch (ArgumentException) {
6111 Report.Warning (-24, 1, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
6112 return false;
6115 if (initializer != null)
6116 Parent.PartialContainer.RegisterFieldForInitialization (this,
6117 new FieldInitializer (FieldBuilder, initializer, Parent));
6119 return true;
6122 protected override bool VerifyClsCompliance ()
6124 if (!base.VerifyClsCompliance ())
6125 return false;
6127 if ((ModFlags & Modifiers.VOLATILE) != 0) {
6128 Report.Warning (3026, 1, Location, "CLS-compliant field `{0}' cannot be volatile", GetSignatureForError ());
6131 return true;
6136 // `set' and `get' accessors are represented with an Accessor.
6138 public class Accessor : IAnonymousHost {
6140 // Null if the accessor is empty, or a Block if not
6142 public const int AllowedModifiers =
6143 Modifiers.PUBLIC |
6144 Modifiers.PROTECTED |
6145 Modifiers.INTERNAL |
6146 Modifiers.PRIVATE;
6148 public ToplevelBlock Block;
6149 public Attributes Attributes;
6150 public Location Location;
6151 public int ModFlags;
6152 public bool Yields;
6153 public ArrayList AnonymousMethods;
6155 public Accessor (ToplevelBlock b, int mod, Attributes attrs, Location loc)
6157 Block = b;
6158 Attributes = attrs;
6159 Location = loc;
6160 ModFlags = Modifiers.Check (AllowedModifiers, mod, 0, loc);
6163 public void SetYields ()
6165 Yields = true;
6168 public void AddAnonymousMethod (AnonymousMethodExpression ame)
6170 if (AnonymousMethods == null)
6171 AnonymousMethods = new ArrayList ();
6172 AnonymousMethods.Add (ame);
6176 // Ooouh Martin, templates are missing here.
6177 // When it will be possible move here a lot of child code and template method type.
6178 public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData {
6179 protected MethodData method_data;
6180 protected ToplevelBlock block;
6181 protected ListDictionary declarative_security;
6183 // The accessor are created event if they are not wanted.
6184 // But we need them because their names are reserved.
6185 // Field says whether accessor will be emited or not
6186 public readonly bool IsDummy;
6188 protected readonly string prefix;
6190 ReturnParameter return_attributes;
6192 public AbstractPropertyEventMethod (PropertyBasedMember member, string prefix)
6193 : base (member.Parent, SetupName (prefix, member, member.Location), null)
6195 this.prefix = prefix;
6196 IsDummy = true;
6199 public AbstractPropertyEventMethod (InterfaceMemberBase member, Accessor accessor,
6200 string prefix)
6201 : base (member.Parent, SetupName (prefix, member, accessor.Location),
6202 accessor.Attributes)
6204 this.prefix = prefix;
6205 this.block = accessor.Block;
6208 static MemberName SetupName (string prefix, InterfaceMemberBase member, Location loc)
6210 return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc);
6213 public void UpdateName (InterfaceMemberBase member)
6215 SetMemberName (SetupName (prefix, member, Location));
6218 #region IMethodData Members
6220 public abstract Iterator Iterator {
6221 get;
6224 public ToplevelBlock Block {
6225 get {
6226 return block;
6229 set {
6230 block = value;
6234 public CallingConventions CallingConventions {
6235 get {
6236 return CallingConventions.Standard;
6240 public bool IsExcluded ()
6242 return false;
6245 GenericMethod IMethodData.GenericMethod {
6246 get {
6247 return null;
6251 public MemberName MethodName {
6252 get {
6253 return MemberName;
6257 public Type[] ParameterTypes {
6258 get {
6259 return ParameterInfo.Types;
6263 public abstract Parameters ParameterInfo { get ; }
6264 public abstract Type ReturnType { get; }
6265 public abstract EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig);
6267 #endregion
6269 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
6271 if (a.Type == TypeManager.cls_compliant_attribute_type || a.Type == TypeManager.obsolete_attribute_type ||
6272 a.Type == TypeManager.conditional_attribute_type) {
6273 Report.Error (1667, a.Location,
6274 "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
6275 TypeManager.CSharpName (a.Type), a.GetValidTargets ());
6276 return;
6279 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
6280 if (declarative_security == null)
6281 declarative_security = new ListDictionary ();
6282 a.ExtractSecurityPermissionSet (declarative_security);
6283 return;
6286 if (a.Target == AttributeTargets.Method) {
6287 method_data.MethodBuilder.SetCustomAttribute (cb);
6288 return;
6291 if (a.Target == AttributeTargets.ReturnValue) {
6292 if (return_attributes == null)
6293 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
6295 return_attributes.ApplyAttributeBuilder (a, cb);
6296 return;
6299 ApplyToExtraTarget (a, cb);
6302 virtual protected void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb)
6304 System.Diagnostics.Debug.Fail ("You forgot to define special attribute target handling");
6307 // It is not supported for the accessors
6308 public sealed override bool Define()
6310 throw new NotSupportedException ();
6313 public void Emit (DeclSpace parent)
6315 EmitMethod (parent);
6317 #if GMCS_SOURCE
6318 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0)
6319 method_data.MethodBuilder.SetCustomAttribute (TypeManager.compiler_generated_attr);
6320 #endif
6321 if (OptAttributes != null)
6322 OptAttributes.Emit ();
6324 if (declarative_security != null) {
6325 foreach (DictionaryEntry de in declarative_security) {
6326 method_data.MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
6330 block = null;
6333 protected virtual void EmitMethod (DeclSpace parent)
6335 method_data.Emit (parent);
6338 public override bool IsClsComplianceRequired()
6340 return false;
6343 public bool IsDuplicateImplementation (MethodCore method)
6345 if (!MemberName.Equals (method.MemberName))
6346 return false;
6348 Type[] param_types = method.ParameterTypes;
6350 if (param_types == null || param_types.Length != ParameterTypes.Length)
6351 return false;
6353 for (int i = 0; i < param_types.Length; i++)
6354 if (param_types [i] != ParameterTypes [i])
6355 return false;
6357 Report.SymbolRelatedToPreviousError (method);
6358 Report.Error (111, Location, TypeContainer.Error111, method.GetSignatureForError ());
6359 return true;
6362 public override bool IsUsed
6364 get {
6365 if (IsDummy)
6366 return false;
6368 return base.IsUsed;
6372 public new Location Location {
6373 get {
6374 return base.Location;
6378 public virtual bool ResolveMembers ()
6380 return true;
6384 // Represents header string for documentation comment.
6386 public override string DocCommentHeader {
6387 get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
6393 // Properties and Indexers both generate PropertyBuilders, we use this to share
6394 // their common bits.
6396 abstract public class PropertyBase : PropertyBasedMember {
6398 public class GetMethod : PropertyMethod
6400 static string[] attribute_targets = new string [] { "method", "return" };
6402 public GetMethod (PropertyBase method):
6403 base (method, "get_")
6407 public GetMethod (PropertyBase method, Accessor accessor):
6408 base (method, accessor, "get_")
6412 public override MethodBuilder Define (DeclSpace parent)
6414 if (!CheckForDuplications ())
6415 return null;
6417 if (IsDummy)
6418 return null;
6420 base.Define (parent);
6422 method_data = new MethodData (method, ModFlags, flags, this);
6424 if (!method_data.Define (parent))
6425 return null;
6427 return method_data.MethodBuilder;
6430 public override Type ReturnType {
6431 get {
6432 return method.MemberType;
6436 public override Parameters ParameterInfo {
6437 get {
6438 return Parameters.EmptyReadOnlyParameters;
6442 public override string[] ValidAttributeTargets {
6443 get {
6444 return attribute_targets;
6449 public class SetMethod : PropertyMethod {
6451 static string[] attribute_targets = new string [] { "method", "param", "return" };
6452 ImplicitParameter param_attr;
6453 protected Parameters parameters;
6455 public SetMethod (PropertyBase method):
6456 base (method, "set_")
6460 public SetMethod (PropertyBase method, Accessor accessor):
6461 base (method, accessor, "set_")
6465 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
6467 if (a.Target == AttributeTargets.Parameter) {
6468 if (param_attr == null)
6469 param_attr = new ImplicitParameter (method_data.MethodBuilder);
6471 param_attr.ApplyAttributeBuilder (a, cb);
6472 return;
6475 base.ApplyAttributeBuilder (a, cb);
6478 public override Parameters ParameterInfo {
6479 get {
6480 if (parameters == null)
6481 DefineParameters ();
6482 return parameters;
6486 protected virtual void DefineParameters ()
6488 parameters = new Parameters (
6489 new Parameter[] { new Parameter (method.MemberType, "value", Parameter.Modifier.NONE, null, Location) },
6490 new Type[] { method.MemberType });
6493 public override MethodBuilder Define (DeclSpace parent)
6495 if (!CheckForDuplications ())
6496 return null;
6498 if (IsDummy)
6499 return null;
6501 base.Define (parent);
6503 method_data = new MethodData (method, ModFlags, flags, this);
6505 if (!method_data.Define (parent))
6506 return null;
6508 return method_data.MethodBuilder;
6511 public override Type ReturnType {
6512 get {
6513 return TypeManager.void_type;
6517 public override string[] ValidAttributeTargets {
6518 get {
6519 return attribute_targets;
6524 static string[] attribute_targets = new string [] { "property" };
6526 public abstract class PropertyMethod : AbstractPropertyEventMethod
6528 protected readonly PropertyBase method;
6529 protected MethodAttributes flags;
6530 Iterator iterator;
6531 ArrayList anonymous_methods;
6532 bool yields;
6534 public PropertyMethod (PropertyBase method, string prefix)
6535 : base (method, prefix)
6537 this.method = method;
6540 public PropertyMethod (PropertyBase method, Accessor accessor,
6541 string prefix)
6542 : base (method, accessor, prefix)
6544 this.method = method;
6545 this.ModFlags = accessor.ModFlags;
6546 yields = accessor.Yields;
6547 anonymous_methods = accessor.AnonymousMethods;
6549 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
6550 Report.FeatureIsNotISO1 (Location, "access modifiers on properties");
6554 public override Iterator Iterator {
6555 get { return iterator; }
6558 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6560 if (a.IsInternalMethodImplAttribute) {
6561 method.is_external_implementation = true;
6564 base.ApplyAttributeBuilder (a, cb);
6567 public override AttributeTargets AttributeTargets {
6568 get {
6569 return AttributeTargets.Method;
6573 public override bool IsClsComplianceRequired ()
6575 return method.IsClsComplianceRequired ();
6578 public override bool ResolveMembers ()
6580 if (yields) {
6581 iterator = Iterator.CreateIterator (this, Parent, null, ModFlags);
6582 if (iterator == null)
6583 return false;
6586 if (anonymous_methods != null) {
6587 foreach (AnonymousMethodExpression ame in anonymous_methods) {
6588 if (!ame.CreateAnonymousHelpers ())
6589 return false;
6593 return true;
6596 public virtual MethodBuilder Define (DeclSpace parent)
6598 if (!method.CheckAbstractAndExtern (block != null))
6599 return null;
6601 TypeContainer container = parent.PartialContainer;
6604 // Check for custom access modifier
6606 if ((ModFlags & Modifiers.Accessibility) == 0) {
6607 ModFlags |= method.ModFlags;
6608 flags = method.flags;
6609 } else {
6610 if (container.Kind == Kind.Interface)
6611 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
6612 GetSignatureForError ());
6614 if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
6615 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
6618 CheckModifiers (ModFlags);
6619 ModFlags |= (method.ModFlags & (~Modifiers.Accessibility));
6620 ModFlags |= Modifiers.PROPERTY_CUSTOM;
6621 flags = Modifiers.MethodAttr (ModFlags);
6622 flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
6625 return null;
6628 public bool HasCustomAccessModifier
6630 get {
6631 return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
6635 public override EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
6637 return new EmitContext (method,
6638 ds, method.ds, method.Location, ig, ReturnType,
6639 method.ModFlags, false);
6642 public override ObsoleteAttribute GetObsoleteAttribute ()
6644 return method.GetObsoleteAttribute ();
6647 public override string GetSignatureForError()
6649 return method.GetSignatureForError () + '.' + prefix.Substring (0, 3);
6652 void CheckModifiers (int modflags)
6654 modflags &= Modifiers.Accessibility;
6655 int flags = 0;
6656 int mflags = method.ModFlags & Modifiers.Accessibility;
6658 if ((mflags & Modifiers.PUBLIC) != 0) {
6659 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
6661 else if ((mflags & Modifiers.PROTECTED) != 0) {
6662 if ((mflags & Modifiers.INTERNAL) != 0)
6663 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL;
6665 flags |= Modifiers.PRIVATE;
6667 else if ((mflags & Modifiers.INTERNAL) != 0)
6668 flags |= Modifiers.PRIVATE;
6670 if ((mflags == modflags) || (modflags & (~flags)) != 0) {
6671 Report.Error (273, Location,
6672 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
6673 GetSignatureForError (), method.GetSignatureForError ());
6677 public override bool MarkForDuplicationCheck ()
6679 caching_flags |= Flags.TestMethodDuplication;
6680 return true;
6683 protected bool CheckForDuplications ()
6685 if ((caching_flags & Flags.TestMethodDuplication) == 0)
6686 return true;
6688 ArrayList ar = Parent.PartialContainer.Methods;
6689 if (ar != null) {
6690 int arLen = ar.Count;
6692 for (int i = 0; i < arLen; i++) {
6693 Method m = (Method) ar [i];
6694 if (IsDuplicateImplementation (m))
6695 return false;
6699 return true;
6703 public PropertyMethod Get, Set;
6704 public PropertyBuilder PropertyBuilder;
6705 public MethodBuilder GetBuilder, SetBuilder;
6707 protected bool define_set_first = false;
6709 public PropertyBase (DeclSpace parent, Expression type, int mod_flags,
6710 int allowed_mod, bool is_iface, MemberName name,
6711 Attributes attrs, bool define_set_first)
6712 : base (parent, null, type, mod_flags, allowed_mod, is_iface, name, attrs)
6714 this.define_set_first = define_set_first;
6717 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6719 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
6720 a.Error_InvalidSecurityParent ();
6721 return;
6724 PropertyBuilder.SetCustomAttribute (cb);
6727 public override AttributeTargets AttributeTargets {
6728 get {
6729 return AttributeTargets.Property;
6733 public override bool Define ()
6735 if (!DoDefine ())
6736 return false;
6738 if (!IsTypePermitted ())
6739 return false;
6741 return true;
6744 protected override bool DoDefine ()
6746 if (!base.DoDefine ())
6747 return false;
6750 // Accessors modifiers check
6752 if ((Get.ModFlags & Modifiers.Accessibility) != 0 &&
6753 (Set.ModFlags & Modifiers.Accessibility) != 0) {
6754 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
6755 GetSignatureForError ());
6756 return false;
6759 if ((Get.IsDummy || Set.IsDummy)
6760 && (Get.ModFlags != 0 || Set.ModFlags != 0) && (ModFlags & Modifiers.OVERRIDE) == 0) {
6761 Report.Error (276, Location,
6762 "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
6763 GetSignatureForError ());
6764 return false;
6767 if (MemberType.IsAbstract && MemberType.IsSealed) {
6768 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
6769 return false;
6772 return true;
6775 bool DefineGet ()
6777 GetBuilder = Get.Define (Parent);
6778 return (Get.IsDummy) ? true : GetBuilder != null;
6781 bool DefineSet (bool define)
6783 if (!define)
6784 return true;
6786 SetBuilder = Set.Define (Parent);
6787 return (Set.IsDummy) ? true : SetBuilder != null;
6790 protected bool DefineAccessors ()
6792 return DefineSet (define_set_first) &&
6793 DefineGet () &&
6794 DefineSet (!define_set_first);
6797 protected abstract PropertyInfo ResolveBaseProperty ();
6799 // TODO: rename to Resolve......
6800 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
6802 PropertyInfo base_property = ResolveBaseProperty ();
6803 if (base_property == null)
6804 return null;
6806 base_ret_type = base_property.PropertyType;
6807 MethodInfo get_accessor = base_property.GetGetMethod (true);
6808 MethodInfo set_accessor = base_property.GetSetMethod (true);
6809 MethodAttributes get_accessor_access, set_accessor_access;
6811 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
6812 if (Get != null && !Get.IsDummy && get_accessor == null) {
6813 Report.SymbolRelatedToPreviousError (base_property);
6814 Report.Error (545, Location, "`{0}.get': cannot override because `{1}' does not have an overridable get accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6817 if (Set != null && !Set.IsDummy && set_accessor == null) {
6818 Report.SymbolRelatedToPreviousError (base_property);
6819 Report.Error (546, Location, "`{0}.set': cannot override because `{1}' does not have an overridable set accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6824 // Check base class accessors access
6827 // TODO: rewrite to reuse Get|Set.CheckAccessModifiers and share code there
6828 get_accessor_access = set_accessor_access = 0;
6829 if ((ModFlags & Modifiers.NEW) == 0) {
6830 if (get_accessor != null) {
6831 MethodAttributes get_flags = Modifiers.MethodAttr (Get.ModFlags != 0 ? Get.ModFlags : ModFlags);
6832 get_accessor_access = (get_accessor.Attributes & MethodAttributes.MemberAccessMask);
6834 if (!Get.IsDummy && !CheckAccessModifiers (get_flags & MethodAttributes.MemberAccessMask, get_accessor_access, get_accessor))
6835 Error_CannotChangeAccessModifiers (get_accessor, get_accessor_access, ".get");
6838 if (set_accessor != null) {
6839 MethodAttributes set_flags = Modifiers.MethodAttr (Set.ModFlags != 0 ? Set.ModFlags : ModFlags);
6840 set_accessor_access = (set_accessor.Attributes & MethodAttributes.MemberAccessMask);
6842 if (!Set.IsDummy && !CheckAccessModifiers (set_flags & MethodAttributes.MemberAccessMask, set_accessor_access, set_accessor))
6843 Error_CannotChangeAccessModifiers (set_accessor, set_accessor_access, ".set");
6847 // When one accessor does not exist and property hides base one
6848 // we need to propagate this upwards
6849 if (set_accessor == null)
6850 set_accessor = get_accessor;
6853 // Get the less restrictive access
6855 return get_accessor_access > set_accessor_access ? get_accessor : set_accessor;
6858 public override void Emit ()
6861 // The PropertyBuilder can be null for explicit implementations, in that
6862 // case, we do not actually emit the ".property", so there is nowhere to
6863 // put the attribute
6865 if (PropertyBuilder != null && OptAttributes != null)
6866 OptAttributes.Emit ();
6868 if (!Get.IsDummy)
6869 Get.Emit (Parent);
6871 if (!Set.IsDummy)
6872 Set.Emit (Parent);
6874 base.Emit ();
6877 /// <summary>
6878 /// Tests whether accessors are not in collision with some method (CS0111)
6879 /// </summary>
6880 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6882 return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
6885 public override bool IsUsed
6887 get {
6888 if (IsExplicitImpl)
6889 return true;
6891 return Get.IsUsed | Set.IsUsed;
6895 protected override void SetMemberName (MemberName new_name)
6897 base.SetMemberName (new_name);
6899 Get.UpdateName (this);
6900 Set.UpdateName (this);
6903 public override string[] ValidAttributeTargets {
6904 get {
6905 return attribute_targets;
6910 // Represents header string for documentation comment.
6912 public override string DocCommentHeader {
6913 get { return "P:"; }
6917 public class Property : PropertyBase {
6918 const int AllowedModifiers =
6919 Modifiers.NEW |
6920 Modifiers.PUBLIC |
6921 Modifiers.PROTECTED |
6922 Modifiers.INTERNAL |
6923 Modifiers.PRIVATE |
6924 Modifiers.STATIC |
6925 Modifiers.SEALED |
6926 Modifiers.OVERRIDE |
6927 Modifiers.ABSTRACT |
6928 Modifiers.UNSAFE |
6929 Modifiers.EXTERN |
6930 Modifiers.METHOD_YIELDS |
6931 Modifiers.VIRTUAL;
6933 const int AllowedInterfaceModifiers =
6934 Modifiers.NEW;
6936 void CreateAutomaticProperty (Block block, Accessor get_block, Accessor set_block)
6938 // Make the field
6939 Field field = new Field (
6940 Parent, Type,
6941 Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & Modifiers.STATIC),
6942 CompilerGeneratedClass.MakeName ("CompilerGeneratedField"),
6943 null, Location);
6944 ((TypeContainer)Parent).AddField (field);
6946 // Make get block
6947 get_block.Block = new ToplevelBlock (block, null, Location);
6948 Return r = new Return (new SimpleName(field.Name, Location), Location);
6949 get_block.Block.AddStatement (r);
6950 get_block.ModFlags |= Modifiers.COMPILER_GENERATED;
6952 // Make set block
6953 Parameters parameters = new Parameters (new Parameter (Type, "value", Parameter.Modifier.NONE, null, Location));
6954 set_block.Block = new ToplevelBlock (block, parameters, Location);
6955 Assign a = new Assign (new SimpleName(field.Name, Location), new SimpleName ("value", Location));
6956 set_block.Block.AddStatement (new StatementExpression(a));
6957 set_block.ModFlags |= Modifiers.COMPILER_GENERATED;
6960 public Property (DeclSpace parent, Expression type, int mod, bool is_iface,
6961 MemberName name, Attributes attrs, Accessor get_block,
6962 Accessor set_block, bool define_set_first)
6963 : this (parent, type, mod, is_iface, name, attrs, get_block, set_block,
6964 define_set_first, null)
6968 public Property (DeclSpace parent, Expression type, int mod, bool is_iface,
6969 MemberName name, Attributes attrs, Accessor get_block,
6970 Accessor set_block, bool define_set_first, Block current_block)
6971 : base (parent, type, mod,
6972 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6973 is_iface, name, attrs, define_set_first)
6975 if (RootContext.Version >= LanguageVersion.LINQ &&
6976 !is_iface &&
6977 (mod & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
6978 get_block != null && get_block.Block == null &&
6979 set_block != null && set_block.Block == null)
6980 CreateAutomaticProperty (current_block, get_block, set_block);
6982 if (get_block == null)
6983 Get = new GetMethod (this);
6984 else
6985 Get = new GetMethod (this, get_block);
6987 if (set_block == null)
6988 Set = new SetMethod (this);
6989 else
6990 Set = new SetMethod (this, set_block);
6993 public override bool Define ()
6995 if (!DoDefineBase ())
6996 return false;
6998 if (!base.Define ())
6999 return false;
7001 if (!CheckBase ())
7002 return false;
7004 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
7006 if (!DefineAccessors ())
7007 return false;
7009 // FIXME - PropertyAttributes.HasDefault ?
7011 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
7012 MemberName.ToString (), PropertyAttributes.None, MemberType, null);
7014 if (!Get.IsDummy)
7015 PropertyBuilder.SetGetMethod (GetBuilder);
7017 if (!Set.IsDummy)
7018 PropertyBuilder.SetSetMethod (SetBuilder);
7020 TypeManager.RegisterProperty (PropertyBuilder, this);
7021 return true;
7024 protected override PropertyInfo ResolveBaseProperty ()
7026 return Parent.PartialContainer.BaseCache.FindMemberToOverride (
7027 Parent.TypeBuilder, Name, Parameters.EmptyReadOnlyParameters.Types, null, true) as PropertyInfo;
7031 /// </summary>
7032 /// Gigantic workaround for lameness in SRE follows :
7033 /// This class derives from EventInfo and attempts to basically
7034 /// wrap around the EventBuilder so that FindMembers can quickly
7035 /// return this in it search for members
7036 /// </summary>
7037 public class MyEventBuilder : EventInfo {
7040 // We use this to "point" to our Builder which is
7041 // not really a MemberInfo
7043 EventBuilder MyBuilder;
7046 // We "catch" and wrap these methods
7048 MethodInfo raise, remove, add;
7050 EventAttributes attributes;
7051 Type declaring_type, reflected_type, event_type;
7052 string name;
7054 Event my_event;
7056 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
7058 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
7060 // And now store the values in our own fields.
7062 declaring_type = type_builder;
7064 reflected_type = type_builder;
7066 attributes = event_attr;
7067 this.name = name;
7068 my_event = ev;
7069 this.event_type = event_type;
7073 // Methods that you have to override. Note that you only need
7074 // to "implement" the variants that take the argument (those are
7075 // the "abstract" methods, the others (GetAddMethod()) are
7076 // regular.
7078 public override MethodInfo GetAddMethod (bool nonPublic)
7080 return add;
7083 public override MethodInfo GetRemoveMethod (bool nonPublic)
7085 return remove;
7088 public override MethodInfo GetRaiseMethod (bool nonPublic)
7090 return raise;
7094 // These methods make "MyEventInfo" look like a Builder
7096 public void SetRaiseMethod (MethodBuilder raiseMethod)
7098 raise = raiseMethod;
7099 MyBuilder.SetRaiseMethod (raiseMethod);
7102 public void SetRemoveOnMethod (MethodBuilder removeMethod)
7104 remove = removeMethod;
7105 MyBuilder.SetRemoveOnMethod (removeMethod);
7108 public void SetAddOnMethod (MethodBuilder addMethod)
7110 add = addMethod;
7111 MyBuilder.SetAddOnMethod (addMethod);
7114 public void SetCustomAttribute (CustomAttributeBuilder cb)
7116 MyBuilder.SetCustomAttribute (cb);
7119 public override object [] GetCustomAttributes (bool inherit)
7121 // FIXME : There's nothing which can be seemingly done here because
7122 // we have no way of getting at the custom attribute objects of the
7123 // EventBuilder !
7124 return null;
7127 public override object [] GetCustomAttributes (Type t, bool inherit)
7129 // FIXME : Same here !
7130 return null;
7133 public override bool IsDefined (Type t, bool b)
7135 return true;
7138 public override EventAttributes Attributes {
7139 get {
7140 return attributes;
7144 public override string Name {
7145 get {
7146 return name;
7150 public override Type DeclaringType {
7151 get {
7152 return declaring_type;
7156 public override Type ReflectedType {
7157 get {
7158 return reflected_type;
7162 public Type EventType {
7163 get {
7164 return event_type;
7168 public void SetUsed ()
7170 if (my_event != null) {
7171 // my_event.SetAssigned ();
7172 my_event.SetMemberIsUsed ();
7177 /// <summary>
7178 /// For case when event is declared like property (with add and remove accessors).
7179 /// </summary>
7180 public class EventProperty: Event {
7181 abstract class AEventPropertyAccessor : AEventAccessor
7183 readonly ArrayList anonymous_methods;
7185 public AEventPropertyAccessor (Event method, Accessor accessor, string prefix):
7186 base (method, accessor, prefix)
7188 this.anonymous_methods = accessor.AnonymousMethods;
7191 public override MethodBuilder Define (DeclSpace ds)
7193 method.CheckAbstractAndExtern (block != null);
7194 return base.Define (ds);
7197 public override bool ResolveMembers ()
7199 if (anonymous_methods == null)
7200 return true;
7202 foreach (AnonymousMethodExpression ame in anonymous_methods) {
7203 if (!ame.CreateAnonymousHelpers ())
7204 return false;
7207 return true;
7212 sealed class AddDelegateMethod: AEventPropertyAccessor
7214 public AddDelegateMethod (Event method, Accessor accessor):
7215 base (method, accessor, "add_")
7219 protected override MethodInfo DelegateMethodInfo {
7220 get {
7221 return TypeManager.delegate_combine_delegate_delegate;
7226 sealed class RemoveDelegateMethod: AEventPropertyAccessor
7228 public RemoveDelegateMethod (Event method, Accessor accessor):
7229 base (method, accessor, "remove_")
7233 protected override MethodInfo DelegateMethodInfo {
7234 get {
7235 return TypeManager.delegate_remove_delegate_delegate;
7241 static readonly string[] attribute_targets = new string [] { "event" }; // "property" target was disabled for 2.0 version
7243 public EventProperty (DeclSpace parent, Expression type, int mod_flags,
7244 bool is_iface, MemberName name,
7245 Attributes attrs, Accessor add, Accessor remove)
7246 : base (parent, type, mod_flags, is_iface, name, attrs)
7248 Add = new AddDelegateMethod (this, add);
7249 Remove = new RemoveDelegateMethod (this, remove);
7252 public override bool Define()
7254 if (!base.Define ())
7255 return false;
7257 if (IsExplicitImpl)
7258 SetMemberIsUsed ();
7260 return true;
7263 public override string[] ValidAttributeTargets {
7264 get {
7265 return attribute_targets;
7270 /// <summary>
7271 /// Event is declared like field.
7272 /// </summary>
7273 public class EventField : Event {
7274 abstract class EventFieldAccessor : AEventAccessor
7276 protected EventFieldAccessor (Event method, string prefix)
7277 : base (method, prefix)
7281 protected override void EmitMethod(DeclSpace parent)
7283 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
7284 return;
7286 MethodBuilder mb = method_data.MethodBuilder;
7287 ILGenerator ig = mb.GetILGenerator ();
7289 // TODO: because we cannot use generics yet
7290 FieldInfo field_info = ((EventField)method).FieldBuilder;
7292 mb.SetImplementationFlags (mb.GetMethodImplementationFlags () | MethodImplAttributes.Synchronized);
7293 if ((method.ModFlags & Modifiers.STATIC) != 0) {
7294 ig.Emit (OpCodes.Ldsfld, field_info);
7295 ig.Emit (OpCodes.Ldarg_0);
7296 ig.Emit (OpCodes.Call, DelegateMethodInfo);
7297 ig.Emit (OpCodes.Castclass, method.MemberType);
7298 ig.Emit (OpCodes.Stsfld, field_info);
7299 } else {
7300 ig.Emit (OpCodes.Ldarg_0);
7301 ig.Emit (OpCodes.Ldarg_0);
7302 ig.Emit (OpCodes.Ldfld, field_info);
7303 ig.Emit (OpCodes.Ldarg_1);
7304 ig.Emit (OpCodes.Call, DelegateMethodInfo);
7305 ig.Emit (OpCodes.Castclass, method.MemberType);
7306 ig.Emit (OpCodes.Stfld, field_info);
7308 ig.Emit (OpCodes.Ret);
7312 sealed class AddDelegateMethod: EventFieldAccessor
7314 public AddDelegateMethod (Event method):
7315 base (method, "add_")
7319 protected override MethodInfo DelegateMethodInfo {
7320 get {
7321 return TypeManager.delegate_combine_delegate_delegate;
7326 sealed class RemoveDelegateMethod: EventFieldAccessor
7328 public RemoveDelegateMethod (Event method):
7329 base (method, "remove_")
7333 protected override MethodInfo DelegateMethodInfo {
7334 get {
7335 return TypeManager.delegate_remove_delegate_delegate;
7341 static readonly string[] attribute_targets = new string [] { "event", "field", "method" };
7342 static readonly string[] attribute_targets_interface = new string[] { "event", "method" };
7344 public FieldBuilder FieldBuilder;
7345 public Expression Initializer;
7347 public EventField (DeclSpace parent, Expression type, int mod_flags,
7348 bool is_iface, MemberName name,
7349 Attributes attrs)
7350 : base (parent, type, mod_flags, is_iface, name, attrs)
7352 Add = new AddDelegateMethod (this);
7353 Remove = new RemoveDelegateMethod (this);
7356 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7358 if (a.Target == AttributeTargets.Field) {
7359 FieldBuilder.SetCustomAttribute (cb);
7360 return;
7363 if (a.Target == AttributeTargets.Method) {
7364 int errors = Report.Errors;
7365 Add.ApplyAttributeBuilder (a, cb);
7366 if (errors == Report.Errors)
7367 Remove.ApplyAttributeBuilder (a, cb);
7368 return;
7371 base.ApplyAttributeBuilder (a, cb);
7374 public override bool Define()
7376 if (!base.Define ())
7377 return false;
7379 if (IsInterface)
7380 return true;
7382 // FIXME: We are unable to detect whether generic event is used because
7383 // we are using FieldExpr instead of EventExpr for event access in that
7384 // case. When this issue will be fixed this hack can be removed.
7385 if (TypeManager.IsGenericType (MemberType))
7386 SetMemberIsUsed();
7388 FieldBuilder = Parent.TypeBuilder.DefineField (
7389 Name, MemberType,
7390 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
7391 TypeManager.RegisterEventField (EventBuilder, this);
7393 if (Initializer != null) {
7394 if (((ModFlags & Modifiers.ABSTRACT) != 0)) {
7395 Report.Error (74, Location, "`{0}': abstract event cannot have an initializer",
7396 GetSignatureForError ());
7397 return false;
7400 Parent.PartialContainer.RegisterFieldForInitialization (this,
7401 new FieldInitializer (FieldBuilder, Initializer, Parent));
7404 return true;
7407 public override string[] ValidAttributeTargets
7409 get {
7410 return IsInterface ? attribute_targets_interface : attribute_targets;
7415 public abstract class Event : PropertyBasedMember {
7416 public abstract class AEventAccessor : AbstractPropertyEventMethod
7418 protected readonly Event method;
7419 ImplicitParameter param_attr;
7421 static readonly string[] attribute_targets = new string [] { "method", "param", "return" };
7423 protected AEventAccessor (Event method, string prefix)
7424 : base (method, prefix)
7426 this.method = method;
7429 protected AEventAccessor (Event method, Accessor accessor, string prefix)
7430 : base (method, accessor, prefix)
7432 this.method = method;
7435 public override Iterator Iterator {
7436 get { return null; }
7439 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7441 if (a.IsInternalMethodImplAttribute) {
7442 method.is_external_implementation = true;
7445 base.ApplyAttributeBuilder (a, cb);
7448 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
7450 if (a.Target == AttributeTargets.Parameter) {
7451 if (param_attr == null)
7452 param_attr = new ImplicitParameter (method_data.MethodBuilder);
7454 param_attr.ApplyAttributeBuilder (a, cb);
7455 return;
7458 base.ApplyAttributeBuilder (a, cb);
7461 public override AttributeTargets AttributeTargets {
7462 get {
7463 return AttributeTargets.Method;
7467 public override bool IsClsComplianceRequired ()
7469 return method.IsClsComplianceRequired ();
7472 public virtual MethodBuilder Define (DeclSpace parent)
7474 method_data = new MethodData (method, method.ModFlags,
7475 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
7477 if (!method_data.Define (parent))
7478 return null;
7480 MethodBuilder mb = method_data.MethodBuilder;
7481 ParameterInfo.ApplyAttributes (mb);
7482 return mb;
7485 protected abstract MethodInfo DelegateMethodInfo { get; }
7487 public override Type ReturnType {
7488 get {
7489 return TypeManager.void_type;
7493 public override EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
7495 return new EmitContext (
7496 ds, method.Parent, Location, ig, ReturnType,
7497 method.ModFlags, false);
7500 public override ObsoleteAttribute GetObsoleteAttribute ()
7502 return method.GetObsoleteAttribute ();
7505 public override string[] ValidAttributeTargets {
7506 get {
7507 return attribute_targets;
7511 public override Parameters ParameterInfo {
7512 get {
7513 return method.parameters;
7519 const int AllowedModifiers =
7520 Modifiers.NEW |
7521 Modifiers.PUBLIC |
7522 Modifiers.PROTECTED |
7523 Modifiers.INTERNAL |
7524 Modifiers.PRIVATE |
7525 Modifiers.STATIC |
7526 Modifiers.VIRTUAL |
7527 Modifiers.SEALED |
7528 Modifiers.OVERRIDE |
7529 Modifiers.UNSAFE |
7530 Modifiers.ABSTRACT |
7531 Modifiers.EXTERN;
7533 const int AllowedInterfaceModifiers =
7534 Modifiers.NEW;
7536 public AEventAccessor Add, Remove;
7537 public MyEventBuilder EventBuilder;
7538 public MethodBuilder AddBuilder, RemoveBuilder;
7540 Parameters parameters;
7542 protected Event (DeclSpace parent, Expression type, int mod_flags,
7543 bool is_iface, MemberName name, Attributes attrs)
7544 : base (parent, null, type, mod_flags,
7545 is_iface ? AllowedInterfaceModifiers : AllowedModifiers, is_iface,
7546 name, attrs)
7550 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7552 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
7553 a.Error_InvalidSecurityParent ();
7554 return;
7557 EventBuilder.SetCustomAttribute (cb);
7560 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
7562 return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
7565 public override AttributeTargets AttributeTargets {
7566 get {
7567 return AttributeTargets.Event;
7571 public override bool Define ()
7573 if (!DoDefineBase ())
7574 return false;
7576 if (!DoDefine ())
7577 return false;
7579 if (!TypeManager.IsDelegateType (MemberType)) {
7580 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
7581 return false;
7584 parameters = new Parameters (
7585 new Parameter[] { new Parameter (MemberType, "value", Parameter.Modifier.NONE, null, Location) },
7586 new Type[] { MemberType } );
7588 if (!CheckBase ())
7589 return false;
7592 // Now define the accessors
7595 AddBuilder = Add.Define (Parent);
7596 if (AddBuilder == null)
7597 return false;
7599 RemoveBuilder = Remove.Define (Parent);
7600 if (RemoveBuilder == null)
7601 return false;
7603 EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, EventAttributes.None, MemberType);
7604 EventBuilder.SetAddOnMethod (AddBuilder);
7605 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
7606 return true;
7609 public override void Emit ()
7611 if (OptAttributes != null) {
7612 OptAttributes.Emit ();
7615 Add.Emit (Parent);
7616 Remove.Emit (Parent);
7618 base.Emit ();
7621 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
7623 MethodInfo mi = (MethodInfo) Parent.PartialContainer.BaseCache.FindBaseEvent (
7624 Parent.TypeBuilder, Name);
7626 if (mi == null)
7627 return null;
7629 ParameterData pd = TypeManager.GetParameterData (mi);
7630 base_ret_type = pd.ParameterType (0);
7631 return mi;
7635 // Represents header string for documentation comment.
7637 public override string DocCommentHeader {
7638 get { return "E:"; }
7643 public class Indexer : PropertyBase {
7645 class GetIndexerMethod : GetMethod
7647 public GetIndexerMethod (PropertyBase method):
7648 base (method)
7652 public GetIndexerMethod (PropertyBase method, Accessor accessor):
7653 base (method, accessor)
7657 public override Parameters ParameterInfo {
7658 get {
7659 return ((Indexer)method).parameters;
7664 class SetIndexerMethod: SetMethod
7666 public SetIndexerMethod (PropertyBase method):
7667 base (method)
7671 public SetIndexerMethod (PropertyBase method, Accessor accessor):
7672 base (method, accessor)
7676 protected override void DefineParameters ()
7678 parameters = Parameters.MergeGenerated (((Indexer)method).parameters,
7679 new Parameter (method.MemberType, "value", Parameter.Modifier.NONE, null, method.Location));
7683 const int AllowedModifiers =
7684 Modifiers.NEW |
7685 Modifiers.PUBLIC |
7686 Modifiers.PROTECTED |
7687 Modifiers.INTERNAL |
7688 Modifiers.PRIVATE |
7689 Modifiers.VIRTUAL |
7690 Modifiers.SEALED |
7691 Modifiers.OVERRIDE |
7692 Modifiers.UNSAFE |
7693 Modifiers.EXTERN |
7694 Modifiers.ABSTRACT;
7696 const int AllowedInterfaceModifiers =
7697 Modifiers.NEW;
7699 public readonly Parameters parameters;
7701 public Indexer (DeclSpace parent, Expression type, MemberName name, int mod,
7702 bool is_iface, Parameters parameters, Attributes attrs,
7703 Accessor get_block, Accessor set_block, bool define_set_first)
7704 : base (parent, type, mod,
7705 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
7706 is_iface, name, attrs, define_set_first)
7708 this.parameters = parameters;
7710 if (get_block == null)
7711 Get = new GetIndexerMethod (this);
7712 else
7713 Get = new GetIndexerMethod (this, get_block);
7715 if (set_block == null)
7716 Set = new SetIndexerMethod (this);
7717 else
7718 Set = new SetIndexerMethod (this, set_block);
7721 protected override bool CheckForDuplications ()
7723 ArrayList ar = Parent.PartialContainer.Indexers;
7724 if (ar != null) {
7725 int arLen = ar.Count;
7727 for (int i = 0; i < arLen; i++) {
7728 Indexer m = (Indexer) ar [i];
7729 if (IsDuplicateImplementation (m))
7730 return false;
7734 return true;
7737 bool IsDuplicateImplementation (Indexer indexer)
7739 if (this == indexer)
7740 return false;
7742 if (!MemberName.Equals (indexer.MemberName))
7743 return false;
7745 Type[] param_types = indexer.parameters.Types;
7747 // When it is not yet defined
7748 if (param_types == null)
7749 return false;
7751 if (param_types.Length != parameters.Count)
7752 return false;
7754 for (int i = 0; i < param_types.Length; i++)
7755 if (param_types [i] != parameters.Types [i])
7756 return false;
7758 Report.SymbolRelatedToPreviousError (indexer);
7759 Report.Error (111, Location, TypeContainer.Error111, indexer.GetSignatureForError ());
7760 return true;
7764 public override bool Define ()
7766 if (!DoDefineBase ())
7767 return false;
7769 if (!base.Define ())
7770 return false;
7772 if (!DefineParameters (parameters))
7773 return false;
7775 if (MemberType == TypeManager.void_type) {
7776 Report.Error (620, Location, "Indexers cannot have void type");
7777 return false;
7780 if (OptAttributes != null) {
7781 Attribute indexer_attr = OptAttributes.Search (TypeManager.indexer_name_type);
7782 if (indexer_attr != null) {
7783 // Remove the attribute from the list because it is not emitted
7784 OptAttributes.Attrs.Remove (indexer_attr);
7786 string name = indexer_attr.GetIndexerAttributeValue ();
7787 if (name == null)
7788 return false;
7790 ShortName = name;
7792 if (IsExplicitImpl) {
7793 Report.Error (415, indexer_attr.Location,
7794 "The `IndexerName' attribute is valid only on an " +
7795 "indexer that is not an explicit interface member declaration");
7796 return false;
7799 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
7800 Report.Error (609, indexer_attr.Location,
7801 "Cannot set the `IndexerName' attribute on an indexer marked override");
7802 return false;
7807 if (InterfaceType != null) {
7808 string base_IndexerName = TypeManager.IndexerPropertyName (InterfaceType);
7809 if (base_IndexerName != Name)
7810 ShortName = base_IndexerName;
7813 if (!Parent.PartialContainer.AddMember (this) ||
7814 !Parent.PartialContainer.AddMember (Get) || !Parent.PartialContainer.AddMember (Set))
7815 return false;
7817 if (!CheckBase ())
7818 return false;
7820 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
7822 if (!DefineAccessors ())
7823 return false;
7825 if (!Get.IsDummy) {
7826 // Setup iterator if we are one
7827 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
7828 Iterator iterator = Iterator.CreateIterator (Get, Parent, null, ModFlags);
7829 if (iterator == null)
7830 return false;
7835 // Now name the parameters
7837 Parameter [] p = parameters.FixedParameters;
7838 if (p != null) {
7839 // TODO: should be done in parser and it needs to do cycle
7840 if ((p [0].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
7841 CSharpParser.Error_ParameterModifierNotValid (Location);
7842 return false;
7846 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
7847 Name, PropertyAttributes.None, MemberType, parameters.Types);
7849 if (!Get.IsDummy)
7850 PropertyBuilder.SetGetMethod (GetBuilder);
7852 if (!Set.IsDummy)
7853 PropertyBuilder.SetSetMethod (SetBuilder);
7855 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder, parameters.Types);
7857 return true;
7860 public override string GetDocCommentName (DeclSpace ds)
7862 return DocUtil.GetMethodDocCommentName (this, parameters, ds);
7865 public override string GetSignatureForError ()
7867 StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
7868 if (MemberName.Left != null) {
7869 sb.Append ('.');
7870 sb.Append (MemberName.Left);
7873 sb.Append (".this");
7874 sb.Append (parameters.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
7875 return sb.ToString ();
7878 public override bool MarkForDuplicationCheck ()
7880 caching_flags |= Flags.TestMethodDuplication;
7881 return true;
7884 protected override PropertyInfo ResolveBaseProperty ()
7886 return Parent.PartialContainer.BaseCache.FindMemberToOverride (
7887 Parent.TypeBuilder, Name, parameters.Types, null, true) as PropertyInfo;
7890 protected override bool VerifyClsCompliance ()
7892 if (!base.VerifyClsCompliance ())
7893 return false;
7895 parameters.VerifyClsCompliance ();
7896 return true;
7900 public class Operator : MethodOrOperator, IAnonymousHost {
7902 const int AllowedModifiers =
7903 Modifiers.PUBLIC |
7904 Modifiers.UNSAFE |
7905 Modifiers.EXTERN |
7906 Modifiers.STATIC;
7908 public enum OpType : byte {
7910 // Unary operators
7911 LogicalNot,
7912 OnesComplement,
7913 Increment,
7914 Decrement,
7915 True,
7916 False,
7918 // Unary and Binary operators
7919 Addition,
7920 Subtraction,
7922 UnaryPlus,
7923 UnaryNegation,
7925 // Binary operators
7926 Multiply,
7927 Division,
7928 Modulus,
7929 BitwiseAnd,
7930 BitwiseOr,
7931 ExclusiveOr,
7932 LeftShift,
7933 RightShift,
7934 Equality,
7935 Inequality,
7936 GreaterThan,
7937 LessThan,
7938 GreaterThanOrEqual,
7939 LessThanOrEqual,
7941 // Implicit and Explicit
7942 Implicit,
7943 Explicit,
7945 // Just because of enum
7949 public readonly OpType OperatorType;
7951 public Operator (DeclSpace parent, OpType type, Expression ret_type,
7952 int mod_flags, Parameters parameters,
7953 ToplevelBlock block, Attributes attrs, Location loc)
7954 : base (parent, null, ret_type, mod_flags, AllowedModifiers, false,
7955 new MemberName ("op_" + type.ToString(), loc), attrs, parameters)
7957 OperatorType = type;
7958 Block = block;
7961 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7963 if (a.Type == TypeManager.conditional_attribute_type) {
7964 Error_ConditionalAttributeIsNotValid ();
7965 return;
7968 base.ApplyAttributeBuilder (a, cb);
7971 protected override bool CheckForDuplications ()
7973 ArrayList ar = Parent.PartialContainer.Operators;
7974 if (ar != null) {
7975 int arLen = ar.Count;
7977 for (int i = 0; i < arLen; i++) {
7978 Operator o = (Operator) ar [i];
7979 if (IsDuplicateImplementation (o))
7980 return false;
7984 ar = Parent.PartialContainer.Methods;
7985 if (ar != null) {
7986 int arLen = ar.Count;
7988 for (int i = 0; i < arLen; i++) {
7989 Method m = (Method) ar [i];
7990 if (IsDuplicateImplementation (m))
7991 return false;
7995 return true;
7998 public override bool Define ()
8000 const int RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
8001 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
8002 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
8003 return false;
8006 // imlicit and explicit operator of same types are not allowed
8007 if (OperatorType == OpType.Explicit || OperatorType == OpType.Implicit)
8008 MarkForDuplicationCheck ();
8010 if (!base.Define ())
8011 return false;
8013 if (MemberType == TypeManager.void_type) {
8014 Report.Error (590, Location, "User-defined operators cannot return void");
8015 return false;
8018 Type declaring_type = MethodData.DeclaringType;
8019 Type return_type = MemberType;
8020 Type first_arg_type = ParameterTypes [0];
8022 // Rules for conversion operators
8024 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
8025 if (first_arg_type == return_type && first_arg_type == declaring_type){
8026 Report.Error (555, Location,
8027 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
8028 return false;
8031 if ((first_arg_type != declaring_type) && (return_type != declaring_type) &&
8032 !TypeManager.IsNullableTypeOf (first_arg_type, declaring_type) &&
8033 !TypeManager.IsNullableTypeOf (return_type, declaring_type)) {
8034 Report.Error (
8035 556, Location,
8036 "User-defined conversion must convert to or from the " +
8037 "enclosing type");
8038 return false;
8041 if (first_arg_type.IsInterface || return_type.IsInterface){
8042 Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
8043 GetSignatureForError ());
8044 return false;
8047 if (first_arg_type.IsSubclassOf (return_type) || return_type.IsSubclassOf (first_arg_type)) {
8048 if (declaring_type.IsSubclassOf (return_type) || declaring_type.IsSubclassOf (first_arg_type)) {
8049 Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from base class",
8050 GetSignatureForError ());
8051 return false;
8053 Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from derived class",
8054 GetSignatureForError ());
8055 return false;
8057 } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
8058 if (first_arg_type != declaring_type || ParameterTypes [1] != TypeManager.int32_type) {
8059 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");
8060 return false;
8062 } else if (Parameters.Count == 1) {
8063 // Checks for Unary operators
8065 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
8066 if (return_type != declaring_type && !TypeManager.IsSubclassOf (return_type, declaring_type)) {
8067 Report.Error (448, Location,
8068 "The return type for ++ or -- operator must be the containing type or derived from the containing type");
8069 return false;
8071 if (first_arg_type != declaring_type) {
8072 Report.Error (
8073 559, Location, "The parameter type for ++ or -- operator must be the containing type");
8074 return false;
8078 if (first_arg_type != declaring_type){
8079 Report.Error (
8080 562, Location,
8081 "The parameter of a unary operator must be the " +
8082 "containing type");
8083 return false;
8086 if (OperatorType == OpType.True || OperatorType == OpType.False) {
8087 if (return_type != TypeManager.bool_type){
8088 Report.Error (
8089 215, Location,
8090 "The return type of operator True or False " +
8091 "must be bool");
8092 return false;
8096 } else {
8097 // Checks for Binary operators
8099 if (first_arg_type != declaring_type &&
8100 ParameterTypes [1] != declaring_type){
8101 Report.Error (
8102 563, Location,
8103 "One of the parameters of a binary operator must " +
8104 "be the containing type");
8105 return false;
8109 return true;
8112 protected override bool DoDefine ()
8114 if (!base.DoDefine ())
8115 return false;
8117 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
8118 return true;
8121 public override void Emit ()
8123 base.Emit ();
8125 Parameters.ApplyAttributes (MethodBuilder);
8128 // abstract or extern methods have no bodies
8130 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
8131 return;
8133 EmitContext ec;
8134 if ((flags & MethodAttributes.PinvokeImpl) == 0)
8135 ec = CreateEmitContext (Parent, MethodBuilder.GetILGenerator ());
8136 else
8137 ec = CreateEmitContext (Parent, null);
8139 SourceMethod source = SourceMethod.Create (Parent, MethodBuilder, Block);
8140 ec.EmitTopBlock (this, Block);
8142 if (source != null)
8143 source.CloseMethod ();
8145 Block = null;
8148 // Operator cannot be override
8149 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
8151 return null;
8154 public static string GetName (OpType ot)
8156 switch (ot){
8157 case OpType.LogicalNot:
8158 return "!";
8159 case OpType.OnesComplement:
8160 return "~";
8161 case OpType.Increment:
8162 return "++";
8163 case OpType.Decrement:
8164 return "--";
8165 case OpType.True:
8166 return "true";
8167 case OpType.False:
8168 return "false";
8169 case OpType.Addition:
8170 return "+";
8171 case OpType.Subtraction:
8172 return "-";
8173 case OpType.UnaryPlus:
8174 return "+";
8175 case OpType.UnaryNegation:
8176 return "-";
8177 case OpType.Multiply:
8178 return "*";
8179 case OpType.Division:
8180 return "/";
8181 case OpType.Modulus:
8182 return "%";
8183 case OpType.BitwiseAnd:
8184 return "&";
8185 case OpType.BitwiseOr:
8186 return "|";
8187 case OpType.ExclusiveOr:
8188 return "^";
8189 case OpType.LeftShift:
8190 return "<<";
8191 case OpType.RightShift:
8192 return ">>";
8193 case OpType.Equality:
8194 return "==";
8195 case OpType.Inequality:
8196 return "!=";
8197 case OpType.GreaterThan:
8198 return ">";
8199 case OpType.LessThan:
8200 return "<";
8201 case OpType.GreaterThanOrEqual:
8202 return ">=";
8203 case OpType.LessThanOrEqual:
8204 return "<=";
8205 case OpType.Implicit:
8206 return "implicit";
8207 case OpType.Explicit:
8208 return "explicit";
8209 default: return "";
8213 public static OpType GetOperatorType (string name)
8215 if (name.StartsWith ("op_")){
8216 for (int i = 0; i < Unary.oper_names.Length; ++i) {
8217 if (Unary.oper_names [i] == name)
8218 return (OpType)i;
8221 for (int i = 0; i < Binary.oper_names.Length; ++i) {
8222 if (Binary.oper_names [i] == name)
8223 return (OpType)i;
8226 return OpType.TOP;
8229 public override string GetSignatureForError ()
8231 StringBuilder sb = new StringBuilder ();
8232 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
8233 sb.AppendFormat ("{0}.{1} operator {2}", Parent.GetSignatureForError (), GetName (OperatorType), Type.Type == null ? Type.ToString () : TypeManager.CSharpName (Type.Type));
8235 else {
8236 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
8239 sb.Append (Parameters.GetSignatureForError ());
8240 return sb.ToString ();
8245 // This is used to compare method signatures
8247 struct MethodSignature {
8248 public string Name;
8249 public Type RetType;
8250 public Type [] Parameters;
8252 /// <summary>
8253 /// This delegate is used to extract methods which have the
8254 /// same signature as the argument
8255 /// </summary>
8256 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
8258 public MethodSignature (string name, Type ret_type, Type [] parameters)
8260 Name = name;
8261 RetType = ret_type;
8263 if (parameters == null)
8264 Parameters = Type.EmptyTypes;
8265 else
8266 Parameters = parameters;
8269 public override string ToString ()
8271 string pars = "";
8272 if (Parameters.Length != 0){
8273 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
8274 for (int i = 0; i < Parameters.Length; i++){
8275 sb.Append (Parameters [i]);
8276 if (i+1 < Parameters.Length)
8277 sb.Append (", ");
8279 pars = sb.ToString ();
8282 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
8285 public override int GetHashCode ()
8287 return Name.GetHashCode ();
8290 public override bool Equals (Object o)
8292 MethodSignature other = (MethodSignature) o;
8294 if (other.Name != Name)
8295 return false;
8297 if (other.RetType != RetType)
8298 return false;
8300 if (Parameters == null){
8301 if (other.Parameters == null)
8302 return true;
8303 return false;
8306 if (other.Parameters == null)
8307 return false;
8309 int c = Parameters.Length;
8310 if (other.Parameters.Length != c)
8311 return false;
8313 for (int i = 0; i < c; i++)
8314 if (other.Parameters [i] != Parameters [i])
8315 return false;
8317 return true;
8320 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
8322 MethodSignature sig = (MethodSignature) filter_criteria;
8324 if (m.Name != sig.Name)
8325 return false;
8327 Type ReturnType;
8328 MethodInfo mi = m as MethodInfo;
8329 PropertyInfo pi = m as PropertyInfo;
8331 if (mi != null)
8332 ReturnType = mi.ReturnType;
8333 else if (pi != null)
8334 ReturnType = pi.PropertyType;
8335 else
8336 return false;
8339 // we use sig.RetType == null to mean `do not check the
8340 // method return value.
8342 if (sig.RetType != null)
8343 if (ReturnType != sig.RetType)
8344 return false;
8346 Type [] args;
8347 if (mi != null)
8348 args = TypeManager.GetParameterData (mi).Types;
8349 else
8350 args = TypeManager.GetArgumentTypes (pi);
8351 Type [] sigp = sig.Parameters;
8353 if (args.Length != sigp.Length)
8354 return false;
8356 for (int i = args.Length; i > 0; ){
8357 i--;
8358 if (args [i] != sigp [i])
8359 return false;
8361 return true;