2 // class.cs: Class and Struct handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@gnome.org)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
12 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
14 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
15 // have fixed a remaining problem: not every AddXXXX was adding a
16 // fully qualified name.
18 // Now everyone registers a fully qualified name in the DeclSpace as
19 // being defined instead of the partial name.
21 // Downsides: we are slower than we need to be due to the excess
22 // copies and the names being registered this way.
24 // The reason for this is that we currently depend (on the corlib
25 // bootstrap for instance) that types are fully qualified, because
26 // we dump all the types in the namespace, and we should really have
27 // types inserted into the proper namespace, so we can only store the
28 // basenames in the defined_names array.
33 using System.Collections;
34 using System.Reflection;
35 using System.Reflection.Emit;
36 using System.Runtime.CompilerServices;
37 using System.Runtime.InteropServices;
39 namespace Mono.CSharp {
42 /// This is the base class for structs and classes.
44 public class TypeContainer : DeclSpace, IMemberContainer {
45 // Holds a list of classes and structures
48 // Holds the list of properties
51 // Holds the list of enumerations
54 // Holds the list of delegates
57 // Holds the list of constructors
58 ArrayList instance_constructors;
60 // Holds the list of fields
63 // Holds a list of fields that have initializers
64 ArrayList initialized_fields;
66 // Holds a list of static fields that have initializers
67 ArrayList initialized_static_fields;
69 // Holds the list of constants
75 // Holds order in which interfaces must be closed
76 ArrayList interface_order;
87 // Holds the operators
90 // The emit context for toplevel objects.
94 // Pointers to the default constructor and the default static constructor
96 Constructor default_constructor;
97 Constructor default_static_constructor;
100 // Whether we have seen a static constructor for this class or not
102 public bool UserDefinedStaticConstructor = false;
105 // Whether we have at least one non-static field
107 bool have_nonstatic_fields = false;
110 // This one is computed after we can distinguish interfaces
111 // from classes from the arraylist `type_bases'
113 string base_class_name;
115 ArrayList type_bases;
117 bool members_defined;
118 bool members_defined_ok;
120 // The interfaces we implement.
122 Type[] base_inteface_types;
124 // The parent member container and our member cache
125 IMemberContainer parent_container;
126 MemberCache member_cache;
129 // The indexer name for this class
131 public string IndexerName;
133 public TypeContainer ():
134 this (null, null, "", null, new Location (-1)) {
137 public TypeContainer (NamespaceEntry ns, TypeContainer parent, string name, Attributes attrs, Location l)
138 : base (ns, parent, name, attrs, l)
140 types = new ArrayList ();
142 base_class_name = null;
145 public AdditionResult AddConstant (Const constant)
148 string basename = constant.Name;
149 string fullname = Name + "." + basename;
151 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
154 if (constants == null)
155 constants = new ArrayList ();
157 constants.Add (constant);
158 DefineName (fullname, constant);
160 return AdditionResult.Success;
163 public AdditionResult AddEnum (Mono.CSharp.Enum e)
167 if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
171 enums = new ArrayList ();
174 DefineName (e.Name, e);
176 return AdditionResult.Success;
179 public AdditionResult AddClass (Class c)
182 string name = c.Basename;
184 if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
187 DefineName (c.Name, c);
190 return AdditionResult.Success;
193 public AdditionResult AddStruct (Struct s)
196 string name = s.Basename;
198 if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
201 DefineName (s.Name, s);
204 return AdditionResult.Success;
207 public AdditionResult AddDelegate (Delegate d)
210 string name = d.Basename;
212 if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
215 if (delegates == null)
216 delegates = new ArrayList ();
218 DefineName (d.Name, d);
221 return AdditionResult.Success;
224 public AdditionResult AddMethod (Method method)
226 string basename = method.Name;
227 string fullname = Name + "." + basename;
229 Object value = defined_names [fullname];
231 if (value != null && (!(value is Method)))
232 return AdditionResult.NameExists;
234 if (basename == Basename)
235 return AdditionResult.EnclosingClash;
238 methods = new ArrayList ();
240 if (method.Name.IndexOf ('.') != -1)
241 methods.Insert (0, method);
243 methods.Add (method);
246 DefineName (fullname, method);
248 return AdditionResult.Success;
251 public AdditionResult AddConstructor (Constructor c)
253 if (c.Name != Basename)
254 return AdditionResult.NotAConstructor;
256 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
259 UserDefinedStaticConstructor = true;
260 if (default_static_constructor != null)
261 return AdditionResult.MethodExists;
263 default_static_constructor = c;
266 if (default_constructor != null)
267 return AdditionResult.MethodExists;
268 default_constructor = c;
271 if (instance_constructors == null)
272 instance_constructors = new ArrayList ();
274 instance_constructors.Add (c);
277 return AdditionResult.Success;
280 public AdditionResult AddInterface (Interface iface)
283 string name = iface.Basename;
285 if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
288 if (interfaces == null)
289 interfaces = new ArrayList ();
290 interfaces.Add (iface);
291 DefineName (iface.Name, iface);
293 return AdditionResult.Success;
296 public AdditionResult AddField (Field field)
299 string basename = field.Name;
300 string fullname = Name + "." + basename;
302 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
306 fields = new ArrayList ();
310 if (field.HasInitializer){
311 if ((field.ModFlags & Modifiers.STATIC) != 0){
312 if (initialized_static_fields == null)
313 initialized_static_fields = new ArrayList ();
315 initialized_static_fields.Add (field);
318 if (initialized_fields == null)
319 initialized_fields = new ArrayList ();
321 initialized_fields.Add (field);
325 if ((field.ModFlags & Modifiers.STATIC) == 0)
326 have_nonstatic_fields = true;
328 DefineName (fullname, field);
329 return AdditionResult.Success;
332 public AdditionResult AddProperty (Property prop)
336 if ((res = AddProperty (prop, prop.Name)) != AdditionResult.Success)
339 if (prop.Get != null) {
340 if ((res = AddProperty (prop, "get_" + prop.Name)) != AdditionResult.Success)
344 if (prop.Set != null) {
345 if ((res = AddProperty (prop, "set_" + prop.Name)) != AdditionResult.Success)
349 if (properties == null)
350 properties = new ArrayList ();
352 if (prop.Name.IndexOf ('.') != -1)
353 properties.Insert (0, prop);
355 properties.Add (prop);
357 return AdditionResult.Success;
360 AdditionResult AddProperty (Property prop, string basename)
363 string fullname = Name + "." + basename;
365 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
368 DefineName (fullname, prop);
370 return AdditionResult.Success;
373 public AdditionResult AddEvent (Event e)
376 string basename = e.Name;
377 string fullname = Name + "." + basename;
379 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
383 events = new ArrayList ();
386 DefineName (fullname, e);
388 return AdditionResult.Success;
391 public void AddIndexer (Indexer i)
393 if (indexers == null)
394 indexers = new ArrayList ();
396 if (i.ExplicitInterfaceName != null)
397 indexers.Insert (0, i);
402 public AdditionResult AddOperator (Operator op)
404 if (operators == null)
405 operators = new ArrayList ();
409 string basename = op.Name;
410 string fullname = Name + "." + basename;
411 if (!defined_names.Contains (fullname))
413 DefineName (fullname, op);
415 return AdditionResult.Success;
418 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
420 if (a.Type == TypeManager.default_member_type) {
421 if (Indexers != null) {
422 Report.Error (646, a.Location,
423 "Cannot specify the DefaultMember attribute on" +
424 " a type containing an indexer");
429 base.ApplyAttributeBuilder (a, cb);
432 public override AttributeTargets AttributeTargets {
434 throw new NotSupportedException ();
438 public void RegisterOrder (Interface iface)
440 if (interface_order == null)
441 interface_order = new ArrayList ();
443 interface_order.Add (iface);
446 public ArrayList Types {
452 public ArrayList Methods {
458 public ArrayList Constants {
464 public ArrayList Interfaces {
472 return base_class_name;
476 public ArrayList Bases {
486 public ArrayList Fields {
496 public ArrayList InstanceConstructors {
498 return instance_constructors;
502 public ArrayList Properties {
508 public ArrayList Events {
514 public ArrayList Enums {
520 public ArrayList Indexers {
526 public ArrayList Operators {
532 public ArrayList Delegates {
538 public virtual TypeAttributes TypeAttr {
540 return Modifiers.TypeAttr (ModFlags, this);
545 // Emits the instance field initializers
547 public bool EmitFieldInitializers (EmitContext ec)
550 Expression instance_expr;
553 fields = initialized_static_fields;
554 instance_expr = null;
556 fields = initialized_fields;
557 instance_expr = new This (Location.Null).Resolve (ec);
563 foreach (Field f in fields){
564 Expression e = f.GetInitializerExpression (ec);
568 Location l = f.Location;
569 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
570 fe.InstanceExpression = instance_expr;
571 ExpressionStatement a = new Assign (fe, e, l);
573 a = a.ResolveStatement (ec);
577 a.EmitStatement (ec);
584 // Defines the default constructors
586 void DefineDefaultConstructor (bool is_static)
590 // The default constructor is public
591 // If the class is abstract, the default constructor is protected
592 // The default static constructor is private
594 int mods = Modifiers.PUBLIC;
596 mods = Modifiers.STATIC | Modifiers.PRIVATE;
597 else if ((ModFlags & Modifiers.ABSTRACT) != 0)
598 mods = Modifiers.PROTECTED;
600 c = new Constructor (this, Basename, mods, Parameters.EmptyReadOnlyParameters,
601 new ConstructorBaseInitializer (
602 null, Parameters.EmptyReadOnlyParameters,
608 c.Block = new ToplevelBlock (null, Location);
612 public void ReportStructInitializedInstanceError ()
614 string n = TypeBuilder.FullName;
616 foreach (Field f in initialized_fields){
619 "`" + n + "." + f.Name + "': can not have " +
620 "instance field initializers in structs");
625 /// The pending methods that need to be implemented (interfaces or abstract methods)
627 public PendingImplementation Pending;
630 /// This function computes the Base class and also the
631 /// list of interfaces that the class or struct @c implements.
633 /// The return value is an array (might be null) of
634 /// interfaces implemented (as Types).
636 /// The @parent argument is set to the parent object or null
637 /// if this is `System.Object'.
639 TypeExpr [] GetClassBases (bool is_class, bool is_iface,
640 out TypeExpr parent, out bool error)
642 ArrayList bases = Bases;
648 if (is_class || is_iface)
651 parent = TypeManager.system_valuetype_expr;
655 if (RootContext.StdLib)
656 parent = TypeManager.system_object_expr;
657 else if (Name != "System.Object")
658 parent = TypeManager.system_object_expr;
661 // If we are compiling our runtime,
662 // and we are defining ValueType, then our
663 // parent is `System.Object'.
665 if (!RootContext.StdLib && Name == "System.ValueType")
666 parent = TypeManager.system_object_expr;
673 // Bases should be null if there are no bases at all
678 TypeExpr name = ResolveTypeExpr ((Expression) bases [0], false, Location);
689 parent = TypeManager.system_object_expr;
695 if (name.IsValueType)
696 detail = " (a class can not inherit from a struct/enum)";
698 Report.Error (509, "class `"+ Name +
699 "': Cannot inherit from sealed class `"+
700 name.Name + "'" + detail);
705 if (!parent.CanInheritFrom ()){
706 Report.Error (644, Location,
707 "`{0}' cannot inherit from special class `{1}'",
713 if (!parent.AsAccessible (this, ModFlags))
714 Report.Error (60, Location,
715 "Inconsistent accessibility: base class `" +
716 name.Name + "' is less accessible than class `" +
724 base_class_name = parent.Name;
726 TypeExpr [] ifaces = new TypeExpr [count-start];
728 for (i = start, j = 0; i < count; i++, j++){
729 Expression name = (Expression) bases [i];
730 TypeExpr resolved = ResolveTypeExpr (name, false, Location);
731 if (resolved == null)
734 bases [i] = resolved;
736 if (is_class == false && !resolved.IsInterface){
737 Report.Error (527, "In Struct `" + Name + "', type `"+
738 name +"' is not an interface");
743 if (resolved.IsClass) {
745 Report.Error (527, "In Class `" + Name + "', type `"+
746 name+"' is not an interface");
752 for (int x = 0; x < j; x++) {
753 if (resolved.Equals (ifaces [x])) {
754 Report.Error (528, "`" + name + "' is already listed in interface list");
761 !resolved.AsAccessible (Parent, ModFlags))
762 Report.Error (61, Location,
763 "Inconsistent accessibility: base interface `" +
764 name + "' is less accessible than interface `" +
767 ifaces [j] = resolved;
770 return TypeManager.ExpandInterfaces (ifaces);
776 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
778 public override TypeBuilder DefineType ()
781 bool is_class, is_iface;
783 if (TypeBuilder != null)
790 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
797 if (this is Interface) {
808 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
810 ifaces = GetClassBases (is_class, is_iface, out parent, out error);
815 if (!is_class && TypeManager.value_type == null)
816 throw new Exception ();
818 TypeAttributes type_attributes = TypeAttr;
822 ptype = parent.ResolveType (ec);
827 if (TypeManager.NamespaceClash (Name, Location)) {
832 ModuleBuilder builder = CodeGen.Module.Builder;
833 TypeBuilder = builder.DefineType (
834 Name, type_attributes, ptype, null);
836 TypeBuilder builder = Parent.DefineType ();
840 TypeBuilder = builder.DefineNestedType (
841 Basename, type_attributes, ptype, null);
845 // Structs with no fields need to have at least one byte.
846 // The right thing would be to set the PackingSize in a DefineType
847 // but there are no functions that allow interfaces *and* the size to
851 if (!is_class && !is_iface && !have_nonstatic_fields){
852 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
853 FieldAttributes.Private);
856 // add interfaces that were not added at type creation
857 if (ifaces != null) {
858 base_inteface_types = new Type[ifaces.Length];
859 for (int i = 0; i < ifaces.Length; ++i) {
860 Type itype = ifaces [i].ResolveType (ec);
861 TypeBuilder.AddInterfaceImplementation (itype);
862 base_inteface_types [i] = itype;
867 // Finish the setup for the EmitContext
869 ec.ContainerType = TypeBuilder;
871 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
873 if ((parent != null) && parent.IsAttribute) {
874 RootContext.RegisterAttribute (this);
876 RootContext.RegisterOrder (this);
878 if (Interfaces != null) {
879 foreach (Interface iface in Interfaces)
880 if (iface.DefineType () == null) {
887 foreach (TypeContainer tc in Types)
888 if (tc.DefineType () == null) {
894 if (Delegates != null) {
895 foreach (Delegate d in Delegates)
896 if (d.DefineType () == null) {
903 foreach (Enum en in Enums)
904 if (en.DefineType () == null) {
916 /// Defines the MemberCore objects that are in the `list' Arraylist
918 /// The `defined_names' array contains a list of members defined in
921 static ArrayList remove_list = new ArrayList ();
922 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
926 remove_list.Clear ();
928 foreach (MemberCore mc in list){
930 if (defined_names != null)
931 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
936 if (RootContext.WarningLevel >= 4){
937 if ((mc.ModFlags & Modifiers.NEW) != 0)
938 Warning_KeywordNewNotRequired (mc.Location, mc);
940 } else if (mc is MethodCore)
941 ((MethodCore) mc).OverridesSomething = true;
943 if (!mc.Define (this)){
944 remove_list.Add (mc);
951 MemberInfo match = defined_names [idx];
953 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
957 // If we are both methods, let the method resolution emit warnings
959 if (match is MethodBase && mc is MethodCore)
962 if ((mc.ModFlags & Modifiers.NEW) == 0) {
964 if (!(match is EventInfo)) {
965 Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
969 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
973 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
977 foreach (object o in remove_list)
980 remove_list.Clear ();
984 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
985 // class is consistent. Either it is `Item' or it is the name defined by all the
986 // indexers with the `IndexerName' attribute.
988 // Turns out that the IndexerNameAttribute is applied to each indexer,
989 // but it is never emitted, instead a DefaultMember attribute is attached
992 void DefineIndexers ()
994 string class_indexer_name = null;
997 // If there's both an explicit and an implicit interface implementation, the
998 // explicit one actually implements the interface while the other one is just
999 // a normal indexer. See bug #37714.
1002 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
1003 bool seen_normal_indexers = false;
1005 foreach (Indexer i in Indexers) {
1010 name = i.IndexerName;
1012 if (i.InterfaceType != null) {
1013 if (seen_normal_indexers)
1014 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
1018 seen_normal_indexers = true;
1020 if (class_indexer_name == null)
1021 class_indexer_name = name;
1022 else if (name != class_indexer_name)
1023 Report.Error (668, "Two indexers have different names, " +
1024 " you should use the same name for all your indexers");
1027 if (seen_normal_indexers && class_indexer_name == null)
1028 class_indexer_name = "Item";
1029 IndexerName = class_indexer_name;
1032 static void Error_KeywordNotAllowed (Location loc)
1034 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1038 /// Populates our TypeBuilder with fields and methods
1040 public override bool DefineMembers (TypeContainer container)
1042 if (members_defined)
1043 return members_defined_ok;
1045 members_defined_ok = DoDefineMembers ();
1046 members_defined = true;
1048 return members_defined_ok;
1051 bool DoDefineMembers ()
1053 MemberInfo [] defined_names = null;
1056 // We need to be able to use the member cache while we are checking/defining
1059 if (TypeBuilder.BaseType != null)
1060 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1063 if (interface_order != null){
1064 foreach (Interface iface in interface_order)
1065 if ((iface.ModFlags & Modifiers.NEW) == 0)
1066 iface.DefineMembers (this);
1068 Error_KeywordNotAllowed (iface.Location);
1071 if (RootContext.WarningLevel > 1){
1075 // This code throws an exception in the comparer
1076 // I guess the string is not an object?
1078 ptype = TypeBuilder.BaseType;
1080 defined_names = (MemberInfo []) FindMembers (
1081 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1082 BindingFlags.Public | BindingFlags.Instance |
1083 BindingFlags.Static, null, null);
1085 Array.Sort (defined_names, mif_compare);
1089 Class pclass = Parent as Class;
1090 if (pclass != null) {
1091 string pname = null;
1093 Type t = pclass.TypeBuilder.BaseType;
1094 while ((t != null) && (ptype == null)) {
1095 pname = t.FullName + "." + Basename;
1096 ptype = RootContext.LookupType (this, pname, true, Location.Null);
1100 if ((ModFlags & Modifiers.NEW) != 0) {
1102 Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
1103 "inherited member. The keyword new is not required.");
1104 } else if (ptype != null) {
1105 Report.Warning (108, Location, "The keyword new is required on `" +
1106 Name + "' because it hides inherited member '" +
1109 } else if ((ModFlags & Modifiers.NEW) != 0)
1110 Error_KeywordNotAllowed (Location);
1112 if (constants != null)
1113 DefineMembers (constants, defined_names);
1116 DefineMembers (fields, defined_names);
1119 if (instance_constructors == null){
1120 if (default_constructor == null)
1121 DefineDefaultConstructor (false);
1124 if (initialized_static_fields != null &&
1125 default_static_constructor == null)
1126 DefineDefaultConstructor (true);
1129 if (this is Struct){
1131 // Structs can not have initialized instance
1134 if (initialized_static_fields != null &&
1135 default_static_constructor == null)
1136 DefineDefaultConstructor (true);
1138 if (initialized_fields != null)
1139 ReportStructInitializedInstanceError ();
1142 if (!(this is Interface))
1143 Pending = PendingImplementation.GetPendingImplementations (this);
1146 // Constructors are not in the defined_names array
1148 if (instance_constructors != null)
1149 DefineMembers (instance_constructors, null);
1151 if (default_static_constructor != null)
1152 default_static_constructor.Define (this);
1154 if (methods != null)
1155 DefineMembers (methods, defined_names);
1157 if (properties != null)
1158 DefineMembers (properties, defined_names);
1161 DefineMembers (events, defined_names);
1163 if (indexers != null)
1166 if (operators != null){
1167 DefineMembers (operators, null);
1169 CheckPairedOperators ();
1173 DefineMembers (enums, defined_names);
1175 if (delegates != null)
1176 DefineMembers (delegates, defined_names);
1179 member_cache = new MemberCache (this);
1186 public override bool Define (TypeContainer container)
1188 if (interface_order != null){
1189 foreach (Interface iface in interface_order)
1190 if ((iface.ModFlags & Modifiers.NEW) == 0)
1191 iface.Define (this);
1198 /// This function is based by a delegate to the FindMembers routine
1200 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1206 /// This filter is used by FindMembers, and we just keep
1207 /// a global for the filter to `AlwaysAccept'
1209 static MemberFilter accepting_filter;
1213 /// A member comparission method based on name only
1215 static IComparer mif_compare;
1217 static TypeContainer ()
1219 accepting_filter = new MemberFilter (AlwaysAccept);
1220 mif_compare = new MemberInfoCompare ();
1223 public MethodInfo[] GetMethods ()
1225 ArrayList members = new ArrayList ();
1227 DefineMembers (null);
1229 if (methods != null) {
1230 int len = methods.Count;
1231 for (int i = 0; i < len; i++) {
1232 Method m = (Method) methods [i];
1234 members.Add (m.MethodBuilder);
1238 if (operators != null) {
1239 int len = operators.Count;
1240 for (int i = 0; i < len; i++) {
1241 Operator o = (Operator) operators [i];
1243 members.Add (o.OperatorMethodBuilder);
1247 if (properties != null) {
1248 int len = properties.Count;
1249 for (int i = 0; i < len; i++) {
1250 Property p = (Property) properties [i];
1252 if (p.GetBuilder != null)
1253 members.Add (p.GetBuilder);
1254 if (p.SetBuilder != null)
1255 members.Add (p.SetBuilder);
1259 if (indexers != null) {
1260 int len = indexers.Count;
1261 for (int i = 0; i < len; i++) {
1262 Indexer ix = (Indexer) indexers [i];
1264 if (ix.GetBuilder != null)
1265 members.Add (ix.GetBuilder);
1266 if (ix.SetBuilder != null)
1267 members.Add (ix.SetBuilder);
1271 if (events != null) {
1272 int len = events.Count;
1273 for (int i = 0; i < len; i++) {
1274 Event e = (Event) events [i];
1276 if (e.AddBuilder != null)
1277 members.Add (e.AddBuilder);
1278 if (e.RemoveBuilder != null)
1279 members.Add (e.RemoveBuilder);
1283 MethodInfo[] retMethods = new MethodInfo [members.Count];
1284 members.CopyTo (retMethods, 0);
1289 /// This method returns the members of this type just like Type.FindMembers would
1290 /// Only, we need to use this for types which are _being_ defined because MS'
1291 /// implementation can't take care of that.
1294 // FIXME: return an empty static array instead of null, that cleans up
1295 // some code and is consistent with some coding conventions I just found
1299 // Notice that in various cases we check if our field is non-null,
1300 // something that would normally mean that there was a bug elsewhere.
1302 // The problem happens while we are defining p-invoke methods, as those
1303 // will trigger a FindMembers, but this happens before things are defined
1305 // Since the whole process is a no-op, it is fine to check for null here.
1307 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1308 MemberFilter filter, object criteria)
1310 ArrayList members = null;
1313 if ((bf & BindingFlags.Public) != 0)
1314 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1316 if ((bf & BindingFlags.NonPublic) != 0)
1317 modflags |= Modifiers.PRIVATE;
1319 int static_mask = 0, static_flags = 0;
1320 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1321 case BindingFlags.Static:
1322 static_mask = static_flags = Modifiers.STATIC;
1325 case BindingFlags.Instance:
1326 static_mask = Modifiers.STATIC;
1331 static_mask = static_flags = 0;
1335 Timer.StartTimer (TimerType.TcFindMembers);
1338 filter = accepting_filter;
1340 if ((mt & MemberTypes.Field) != 0) {
1341 if (fields != null) {
1342 int len = fields.Count;
1343 for (int i = 0; i < len; i++) {
1344 Field f = (Field) fields [i];
1346 if ((f.ModFlags & modflags) == 0)
1348 if ((f.ModFlags & static_mask) != static_flags)
1351 FieldBuilder fb = f.FieldBuilder;
1352 if (fb != null && filter (fb, criteria) == true) {
1353 if (members == null)
1354 members = new ArrayList ();
1361 if (constants != null) {
1362 int len = constants.Count;
1363 for (int i = 0; i < len; i++) {
1364 Const con = (Const) constants [i];
1366 if ((con.ModFlags & modflags) == 0)
1368 if ((con.ModFlags & static_mask) != static_flags)
1371 FieldBuilder fb = con.FieldBuilder;
1372 if (fb != null && filter (fb, criteria) == true) {
1373 if (members == null)
1374 members = new ArrayList ();
1382 if ((mt & MemberTypes.Method) != 0) {
1383 if (methods != null) {
1384 int len = methods.Count;
1385 for (int i = 0; i < len; i++) {
1386 Method m = (Method) methods [i];
1388 if ((m.ModFlags & modflags) == 0)
1390 if ((m.ModFlags & static_mask) != static_flags)
1393 MethodBuilder mb = m.MethodBuilder;
1395 if (mb != null && filter (mb, criteria) == true) {
1396 if (members == null)
1397 members = new ArrayList ();
1404 if (operators != null) {
1405 int len = operators.Count;
1406 for (int i = 0; i < len; i++) {
1407 Operator o = (Operator) operators [i];
1409 if ((o.ModFlags & modflags) == 0)
1411 if ((o.ModFlags & static_mask) != static_flags)
1414 MethodBuilder ob = o.OperatorMethodBuilder;
1415 if (ob != null && filter (ob, criteria) == true) {
1416 if (members == null)
1417 members = new ArrayList ();
1424 if (properties != null) {
1425 int len = properties.Count;
1426 for (int i = 0; i < len; i++) {
1427 Property p = (Property) properties [i];
1429 if ((p.ModFlags & modflags) == 0)
1431 if ((p.ModFlags & static_mask) != static_flags)
1437 if (b != null && filter (b, criteria) == true) {
1438 if (members == null)
1439 members = new ArrayList ();
1445 if (b != null && filter (b, criteria) == true) {
1446 if (members == null)
1447 members = new ArrayList ();
1454 if (indexers != null) {
1455 int len = indexers.Count;
1456 for (int i = 0; i < len; i++) {
1457 Indexer ix = (Indexer) indexers [i];
1459 if ((ix.ModFlags & modflags) == 0)
1461 if ((ix.ModFlags & static_mask) != static_flags)
1467 if (b != null && filter (b, criteria) == true) {
1468 if (members == null)
1469 members = new ArrayList ();
1475 if (b != null && filter (b, criteria) == true) {
1476 if (members == null)
1477 members = new ArrayList ();
1485 if ((mt & MemberTypes.Event) != 0) {
1486 if (events != null) {
1487 int len = events.Count;
1488 for (int i = 0; i < len; i++) {
1489 Event e = (Event) events [i];
1491 if ((e.ModFlags & modflags) == 0)
1493 if ((e.ModFlags & static_mask) != static_flags)
1496 MemberInfo eb = e.EventBuilder;
1497 if (eb != null && filter (eb, criteria) == true) {
1498 if (members == null)
1499 members = new ArrayList ();
1501 members.Add (e.EventBuilder);
1507 if ((mt & MemberTypes.Property) != 0){
1508 if (properties != null) {
1509 int len = properties.Count;
1510 for (int i = 0; i < len; i++) {
1511 Property p = (Property) properties [i];
1513 if ((p.ModFlags & modflags) == 0)
1515 if ((p.ModFlags & static_mask) != static_flags)
1518 MemberInfo pb = p.PropertyBuilder;
1519 if (pb != null && filter (pb, criteria) == true) {
1520 if (members == null)
1521 members = new ArrayList ();
1523 members.Add (p.PropertyBuilder);
1528 if (indexers != null) {
1529 int len = indexers.Count;
1530 for (int i = 0; i < len; i++) {
1531 Indexer ix = (Indexer) indexers [i];
1533 if ((ix.ModFlags & modflags) == 0)
1535 if ((ix.ModFlags & static_mask) != static_flags)
1538 MemberInfo ib = ix.PropertyBuilder;
1539 if (ib != null && filter (ib, criteria) == true) {
1540 if (members == null)
1541 members = new ArrayList ();
1543 members.Add (ix.PropertyBuilder);
1549 if ((mt & MemberTypes.NestedType) != 0) {
1550 if (types != null) {
1551 int len = types.Count;
1552 for (int i = 0; i < len; i++) {
1553 TypeContainer t = (TypeContainer) types [i];
1555 if ((t.ModFlags & modflags) == 0)
1558 TypeBuilder tb = t.TypeBuilder;
1559 if (tb != null && (filter (tb, criteria) == true)) {
1560 if (members == null)
1561 members = new ArrayList ();
1568 if (enums != null) {
1569 int len = enums.Count;
1570 for (int i = 0; i < len; i++) {
1571 Enum en = (Enum) enums [i];
1573 if ((en.ModFlags & modflags) == 0)
1576 TypeBuilder tb = en.TypeBuilder;
1577 if (tb != null && (filter (tb, criteria) == true)) {
1578 if (members == null)
1579 members = new ArrayList ();
1586 if (delegates != null) {
1587 int len = delegates.Count;
1588 for (int i = 0; i < len; i++) {
1589 Delegate d = (Delegate) delegates [i];
1591 if ((d.ModFlags & modflags) == 0)
1594 TypeBuilder tb = d.TypeBuilder;
1595 if (tb != null && (filter (tb, criteria) == true)) {
1596 if (members == null)
1597 members = new ArrayList ();
1604 if (interfaces != null) {
1605 int len = interfaces.Count;
1606 for (int i = 0; i < len; i++) {
1607 Interface iface = (Interface) interfaces [i];
1609 if ((iface.ModFlags & modflags) == 0)
1612 TypeBuilder tb = iface.TypeBuilder;
1613 if (tb != null && (filter (tb, criteria) == true)) {
1614 if (members == null)
1615 members = new ArrayList ();
1623 if ((mt & MemberTypes.Constructor) != 0){
1624 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1625 int len = instance_constructors.Count;
1626 for (int i = 0; i < len; i++) {
1627 Constructor c = (Constructor) instance_constructors [i];
1629 ConstructorBuilder cb = c.ConstructorBuilder;
1630 if (cb != null && filter (cb, criteria) == true) {
1631 if (members == null)
1632 members = new ArrayList ();
1639 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1640 ConstructorBuilder cb =
1641 default_static_constructor.ConstructorBuilder;
1643 if (cb != null && filter (cb, criteria) == true) {
1644 if (members == null)
1645 members = new ArrayList ();
1653 // Lookup members in parent if requested.
1655 if ((bf & BindingFlags.DeclaredOnly) == 0) {
1656 if (TypeBuilder.BaseType != null) {
1657 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1658 if (list.Count > 0) {
1659 if (members == null)
1660 members = new ArrayList ();
1662 members.AddRange (list);
1665 if (base_inteface_types != null) {
1666 foreach (Type base_type in base_inteface_types) {
1667 MemberList list = TypeContainer.FindMembers (base_type, mt, bf, filter, criteria);
1669 if (list.Count > 0) {
1670 if (members == null)
1671 members = new ArrayList ();
1672 members.AddRange (list);
1678 Timer.StopTimer (TimerType.TcFindMembers);
1680 if (members == null)
1681 return MemberList.Empty;
1683 return new MemberList (members);
1686 public override MemberCache MemberCache {
1688 return member_cache;
1692 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1693 MemberFilter filter, object criteria)
1695 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1698 return ds.FindMembers (mt, bf, filter, criteria);
1700 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1705 // FindMethods will look for methods not only in the type `t', but in
1706 // any interfaces implemented by the type.
1708 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1709 MemberFilter filter, object criteria)
1715 /// Emits the values for the constants
1717 public void EmitConstants ()
1719 if (constants != null)
1720 foreach (Const con in constants)
1725 protected virtual void VerifyMembers (EmitContext ec)
1728 // Check for internal or private fields that were never assigned
1730 if (RootContext.WarningLevel >= 3) {
1731 if (fields != null){
1732 foreach (Field f in fields) {
1733 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
1736 if ((f.status & Field.Status.USED) == 0){
1738 169, f.Location, "Private field " +
1739 MakeName (f.Name) + " is never used");
1744 // Only report 649 on level 4
1746 if (RootContext.WarningLevel < 4)
1749 if ((f.status & Field.Status.ASSIGNED) != 0)
1754 "Field " + MakeName (f.Name) + " is never assigned " +
1755 " to and will always have its default value");
1759 if (events != null){
1760 foreach (Event e in events){
1762 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1769 /// Emits the code, this step is performed after all
1770 /// the types, enumerations, constructors
1774 if (OptAttributes != null)
1775 OptAttributes.Emit (ec, this);
1779 if (instance_constructors != null) {
1780 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && IsClsCompliaceRequired (this)) {
1781 bool has_compliant_args = false;
1783 foreach (Constructor c in instance_constructors) {
1786 if (has_compliant_args)
1789 has_compliant_args = c.HasCompliantArgs;
1791 if (!has_compliant_args)
1792 Report.Error_T (3015, Location, GetSignatureForError ());
1794 foreach (Constructor c in instance_constructors)
1799 if (default_static_constructor != null)
1800 default_static_constructor.Emit (this);
1802 if (methods != null)
1803 foreach (Method m in methods)
1806 if (operators != null)
1807 foreach (Operator o in operators)
1810 if (properties != null)
1811 foreach (Property p in properties)
1814 if (indexers != null){
1815 foreach (Indexer ix in indexers)
1817 if (IndexerName != null) {
1818 CustomAttributeBuilder cb = EmitDefaultMemberAttr ();
1819 TypeBuilder.SetCustomAttribute (cb);
1824 foreach (Field f in fields)
1827 if (events != null){
1828 foreach (Event e in Events)
1832 if (delegates != null) {
1833 foreach (Delegate d in Delegates) {
1838 if (Pending != null)
1839 if (Pending.VerifyPendingMethods ())
1844 // if (types != null)
1845 // foreach (TypeContainer tc in types)
1849 CustomAttributeBuilder EmitDefaultMemberAttr ()
1851 EmitContext ec = new EmitContext (this, Location, null, null, ModFlags);
1853 Expression ml = Expression.MemberLookup (ec, TypeManager.default_member_type,
1854 ".ctor", MemberTypes.Constructor,
1855 BindingFlags.Public | BindingFlags.Instance,
1858 MethodGroupExpr mg = (MethodGroupExpr) ml;
1860 MethodBase constructor = mg.Methods [0];
1862 string [] vals = { IndexerName };
1864 CustomAttributeBuilder cb = null;
1866 cb = new CustomAttributeBuilder ((ConstructorInfo) constructor, vals);
1868 Report.Warning (-100, "Can not set the indexer default member attribute");
1874 public override void CloseType ()
1876 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1880 caching_flags |= Flags.CloseTypeCreated;
1881 TypeBuilder.CreateType ();
1882 } catch (TypeLoadException){
1884 // This is fine, the code still created the type
1886 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1887 // Console.WriteLine (e.Message);
1889 Console.WriteLine ("In type: " + Name);
1894 foreach (Enum en in Enums)
1897 if (interface_order != null){
1898 foreach (Interface iface in interface_order)
1903 foreach (TypeContainer tc in Types)
1907 foreach (TypeContainer tc in Types)
1908 if (!(tc is Struct))
1912 if (Delegates != null)
1913 foreach (Delegate d in Delegates)
1921 initialized_fields = null;
1922 initialized_static_fields = null;
1925 interface_order = null;
1931 default_constructor = null;
1932 default_static_constructor = null;
1934 OptAttributes = null;
1936 parent_container = null;
1937 member_cache = null;
1940 public string MakeName (string n)
1942 return "`" + Name + "." + n + "'";
1945 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1948 108, l, "The keyword new is required on " +
1949 MakeName (mi.Name) + " because it hides `" +
1950 mi.ReflectedType.Name + "." + mi.Name + "'");
1953 public void Warning_KeywordNewNotRequired (Location l, MemberCore mc)
1956 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1957 "inherited member, the keyword new is not required");
1960 public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
1963 72, l, MakeName (mi.Name) + " : cannot override; `" +
1964 mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
1967 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1973 // Performs the validation on a Method's modifiers (properties have
1974 // the same properties).
1976 public bool MethodModifiersValid (int flags, string n, Location loc)
1978 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1979 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1980 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1984 // At most one of static, virtual or override
1986 if ((flags & Modifiers.STATIC) != 0){
1987 if ((flags & vao) != 0){
1989 112, loc, "static method " + MakeName (n) + "can not be marked " +
1990 "as virtual, abstract or override");
1995 if (this is Struct){
1996 if ((flags & va) != 0){
1997 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
2002 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2004 113, loc, MakeName (n) +
2005 " marked as override cannot be marked as new or virtual");
2010 // If the declaration includes the abstract modifier, then the
2011 // declaration does not include static, virtual or extern
2013 if ((flags & Modifiers.ABSTRACT) != 0){
2014 if ((flags & Modifiers.EXTERN) != 0){
2016 180, loc, MakeName (n) + " can not be both abstract and extern");
2020 if ((flags & Modifiers.VIRTUAL) != 0){
2022 503, loc, MakeName (n) + " can not be both abstract and virtual");
2026 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2028 513, loc, MakeName (n) +
2029 " is abstract but its container class is not");
2035 if ((flags & Modifiers.PRIVATE) != 0){
2036 if ((flags & vao) != 0){
2038 621, loc, MakeName (n) +
2039 " virtual or abstract members can not be private");
2044 if ((flags & Modifiers.SEALED) != 0){
2045 if ((flags & Modifiers.OVERRIDE) == 0){
2047 238, loc, MakeName (n) +
2048 " cannot be sealed because it is not an override");
2056 Hashtable builder_and_args;
2058 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
2060 if (builder_and_args == null)
2061 builder_and_args = new Hashtable ();
2065 protected override bool VerifyClsCompliance (DeclSpace ds)
2067 if (!base.VerifyClsCompliance (ds))
2070 // parent_container is null for System.Object
2071 if (parent_container != null && !AttributeTester.IsClsCompliant (parent_container.Type)) {
2072 Report.Error_T (3009, Location, GetSignatureForError (), TypeManager.CSharpName (parent_container.Type));
2079 /// Performs checks for an explicit interface implementation. First it
2080 /// checks whether the `interface_type' is a base inteface implementation.
2081 /// Then it checks whether `name' exists in the interface type.
2083 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
2087 if (ifaces != null){
2088 foreach (TypeExpr t in ifaces){
2089 if (t.Type == interface_type){
2097 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
2108 string IMemberContainer.Name {
2114 Type IMemberContainer.Type {
2120 IMemberContainer IMemberContainer.Parent {
2122 return parent_container;
2126 MemberCache IMemberContainer.MemberCache {
2128 return member_cache;
2132 bool IMemberContainer.IsInterface {
2134 return this is Interface;
2138 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2140 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
2144 // Operator pair checking
2147 class OperatorEntry {
2149 public Type ret_type;
2150 public Type type1, type2;
2152 public Operator.OpType ot;
2154 public OperatorEntry (int f, Operator o)
2158 ret_type = o.OperatorMethod.GetReturnType ();
2159 Type [] pt = o.OperatorMethod.ParameterTypes;
2163 ot = o.OperatorType;
2166 public override int GetHashCode ()
2168 return ret_type.GetHashCode ();
2171 public override bool Equals (object o)
2173 OperatorEntry other = (OperatorEntry) o;
2175 if (other.ret_type != ret_type)
2177 if (other.type1 != type1)
2179 if (other.type2 != type2)
2186 // Checks that some operators come in pairs:
2192 // They are matched based on the return type and the argument types
2194 void CheckPairedOperators ()
2196 Hashtable pairs = new Hashtable (null, null);
2197 Operator true_op = null;
2198 Operator false_op = null;
2199 bool has_equality_or_inequality = false;
2201 // Register all the operators we care about.
2202 foreach (Operator op in operators){
2205 switch (op.OperatorType){
2206 case Operator.OpType.Equality:
2208 has_equality_or_inequality = true;
2210 case Operator.OpType.Inequality:
2212 has_equality_or_inequality = true;
2215 case Operator.OpType.True:
2218 case Operator.OpType.False:
2222 case Operator.OpType.GreaterThan:
2224 case Operator.OpType.LessThan:
2227 case Operator.OpType.GreaterThanOrEqual:
2229 case Operator.OpType.LessThanOrEqual:
2235 OperatorEntry oe = new OperatorEntry (reg, op);
2237 object o = pairs [oe];
2241 oe = (OperatorEntry) o;
2246 if (true_op != null){
2247 if (false_op == null)
2248 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
2249 } else if (false_op != null)
2250 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
2253 // Look for the mistakes.
2255 foreach (DictionaryEntry de in pairs){
2256 OperatorEntry oe = (OperatorEntry) de.Key;
2263 case Operator.OpType.Equality:
2266 case Operator.OpType.Inequality:
2269 case Operator.OpType.GreaterThan:
2272 case Operator.OpType.LessThan:
2275 case Operator.OpType.GreaterThanOrEqual:
2278 case Operator.OpType.LessThanOrEqual:
2282 Report.Error (216, oe.op.Location,
2283 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2286 if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2287 MethodSignature equals_ms = new MethodSignature (
2288 "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2289 MethodSignature hash_ms = new MethodSignature (
2290 "GetHashCode", TypeManager.int32_type, new Type [0]);
2292 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2293 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2295 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2296 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2299 bool equals_ok = false;
2300 if ((equals_ml != null) && (equals_ml.Count == 1))
2301 equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2302 bool hash_ok = false;
2303 if ((hash_ml != null) && (hash_ml.Count == 1))
2304 hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2307 Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2308 "not override Object.Equals (object o)");
2310 Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2311 "not override Object.GetHashCode ()");
2318 public class ClassOrStruct : TypeContainer {
2319 bool hasExplicitLayout = false;
2320 public ClassOrStruct (NamespaceEntry ns, TypeContainer parent, string name, Attributes attrs, Location l)
2321 : base (ns, parent, name, attrs, l)
2325 protected override void VerifyMembers (EmitContext ec)
2327 if (Fields != null) {
2328 foreach (Field f in Fields) {
2329 if ((f.ModFlags & Modifiers.STATIC) != 0)
2331 if (hasExplicitLayout) {
2332 if (f.OptAttributes == null
2333 || !f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, ec)) {
2334 Report.Error (625, f.Location,
2335 "Instance field of type marked with"
2336 + " StructLayout(LayoutKind.Explicit) must have a"
2337 + " FieldOffset attribute.");
2341 if (f.OptAttributes != null
2342 && f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, ec)) {
2343 Report.Error (636, f.Location,
2344 "The FieldOffset attribute can only be placed on members of "
2345 + "types marked with the StructLayout(LayoutKind.Explicit)");
2350 base.VerifyMembers (ec);
2353 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2355 if (a.Type == TypeManager.struct_layout_attribute_type
2356 && (LayoutKind) a.GetPositionalValue (0) == LayoutKind.Explicit)
2357 hasExplicitLayout = true;
2359 base.ApplyAttributeBuilder (a, cb);
2363 public class Class : ClassOrStruct {
2365 // Modifiers allowed in a class declaration
2367 public const int AllowedModifiers =
2370 Modifiers.PROTECTED |
2371 Modifiers.INTERNAL |
2373 Modifiers.ABSTRACT |
2378 // Information in the case we are an attribute type
2379 AttributeUsageAttribute attribute_usage;
2381 public Class (NamespaceEntry ns, TypeContainer parent, string name, int mod,
2382 Attributes attrs, Location l)
2383 : base (ns, parent, name, attrs, l)
2387 if (parent.Parent == null)
2388 accmods = Modifiers.INTERNAL;
2390 accmods = Modifiers.PRIVATE;
2392 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2393 attribute_usage = new AttributeUsageAttribute (AttributeTargets.All);
2396 public override AttributeTargets AttributeTargets {
2398 return AttributeTargets.Class;
2402 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
2404 if (a.UsageAttribute != null)
2405 attribute_usage = a.UsageAttribute;
2407 base.ApplyAttributeBuilder (a, cb);
2410 public AttributeUsageAttribute AttributeUsage {
2412 return attribute_usage;
2417 // FIXME: How do we deal with the user specifying a different
2420 public override TypeAttributes TypeAttr {
2422 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2427 public class Struct : ClassOrStruct {
2429 // Modifiers allowed in a struct declaration
2431 public const int AllowedModifiers =
2434 Modifiers.PROTECTED |
2435 Modifiers.INTERNAL |
2439 public Struct (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2440 : base (ns, parent, name, attrs, l)
2444 if (parent.Parent == null)
2445 accmods = Modifiers.INTERNAL;
2447 accmods = Modifiers.PRIVATE;
2449 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2451 this.ModFlags |= Modifiers.SEALED;
2454 public override AttributeTargets AttributeTargets {
2456 return AttributeTargets.Struct;
2462 // FIXME: Allow the user to specify a different set of attributes
2463 // in some cases (Sealed for example is mandatory for a class,
2464 // but what SequentialLayout can be changed
2466 public override TypeAttributes TypeAttr {
2468 return base.TypeAttr |
2469 TypeAttributes.SequentialLayout |
2470 TypeAttributes.Sealed |
2471 TypeAttributes.BeforeFieldInit;
2479 public class Interface : TypeContainer, IMemberContainer {
2481 /// Modifiers allowed in a class declaration
2483 public const int AllowedModifiers =
2486 Modifiers.PROTECTED |
2487 Modifiers.INTERNAL |
2491 public Interface (NamespaceEntry ns, TypeContainer parent, string name, int mod,
2492 Attributes attrs, Location l)
2493 : base (ns, parent, name, attrs, l)
2497 if (parent.Parent == null)
2498 accmods = Modifiers.INTERNAL;
2500 accmods = Modifiers.PRIVATE;
2502 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2505 public override AttributeTargets AttributeTargets {
2507 return AttributeTargets.Interface;
2511 public override TypeAttributes TypeAttr {
2513 return base.TypeAttr |
2514 TypeAttributes.AutoLayout |
2515 TypeAttributes.Abstract |
2516 TypeAttributes.Interface;
2521 public abstract class MethodCore : MemberBase {
2522 public readonly Parameters Parameters;
2523 protected Block block;
2524 public DeclSpace ds;
2527 // Parameters, cached for semantic analysis.
2529 protected InternalParameters parameter_info;
2530 protected Type [] parameter_types;
2533 // This is set from TypeContainer.DefineMembers if this method overrides something.
2535 public bool OverridesSomething;
2537 // Whether this is an operator method.
2538 public bool IsOperator;
2540 static string[] attribute_targets = new string [] { "method", "return" };
2542 public MethodCore (DeclSpace ds, Expression type, int mod, int allowed_mod,
2543 bool is_interface, string name, Attributes attrs,
2544 Parameters parameters, Location loc)
2545 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
2547 Parameters = parameters;
2548 IsInterface = is_interface;
2553 // Returns the System.Type array for the parameters of this method
2555 public Type [] ParameterTypes {
2557 return parameter_types;
2561 public InternalParameters ParameterInfo
2564 return parameter_info;
2568 public Block Block {
2578 protected virtual bool DoDefineParameters ()
2580 // Check if arguments were correct
2581 parameter_types = Parameters.GetParameterInfo (ds);
2582 if ((parameter_types == null) || !CheckParameters (ds, parameter_types))
2585 parameter_info = new InternalParameters (ds, Parameters);
2587 Parameter array_param = Parameters.ArrayParameter;
2588 if ((array_param != null) &&
2589 (!array_param.ParameterType.IsArray ||
2590 (array_param.ParameterType.GetArrayRank () != 1))) {
2591 Report.Error (225, Location, "params parameter has to be a single dimensional array");
2598 protected override string[] ValidAttributeTargets {
2600 return attribute_targets;
2604 protected override bool VerifyClsCompliance (DeclSpace ds)
2606 if (!base.VerifyClsCompliance (ds)) {
2607 if ((ModFlags & Modifiers.ABSTRACT) != 0 && IsExposedFromAssembly (ds) && ds.IsClsCompliaceRequired (ds)) {
2608 Report.Error_T (3011, Location, GetSignatureForError ());
2613 AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location);
2615 if (!AttributeTester.IsClsCompliant (MemberType)) {
2616 Report.Error_T (3002, Location, GetSignatureForError ());
2622 protected bool IsDuplicateImplementation (TypeContainer tc, MethodCore method)
2624 if ((method == this) || (method.Name != Name))
2627 Type[] param_types = method.ParameterTypes;
2628 if (param_types == null)
2631 if (param_types.Length != ParameterTypes.Length)
2634 for (int i = 0; i < param_types.Length; i++)
2635 if (param_types [i] != ParameterTypes [i])
2639 // Try to report 663: method only differs on out/ref
2641 ParameterData info = ParameterInfo;
2642 ParameterData other_info = method.ParameterInfo;
2643 for (int i = 0; i < info.Count; i++){
2644 if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
2645 Report.Error (663, Location, "Overload method only differs in parameter modifier");
2650 Report.Error (111, Location, "Class `{0}' already defines a " +
2651 "member called `{1}' with the same parameter types",
2656 public CallingConventions GetCallingConvention (bool is_class)
2658 CallingConventions cc = 0;
2660 cc = Parameters.GetCallingConvention ();
2663 if ((ModFlags & Modifiers.STATIC) == 0)
2664 cc |= CallingConventions.HasThis;
2666 // FIXME: How is `ExplicitThis' used in C#?
2672 public class Method : MethodCore, IIteratorContainer, IMethodData {
2673 public MethodBuilder MethodBuilder;
2674 public MethodData MethodData;
2675 ReturnParameter return_attributes;
2678 /// Modifiers allowed in a class declaration
2680 const int AllowedModifiers =
2683 Modifiers.PROTECTED |
2684 Modifiers.INTERNAL |
2689 Modifiers.OVERRIDE |
2690 Modifiers.ABSTRACT |
2692 Modifiers.METHOD_YIELDS |
2695 const int AllowedInterfaceModifiers =
2696 Modifiers.NEW | Modifiers.UNSAFE;
2699 // return_type can be "null" for VOID values.
2701 public Method (DeclSpace ds, Expression return_type, int mod, bool is_iface,
2702 string name, Parameters parameters, Attributes attrs, Location l)
2703 : base (ds, return_type, mod,
2704 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
2705 is_iface, name, attrs, parameters, l)
2709 public override AttributeTargets AttributeTargets {
2711 return AttributeTargets.Method | AttributeTargets.ReturnValue;
2716 // Returns the `System.Type' for the ReturnType of this
2717 // function. Provides a nice cache. (used between semantic analysis
2718 // and actual code generation
2720 public Type GetReturnType ()
2725 public override string GetSignatureForError()
2727 return TypeManager.CSharpSignature (MethodBuilder);
2730 void DuplicateEntryPoint (MethodInfo b, Location location)
2734 "Program `" + CodeGen.FileName +
2735 "' has more than one entry point defined: `" +
2736 TypeManager.CSharpSignature(b) + "'");
2739 void Report28 (MethodInfo b)
2743 "`" + TypeManager.CSharpSignature(b) +
2744 "' has the wrong signature to be an entry point");
2747 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2749 if (b.ReturnType != TypeManager.void_type &&
2750 b.ReturnType != TypeManager.int32_type)
2753 if (pinfo.Count == 0)
2756 if (pinfo.Count > 1)
2759 Type t = pinfo.ParameterType(0);
2761 (t.GetArrayRank() == 1) &&
2762 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
2763 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2769 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2771 if (a.Target == "return") {
2772 if (return_attributes == null)
2773 return_attributes = new ReturnParameter (MethodBuilder, Location);
2775 return_attributes.ApplyAttributeBuilder (a, cb);
2779 if (a.Type == TypeManager.methodimpl_attr_type && a.IsInternalCall) {
2780 MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
2783 if (a.Type == TypeManager.dllimport_type)
2786 MethodBuilder.SetCustomAttribute (cb);
2790 // Checks our base implementation if any
2792 protected override bool CheckBase (TypeContainer container)
2794 base.CheckBase (container);
2796 // Check whether arguments were correct.
2797 if (!DoDefineParameters ())
2800 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2802 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2805 // Check in our class for dups
2807 ArrayList ar = container.Methods;
2809 int arLen = ar.Count;
2811 for (int i = 0; i < arLen; i++) {
2812 Method m = (Method) ar [i];
2813 if (IsDuplicateImplementation (container, m))
2821 // Verify if the parent has a type with the same name, and then
2822 // check whether we have to create a new slot for it or not.
2824 Type ptype = container.TypeBuilder.BaseType;
2826 // ptype is only null for System.Object while compiling corlib.
2827 if (ptype != null) {
2830 // Explicit implementations do not have `parent' methods, however,
2831 // the member cache stores them there. Without this check, we get
2832 // an incorrect warning in corlib.
2834 if (! IsExplicitImpl) {
2835 parent_method = (MethodInfo)((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
2836 container.TypeBuilder, Name, ParameterTypes, false);
2839 if (parent_method != null) {
2840 string name = parent_method.DeclaringType.Name + "." +
2843 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
2846 if ((ModFlags & Modifiers.NEW) == 0) {
2847 Type parent_ret = TypeManager.TypeToCoreType (
2848 parent_method.ReturnType);
2850 if (parent_ret != MemberType) {
2852 508, Location, container.MakeName (Name) + ": cannot " +
2853 "change return type when overriding " +
2854 "inherited member " + name);
2859 if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
2860 WarningNotHiding (container);
2862 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2863 Report.Error (115, Location,
2864 container.MakeName (Name) +
2865 " no suitable methods found to override");
2868 } else if ((ModFlags & Modifiers.NEW) != 0)
2869 WarningNotHiding (container);
2877 public override bool Define (TypeContainer container)
2879 if (!DoDefine (container))
2882 if (!CheckBase (container))
2885 MethodData = new MethodData (this, ParameterInfo, ModFlags, flags, true, this);
2887 if (!MethodData.Define (container))
2891 // Setup iterator if we are one
2893 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
2894 IteratorHandler ih = new IteratorHandler (
2895 Name, container, MemberType,
2896 ParameterTypes, ParameterInfo,
2897 ModFlags, Location);
2899 Block new_block = ih.Setup (block);
2900 if (new_block == null)
2905 MethodBuilder = MethodData.MethodBuilder;
2908 // This is used to track the Entry Point,
2910 if (Name == "Main" &&
2911 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
2912 (RootContext.MainClass == null ||
2913 RootContext.MainClass == container.TypeBuilder.FullName)){
2914 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2915 if (RootContext.EntryPoint == null) {
2916 RootContext.EntryPoint = MethodBuilder;
2917 RootContext.EntryPointLocation = Location;
2919 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2920 DuplicateEntryPoint (MethodBuilder, Location);
2923 Report28(MethodBuilder);
2932 public override void Emit (TypeContainer container)
2934 MethodData.Emit (container, this);
2935 base.Emit (container);
2940 void IIteratorContainer.SetYields ()
2942 ModFlags |= Modifiers.METHOD_YIELDS;
2945 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
2947 return IsIdentifierAndParamClsCompliant (ds, Name, MethodBuilder, parameter_types);
2950 #region IMethodData Members
2952 public CallingConventions CallingConventions {
2954 CallingConventions cc = Parameters.GetCallingConvention ();
2957 if ((ModFlags & Modifiers.STATIC) == 0)
2958 cc |= CallingConventions.HasThis;
2960 // FIXME: How is `ExplicitThis' used in C#?
2966 public Type ReturnType {
2972 public string MethodName {
2978 public new Location Location {
2980 return base.Location;
2984 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
2986 return new EmitContext (tc, ds, Location, ig, ReturnType, ModFlags, false);
2992 public abstract class ConstructorInitializer {
2993 ArrayList argument_list;
2994 ConstructorInfo parent_constructor;
2995 Parameters parameters;
2998 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
3001 this.argument_list = argument_list;
3002 this.parameters = parameters;
3006 public ArrayList Arguments {
3008 return argument_list;
3012 public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
3014 Expression parent_constructor_group;
3017 ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
3019 if (argument_list != null){
3020 foreach (Argument a in argument_list){
3021 if (!a.Resolve (ec, loc))
3025 ec.CurrentBlock = null;
3027 if (this is ConstructorBaseInitializer) {
3028 if (ec.ContainerType.BaseType == null)
3031 t = ec.ContainerType.BaseType;
3032 if (ec.ContainerType.IsValueType) {
3033 Report.Error (522, loc,
3034 "structs cannot call base class constructors");
3038 t = ec.ContainerType;
3040 parent_constructor_group = Expression.MemberLookup (
3041 ec, t, ".ctor", MemberTypes.Constructor,
3042 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3045 if (parent_constructor_group == null){
3046 parent_constructor_group = Expression.MemberLookup (
3047 ec, t, ".ctor", MemberTypes.Constructor,
3048 BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3051 if (parent_constructor_group != null)
3053 112, loc, "`{0}.{1}' is inaccessible due to " +
3054 "its protection level", t.FullName, t.Name);
3057 1501, loc, "Can not find a constructor for " +
3058 "this argument list");
3062 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
3063 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
3065 if (parent_constructor == null){
3066 Report.Error (1501, loc,
3067 "Can not find a constructor for this argument list");
3071 if (parent_constructor == caller_builder){
3072 Report.Error (515, String.Format ("Constructor `{0}' can not call itself", TypeManager.CSharpSignature (caller_builder)));
3079 public void Emit (EmitContext ec)
3081 if (parent_constructor != null){
3082 ec.Mark (loc, false);
3084 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
3086 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
3091 public class ConstructorBaseInitializer : ConstructorInitializer {
3092 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
3093 base (argument_list, pars, l)
3098 public class ConstructorThisInitializer : ConstructorInitializer {
3099 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
3100 base (argument_list, pars, l)
3105 public class Constructor : MethodCore {
3106 public ConstructorBuilder ConstructorBuilder;
3107 public ConstructorInitializer Initializer;
3110 // Modifiers allowed for a constructor.
3112 public const int AllowedModifiers =
3114 Modifiers.PROTECTED |
3115 Modifiers.INTERNAL |
3121 bool has_compliant_args = false;
3123 // The spec claims that static is not permitted, but
3124 // my very own code has static constructors.
3126 public Constructor (DeclSpace ds, string name, int mod, Parameters args,
3127 ConstructorInitializer init, Location l)
3128 : base (ds, null, mod, AllowedModifiers, false, name, null, args, l)
3133 public override string GetSignatureForError()
3135 return TypeManager.CSharpSignature (ConstructorBuilder);
3138 public bool HasCompliantArgs {
3140 return has_compliant_args;
3144 public override AttributeTargets AttributeTargets {
3146 return AttributeTargets.Constructor;
3152 // Returns true if this is a default constructor
3154 public bool IsDefault ()
3156 if ((ModFlags & Modifiers.STATIC) != 0)
3157 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3158 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
3161 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3162 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
3163 (Initializer is ConstructorBaseInitializer) &&
3164 (Initializer.Arguments == null);
3167 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3169 ConstructorBuilder.SetCustomAttribute (cb);
3172 protected override bool CheckBase (TypeContainer container)
3174 base.CheckBase (container);
3176 // Check whether arguments were correct.
3177 if (!DoDefineParameters ())
3180 if ((ModFlags & Modifiers.STATIC) != 0)
3183 if (container is Struct && ParameterTypes.Length == 0) {
3184 Report.Error (568, Location,
3185 "Structs can not contain explicit parameterless " +
3191 // Check in our class for dups
3193 ArrayList ar = container.InstanceConstructors;
3195 int arLen = ar.Count;
3197 for (int i = 0; i < arLen; i++) {
3198 Constructor m = (Constructor) ar [i];
3199 if (IsDuplicateImplementation (container, m))
3208 // Creates the ConstructorBuilder
3210 public override bool Define (TypeContainer container)
3212 MethodAttributes ca = (MethodAttributes.RTSpecialName |
3213 MethodAttributes.SpecialName);
3215 if ((ModFlags & Modifiers.STATIC) != 0) {
3216 ca |= MethodAttributes.Static | MethodAttributes.Private;
3218 ca |= MethodAttributes.HideBySig;
3220 if ((ModFlags & Modifiers.PUBLIC) != 0)
3221 ca |= MethodAttributes.Public;
3222 else if ((ModFlags & Modifiers.PROTECTED) != 0){
3223 if ((ModFlags & Modifiers.INTERNAL) != 0)
3224 ca |= MethodAttributes.FamORAssem;
3226 ca |= MethodAttributes.Family;
3227 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
3228 ca |= MethodAttributes.Assembly;
3229 else if (IsDefault ())
3230 ca |= MethodAttributes.Public;
3232 ca |= MethodAttributes.Private;
3235 // Check if arguments were correct.
3236 if (!CheckBase (container))
3239 ConstructorBuilder = container.TypeBuilder.DefineConstructor (
3240 ca, GetCallingConvention (container is Class), ParameterTypes);
3242 if ((ModFlags & Modifiers.UNSAFE) != 0)
3243 ConstructorBuilder.InitLocals = false;
3246 // HACK because System.Reflection.Emit is lame
3248 TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes);
3256 public override void Emit (TypeContainer container)
3258 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
3259 EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
3262 // extern methods have no bodies
3264 if ((ModFlags & Modifiers.EXTERN) != 0) {
3265 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
3267 179, Location, "External constructor `" +
3268 TypeManager.CSharpSignature (ConstructorBuilder) +
3269 "' can not have a body");
3272 } else if (block == null) {
3274 501, Location, "Constructor `" +
3275 TypeManager.CSharpSignature (ConstructorBuilder) +
3276 "' must declare a body since it is not marked extern");
3280 if ((ModFlags & Modifiers.STATIC) == 0){
3281 if (container is Class && Initializer == null)
3282 Initializer = new ConstructorBaseInitializer (
3283 null, Parameters.EmptyReadOnlyParameters, Location);
3287 // Spec mandates that Initializers will not have
3291 if (Initializer != null && !Initializer.Resolve (ConstructorBuilder, ec))
3293 ec.IsStatic = false;
3296 Parameters.LabelParameters (ec, ConstructorBuilder, Location);
3298 SymbolWriter sw = CodeGen.SymbolWriter;
3299 bool generate_debugging = false;
3301 if ((sw != null) && (block != null) &&
3302 !Location.IsNull (Location) &&
3303 !Location.IsNull (block.EndLocation) &&
3304 (Location.SymbolDocument != null)) {
3305 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
3307 generate_debugging = true;
3311 // Classes can have base initializers and instance field initializers.
3313 if (container is Class){
3314 if ((ModFlags & Modifiers.STATIC) == 0){
3317 // If we use a "this (...)" constructor initializer, then
3318 // do not emit field initializers, they are initialized in the other constructor
3320 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
3321 container.EmitFieldInitializers (ec);
3324 if (Initializer != null)
3325 Initializer.Emit (ec);
3327 if ((ModFlags & Modifiers.STATIC) != 0)
3328 container.EmitFieldInitializers (ec);
3330 if (OptAttributes != null)
3331 OptAttributes.Emit (ec, this);
3333 // If this is a non-static `struct' constructor and doesn't have any
3334 // initializer, it must initialize all of the struct's fields.
3335 if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
3336 Block.AddThisVariable (container, Location);
3338 ec.EmitTopBlock (block, ParameterInfo, Location);
3340 if (generate_debugging)
3343 base.Emit (container);
3348 // For constructors is needed to test only parameters
3349 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
3351 if (parameter_types == null || parameter_types.Length == 0)
3354 TypeContainer tc = ds as TypeContainer;
3356 for (int i = 0; i < tc.InstanceConstructors.Count; i++) {
3357 Constructor c = (Constructor) tc.InstanceConstructors [i];
3359 if (c == this || c.ParameterTypes.Length == 0)
3362 if (!c.IsClsCompliaceRequired (ds))
3365 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, c.ParameterTypes)) {
3366 Report.Error_T (3006, Location, GetSignatureForError ());
3371 if (tc.TypeBuilder.BaseType == null)
3374 DeclSpace temp_ds = TypeManager.LookupDeclSpace (tc.TypeBuilder.BaseType);
3375 if (temp_ds != null)
3376 return IsIdentifierClsCompliant (temp_ds);
3378 MemberInfo[] ml = tc.TypeBuilder.BaseType.FindMembers (MemberTypes.Constructor, BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance, null, null);
3379 // Skip parameter-less ctor
3383 foreach (ConstructorInfo ci in ml) {
3384 object[] cls_attribute = ci.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false);
3385 if (cls_attribute.Length == 1 && (!((CLSCompliantAttribute)cls_attribute[0]).IsCompliant))
3388 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, TypeManager.GetArgumentTypes (ci))) {
3389 Report.Error_T (3006, Location, GetSignatureForError ());
3397 protected override bool VerifyClsCompliance (DeclSpace ds)
3399 if (!base.VerifyClsCompliance (ds) || !IsExposedFromAssembly (ds)) {
3403 if (ds.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
3404 foreach (Type param in parameter_types) {
3405 if (param.IsArray) {
3410 has_compliant_args = true;
3417 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
3419 public interface IMethodData
3421 CallingConventions CallingConventions { get; }
3422 Location Location { get; }
3423 string MethodName { get; }
3424 Type[] ParameterTypes { get; }
3425 Type ReturnType { get; }
3427 Attributes OptAttributes { get; }
3428 Block Block { get; }
3430 EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig);
3434 // Encapsulates most of the Method's state
3436 public class MethodData {
3438 readonly IMethodData method;
3441 // The return type of this method
3443 public readonly InternalParameters ParameterInfo;
3446 // Are we implementing an interface ?
3448 public bool IsImplementing = false;
3453 protected MemberBase member;
3454 protected int modifiers;
3455 protected MethodAttributes flags;
3456 protected bool is_method;
3459 // It can either hold a string with the condition, or an arraylist of conditions.
3460 object conditionals;
3462 MethodBuilder builder = null;
3463 public MethodBuilder MethodBuilder {
3469 public MethodData (MemberBase member, InternalParameters parameters,
3470 int modifiers, MethodAttributes flags, bool is_method, IMethodData method)
3472 this.member = member;
3473 this.ParameterInfo = parameters;
3474 this.modifiers = modifiers;
3476 this.is_method = is_method;
3477 this.conditionals = null;
3479 this.method = method;
3485 Attribute dllimport_attribute = null;
3486 string obsolete = null;
3487 bool obsolete_error = false;
3489 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method,
3492 if ((opt_attrs == null) || (opt_attrs.Attrs == null))
3495 foreach (Attribute a in opt_attrs.Attrs) {
3496 Type attr_type = a.ResolveType (ec, true);
3497 if (attr_type == TypeManager.conditional_attribute_type) {
3498 if (!ApplyConditionalAttribute (a))
3500 } else if (attr_type == TypeManager.obsolete_attribute_type) {
3501 if (!ApplyObsoleteAttribute (a))
3503 } else if (attr_type == TypeManager.dllimport_type) {
3505 Attribute.Error_AttributeNotValidForElement (a, method.Location);
3508 if (!ApplyDllImportAttribute (a))
3517 // Applies the `DllImport' attribute to the method.
3519 protected virtual bool ApplyDllImportAttribute (Attribute a)
3521 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3522 if ((modifiers & extern_static) != extern_static) {
3523 Report.Error (601, method.Location,
3524 "The DllImport attribute must be specified on a method " +
3525 "marked `static' and `extern'.");
3529 flags |= MethodAttributes.PinvokeImpl;
3530 dllimport_attribute = a;
3535 // Applies the `Obsolete' attribute to the method.
3537 protected virtual bool ApplyObsoleteAttribute (Attribute a)
3539 if (obsolete != null) {
3540 Report.Error (579, method.Location, "Duplicate `Obsolete' attribute");
3544 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
3545 return obsolete != null;
3549 // Applies the `Conditional' attribute to the method.
3551 protected virtual bool ApplyConditionalAttribute (Attribute a)
3553 // The Conditional attribute is only valid on methods.
3555 Attribute.Error_AttributeNotValidForElement (a, method.Location);
3559 string condition = a.Conditional_GetConditionName ();
3561 if (condition == null)
3564 if (method.ReturnType != TypeManager.void_type) {
3565 Report.Error (578, method.Location,
3566 "Conditional not valid on `" + member.Name + "' " +
3567 "because its return type is not void");
3571 if ((modifiers & Modifiers.OVERRIDE) != 0) {
3572 Report.Error (243, method.Location,
3573 "Conditional not valid on `" + member.Name + "' " +
3574 "because it is an override method");
3578 if (member.IsExplicitImpl) {
3579 Report.Error (577, method.Location,
3580 "Conditional not valid on `" + member.Name + "' " +
3581 "because it is an explicit interface implementation");
3585 if (IsImplementing) {
3586 Report.Error (623, method.Location,
3587 "Conditional not valid on `" + member.Name + "' " +
3588 "because it is an interface method");
3593 // The likelyhood that the conditional will be more than 1 is very slim
3595 if (conditionals == null)
3596 conditionals = condition;
3597 else if (conditionals is string){
3598 string s = (string) conditionals;
3599 conditionals = new ArrayList ();
3600 ((ArrayList)conditionals).Add (s);
3602 ((ArrayList)conditionals).Add (condition);
3608 // Checks whether this method should be ignored due to its Conditional attributes.
3610 bool ShouldIgnore (Location loc)
3612 // When we're overriding a virtual method, we implicitly inherit the
3613 // Conditional attributes from our parent.
3614 if (member.ParentMethod != null) {
3615 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
3616 member.ParentMethod, loc);
3618 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
3622 if (conditionals != null){
3623 if (conditionals is string){
3624 if (RootContext.AllDefines [conditionals] == null)
3627 foreach (string condition in (ArrayList) conditionals)
3628 if (RootContext.AllDefines [condition] == null)
3636 // Returns the TypeManager.MethodFlags for this method.
3637 // This emits an error 619 / warning 618 if the method is obsolete.
3638 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
3640 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
3642 TypeManager.MethodFlags flags = 0;
3644 if (obsolete != null) {
3645 if (obsolete_error) {
3646 Report.Error (619, loc, "Method `" + member.Name +
3647 "' is obsolete: `" + obsolete + "'");
3648 return TypeManager.MethodFlags.IsObsoleteError;
3650 Report.Warning (618, loc, "Method `" + member.Name +
3651 "' is obsolete: `" + obsolete + "'");
3653 flags |= TypeManager.MethodFlags.IsObsolete;
3656 if (ShouldIgnore (loc))
3657 flags |= TypeManager.MethodFlags.ShouldIgnore;
3662 public bool Define (TypeContainer container)
3664 MethodInfo implementing = null;
3667 EmitContext ec = method.CreateEmitContext (container, null);
3669 if (method.OptAttributes != null)
3670 if (!ApplyAttributes (method.OptAttributes, is_method, ec))
3673 if (member.IsExplicitImpl)
3674 prefix = member.InterfaceType.FullName + ".";
3678 string name = method.MethodName;
3679 string method_name = prefix + name;
3680 Type[] ParameterTypes = method.ParameterTypes;
3682 if (container.Pending != null){
3683 if (member is Indexer)
3684 implementing = container.Pending.IsInterfaceIndexer (
3685 member.InterfaceType, method.ReturnType, ParameterTypes);
3687 implementing = container.Pending.IsInterfaceMethod (
3688 member.InterfaceType, name, method.ReturnType, ParameterTypes);
3690 if (member.InterfaceType != null && implementing == null){
3691 Report.Error (539, method.Location, "'{0}' in explicit interface declaration is not an interface", method_name);
3697 // For implicit implementations, make sure we are public, for
3698 // explicit implementations, make sure we are private.
3700 if (implementing != null){
3702 // Setting null inside this block will trigger a more
3703 // verbose error reporting for missing interface implementations
3705 // The "candidate" function has been flagged already
3706 // but it wont get cleared
3708 if (member.IsExplicitImpl){
3709 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3710 Modifiers.Error_InvalidModifier (method.Location, "public, virtual or abstract");
3711 implementing = null;
3713 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
3714 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
3716 // If this is an interface method implementation,
3717 // check for public accessibility
3719 implementing = null;
3720 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
3721 // We may never be private.
3722 implementing = null;
3723 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
3725 // We may be protected if we're overriding something.
3727 implementing = null;
3732 // Static is not allowed
3734 if ((modifiers & Modifiers.STATIC) != 0){
3735 implementing = null;
3736 Modifiers.Error_InvalidModifier (method.Location, "static");
3741 // If implementing is still valid, set flags
3743 if (implementing != null){
3745 // When implementing interface methods, set NewSlot
3746 // unless, we are overwriting a method.
3748 if (implementing.DeclaringType.IsInterface){
3749 if ((modifiers & Modifiers.OVERRIDE) == 0)
3750 flags |= MethodAttributes.NewSlot;
3753 MethodAttributes.Virtual |
3754 MethodAttributes.HideBySig;
3756 // Set Final unless we're virtual, abstract or already overriding a method.
3757 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
3758 flags |= MethodAttributes.Final;
3760 // Get the method name from the explicit interface.
3761 if (member.InterfaceType != null) {
3762 name = implementing.Name;
3763 method_name = prefix + name;
3766 IsImplementing = true;
3770 // Create the MethodBuilder for the method
3772 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3773 if ((modifiers & Modifiers.STATIC) == 0) {
3774 Report.Error (601, method.Location,
3775 "The DllImport attribute must be specified on " +
3776 "a method marked 'static' and 'extern'.");
3780 builder = dllimport_attribute.DefinePInvokeMethod (
3781 ec, container.TypeBuilder, method_name, flags,
3782 method.ReturnType, ParameterTypes);
3784 builder = container.TypeBuilder.DefineMethod (
3785 method_name, flags, method.CallingConventions,
3786 method.ReturnType, ParameterTypes);
3788 if (builder == null)
3791 if ((modifiers & Modifiers.UNSAFE) != 0)
3792 builder.InitLocals = false;
3794 if (IsImplementing){
3796 // clear the pending implemntation flag
3798 if (member is Indexer) {
3799 container.Pending.ImplementIndexer (
3800 member.InterfaceType, builder, method.ReturnType,
3801 ParameterTypes, true);
3803 container.Pending.ImplementMethod (
3804 member.InterfaceType, name, method.ReturnType,
3805 ParameterTypes, member.IsExplicitImpl);
3807 if (member.IsExplicitImpl)
3808 container.TypeBuilder.DefineMethodOverride (
3809 builder, implementing);
3813 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3814 Report.Error (111, method.Location,
3815 "Class `" + container.Name +
3816 "' already contains a definition with the " +
3817 "same return value and parameter types as the " +
3818 "'get' method of property `" + member.Name + "'");
3822 TypeManager.AddMethod (builder, this);
3830 public void Emit (TypeContainer container, Attributable kind)
3834 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3835 ec = method.CreateEmitContext (container, builder.GetILGenerator ());
3837 ec = method.CreateEmitContext (container, null);
3839 Location loc = method.Location;
3840 Attributes OptAttributes = method.OptAttributes;
3842 if (OptAttributes != null)
3843 OptAttributes.Emit (ec, kind);
3845 if (member is MethodCore)
3846 ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder, loc);
3848 SymbolWriter sw = CodeGen.SymbolWriter;
3849 Block block = method.Block;
3852 // abstract or extern methods have no bodies
3854 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3855 if (block == null) {
3856 if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0) &&
3857 !Location.IsNull (loc) &&
3858 (method.Location.SymbolDocument != null)) {
3859 sw.OpenMethod (container, MethodBuilder, loc, loc);
3867 // abstract or extern methods have no bodies.
3869 if ((modifiers & Modifiers.ABSTRACT) != 0)
3871 500, method.Location, "Abstract method `" +
3872 TypeManager.CSharpSignature (builder) +
3873 "' can not have a body");
3875 if ((modifiers & Modifiers.EXTERN) != 0)
3877 179, method.Location, "External method `" +
3878 TypeManager.CSharpSignature (builder) +
3879 "' can not have a body");
3885 // Methods must have a body unless they're extern or abstract
3887 if (block == null) {
3889 501, method.Location, "Method `" +
3890 TypeManager.CSharpSignature (builder) +
3891 "' must declare a body since it is not marked " +
3892 "abstract or extern");
3897 // Handle destructors specially
3899 // FIXME: This code generates buggy code
3901 if ((sw != null) && !Location.IsNull (loc) &&
3902 !Location.IsNull (block.EndLocation) &&
3903 (loc.SymbolDocument != null)) {
3904 sw.OpenMethod (container, MethodBuilder, loc, block.EndLocation);
3906 if (member is Destructor)
3907 EmitDestructor (ec, block);
3909 ec.EmitTopBlock (block, ParameterInfo, loc);
3913 if (member is Destructor)
3914 EmitDestructor (ec, block);
3916 ec.EmitTopBlock (block, ParameterInfo, loc);
3920 void EmitDestructor (EmitContext ec, Block block)
3922 ILGenerator ig = ec.ig;
3924 Label finish = ig.DefineLabel ();
3926 block.SetDestructor ();
3928 ig.BeginExceptionBlock ();
3929 ec.ReturnLabel = finish;
3930 ec.HasReturnLabel = true;
3931 ec.EmitTopBlock (block, null, method.Location);
3933 // ig.MarkLabel (finish);
3934 ig.BeginFinallyBlock ();
3936 if (ec.ContainerType.BaseType != null) {
3937 Expression member_lookup = Expression.MemberLookup (
3938 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
3939 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, method.Location);
3941 if (member_lookup != null){
3942 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3944 ig.Emit (OpCodes.Ldarg_0);
3945 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3949 ig.EndExceptionBlock ();
3950 //ig.MarkLabel (ec.ReturnLabel);
3951 ig.Emit (OpCodes.Ret);
3955 public class Destructor : Method {
3957 public Destructor (DeclSpace ds, Expression return_type, int mod, string name,
3958 Parameters parameters, Attributes attrs, Location l)
3959 : base (ds, return_type, mod, false, name, parameters, attrs, l)
3964 abstract public class MemberBase : MemberCore {
3965 public Expression Type;
3967 public MethodAttributes flags;
3969 protected readonly int explicit_mod_flags;
3972 // The "short" name of this property / indexer / event. This is the
3973 // name without the explicit interface.
3975 public string ShortName;
3978 // The type of this property / indexer / event
3980 public Type MemberType;
3983 // If true, this is an explicit interface implementation
3985 public bool IsExplicitImpl = false;
3988 // The name of the interface we are explicitly implementing
3990 public string ExplicitInterfaceName = null;
3993 // Whether this is an interface member.
3995 public bool IsInterface;
3998 // If true, the interface type we are explicitly implementing
4000 public Type InterfaceType = null;
4003 // The method we're overriding if this is an override method.
4005 protected MethodInfo parent_method = null;
4006 public MethodInfo ParentMethod {
4008 return parent_method;
4013 // The constructor is only exposed to our children
4015 protected MemberBase (Expression type, int mod, int allowed_mod, int def_mod, string name,
4016 Attributes attrs, Location loc)
4017 : base (name, attrs, loc)
4019 explicit_mod_flags = mod;
4021 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
4024 protected virtual bool CheckBase (TypeContainer container)
4026 if ((container is Struct) || (RootContext.WarningLevel > 3)){
4027 if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
4028 if (container is Struct){
4029 Report.Error (666, Location, "Protected member in struct declaration");
4032 Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
4038 protected void WarningNotHiding (TypeContainer parent)
4042 "The member " + parent.MakeName (Name) + " does not hide an " +
4043 "inherited member. The keyword new is not required");
4047 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
4051 // FIXME: report the old/new permissions?
4054 507, Location, parent.MakeName (Name) +
4055 ": can't change the access modifiers when overriding inherited " +
4056 "member `" + name + "'");
4060 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
4061 // that have been defined.
4063 // `name' is the user visible name for reporting errors (this is used to
4064 // provide the right name regarding method names and properties)
4066 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
4067 MethodInfo mb, string name)
4071 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4072 if (!(mb.IsAbstract || mb.IsVirtual)){
4074 506, Location, parent.MakeName (Name) +
4075 ": cannot override inherited member `" +
4076 name + "' because it is not " +
4077 "virtual, abstract or override");
4081 // Now we check that the overriden method is not final
4084 // This happens when implementing interface methods.
4085 if (mb.IsHideBySig && mb.IsVirtual) {
4087 506, Location, parent.MakeName (Name) +
4088 ": cannot override inherited member `" +
4089 name + "' because it is not " +
4090 "virtual, abstract or override");
4092 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
4093 "override inherited member `" + name +
4094 "' because it is sealed.");
4098 // Check that the permissions are not being changed
4100 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
4101 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
4104 // special case for "protected internal"
4107 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4109 // when overriding protected internal, the method can be declared
4110 // protected internal only within the same assembly
4113 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4114 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
4116 // assemblies differ - report an error
4119 Error_CannotChangeAccessModifiers (parent, mb, name);
4121 } else if (thisp != parentp) {
4123 // same assembly, but other attributes differ - report an error
4126 Error_CannotChangeAccessModifiers (parent, mb, name);
4129 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
4131 // if it's not "protected internal", it must be "protected"
4134 Error_CannotChangeAccessModifiers (parent, mb, name);
4136 } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
4138 // protected within the same assembly - an error
4140 Error_CannotChangeAccessModifiers (parent, mb, name);
4142 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
4143 (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
4145 // protected ok, but other attributes differ - report an error
4147 Error_CannotChangeAccessModifiers (parent, mb, name);
4151 if (thisp != parentp){
4152 Error_CannotChangeAccessModifiers (parent, mb, name);
4158 if (mb.IsVirtual || mb.IsAbstract){
4159 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4160 if (Name != "Finalize"){
4162 114, 2, Location, parent.MakeName (Name) +
4163 " hides inherited member `" + name +
4164 "'. To make the current member override that " +
4165 "implementation, add the override keyword, " +
4166 "otherwise use the new keyword");
4167 ModFlags |= Modifiers.NEW;
4171 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4172 if (Name != "Finalize"){
4174 108, 1, Location, "The keyword new is required on " +
4175 parent.MakeName (Name) + " because it hides " +
4176 "inherited member `" + name + "'");
4177 ModFlags |= Modifiers.NEW;
4185 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
4189 foreach (Type partype in parameters){
4190 if (partype == TypeManager.void_type) {
4192 1547, Location, "Keyword 'void' cannot " +
4193 "be used in this context");
4197 if (partype.IsPointer){
4200 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
4204 if (ds.AsAccessible (partype, ModFlags))
4207 if (this is Indexer)
4208 Report.Error (55, Location,
4209 "Inconsistent accessibility: parameter type `" +
4210 TypeManager.CSharpName (partype) + "' is less " +
4211 "accessible than indexer `" + Name + "'");
4212 else if ((this is Method) && ((Method) this).IsOperator)
4213 Report.Error (57, Location,
4214 "Inconsistent accessibility: parameter type `" +
4215 TypeManager.CSharpName (partype) + "' is less " +
4216 "accessible than operator `" + Name + "'");
4218 Report.Error (51, Location,
4219 "Inconsistent accessibility: parameter type `" +
4220 TypeManager.CSharpName (partype) + "' is less " +
4221 "accessible than method `" + Name + "'");
4228 protected virtual bool DoDefine (TypeContainer container)
4234 ModFlags = Modifiers.PUBLIC |
4235 Modifiers.ABSTRACT |
4236 Modifiers.VIRTUAL | (ModFlags & Modifiers.UNSAFE);
4238 flags = MethodAttributes.Public |
4239 MethodAttributes.Abstract |
4240 MethodAttributes.HideBySig |
4241 MethodAttributes.NewSlot |
4242 MethodAttributes.Virtual;
4244 if (!container.MethodModifiersValid (ModFlags, Name, Location))
4247 flags = Modifiers.MethodAttr (ModFlags);
4250 // Lookup Type, verify validity
4251 MemberType = container.ResolveType (Type, false, Location);
4252 if (MemberType == null)
4255 if ((container.ModFlags & Modifiers.SEALED) != 0){
4256 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
4257 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
4262 // verify accessibility
4263 if (!container.AsAccessible (MemberType, ModFlags)) {
4264 if (this is Property)
4265 Report.Error (53, Location,
4266 "Inconsistent accessibility: property type `" +
4267 TypeManager.CSharpName (MemberType) + "' is less " +
4268 "accessible than property `" + Name + "'");
4269 else if (this is Indexer)
4270 Report.Error (54, Location,
4271 "Inconsistent accessibility: indexer return type `" +
4272 TypeManager.CSharpName (MemberType) + "' is less " +
4273 "accessible than indexer `" + Name + "'");
4274 else if (this is Method) {
4275 if (((Method) this).IsOperator)
4276 Report.Error (56, Location,
4277 "Inconsistent accessibility: return type `" +
4278 TypeManager.CSharpName (MemberType) + "' is less " +
4279 "accessible than operator `" + Name + "'");
4281 Report.Error (50, Location,
4282 "Inconsistent accessibility: return type `" +
4283 TypeManager.CSharpName (MemberType) + "' is less " +
4284 "accessible than method `" + Name + "'");
4286 Report.Error (52, Location,
4287 "Inconsistent accessibility: field type `" +
4288 TypeManager.CSharpName (MemberType) + "' is less " +
4289 "accessible than field `" + Name + "'");
4293 if (MemberType.IsPointer && !UnsafeOK (container))
4297 // Check for explicit interface implementation
4299 if ((ExplicitInterfaceName == null) && (Name.IndexOf ('.') != -1)){
4300 int pos = Name.LastIndexOf ('.');
4302 ExplicitInterfaceName = Name.Substring (0, pos);
4303 ShortName = Name.Substring (pos + 1);
4307 if (ExplicitInterfaceName != null) {
4308 InterfaceType = RootContext.LookupType (
4309 container, ExplicitInterfaceName, false, Location);
4310 if (InterfaceType == null)
4313 if (InterfaceType.IsClass) {
4314 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
4318 // Compute the full name that we need to export.
4319 Name = InterfaceType.FullName + "." + ShortName;
4321 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
4324 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
4326 IsExplicitImpl = true;
4328 IsExplicitImpl = false;
4333 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
4335 return IsIdentifierAndParamClsCompliant (ds, Name, null, null);
4338 protected override bool VerifyClsCompliance(DeclSpace ds)
4340 if (base.VerifyClsCompliance (ds)) {
4344 if (IsInterface && HasClsCompliantAttribute && ds.IsClsCompliaceRequired (ds)) {
4345 Report.Error_T (3010, Location, GetSignatureForError ());
4354 // Fields and Events both generate FieldBuilders, we use this to share
4355 // their common bits. This is also used to flag usage of the field
4357 abstract public class FieldBase : MemberBase {
4358 public FieldBuilder FieldBuilder;
4359 public Status status;
4362 public enum Status : byte { ASSIGNED = 1, USED = 2 }
4364 static string[] attribute_targets = new string [] { "field" };
4367 // The constructor is only exposed to our children
4369 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
4370 object init, Attributes attrs, Location loc)
4371 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
4376 public override AttributeTargets AttributeTargets {
4378 return AttributeTargets.Field;
4382 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4384 if (a.Type == TypeManager.marshal_as_attr_type) {
4385 UnmanagedMarshal marshal = a.GetMarshal ();
4386 if (marshal != null) {
4387 FieldBuilder.SetMarshal (marshal);
4390 Report.Warning_T (-24, a.Location);
4395 FieldBuilder.SetCustomAttribute (cb);
4399 // Whether this field has an initializer.
4401 public bool HasInitializer {
4403 return init != null;
4407 protected readonly Object init;
4409 Expression init_expr;
4410 bool init_expr_initialized = false;
4413 // Resolves and returns the field initializer.
4415 public Expression GetInitializerExpression (EmitContext ec)
4417 if (init_expr_initialized)
4421 if (init is Expression)
4422 e = (Expression) init;
4424 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
4426 ec.IsFieldInitializer = true;
4427 e = e.DoResolve (ec);
4428 ec.IsFieldInitializer = false;
4431 init_expr_initialized = true;
4436 protected override bool DoDefine (TypeContainer container)
4438 if (!base.DoDefine (container))
4441 if (MemberType == TypeManager.void_type) {
4442 Report.Error (1547, Location,
4443 "Keyword 'void' cannot be used in this context");
4450 public override string GetSignatureForError ()
4452 return TypeManager.GetFullNameSignature (FieldBuilder);
4455 protected override string[] ValidAttributeTargets {
4457 return attribute_targets;
4461 protected override bool VerifyClsCompliance (DeclSpace ds)
4463 if (!base.VerifyClsCompliance (ds))
4466 if (FieldBuilder == null) {
4470 if (!AttributeTester.IsClsCompliant (FieldBuilder.FieldType)) {
4471 Report.Error_T (3003, Location, GetSignatureForError ());
4477 public void SetAssigned ()
4479 status |= Status.ASSIGNED;
4484 // The Field class is used to represents class/struct fields during parsing.
4486 public class Field : FieldBase {
4488 // Modifiers allowed in a class declaration
4490 const int AllowedModifiers =
4493 Modifiers.PROTECTED |
4494 Modifiers.INTERNAL |
4497 Modifiers.VOLATILE |
4501 public Field (Expression type, int mod, string name, Object expr_or_array_init,
4502 Attributes attrs, Location loc)
4503 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
4507 public override bool Define (TypeContainer container)
4509 Type t = container.ResolveType (Type, false, Location);
4514 CheckBase (container);
4516 if (!container.AsAccessible (t, ModFlags)) {
4517 Report.Error (52, Location,
4518 "Inconsistent accessibility: field type `" +
4519 TypeManager.CSharpName (t) + "' is less " +
4520 "accessible than field `" + Name + "'");
4524 if (t.IsPointer && !UnsafeOK (container))
4527 if (RootContext.WarningLevel > 1){
4528 Type ptype = container.TypeBuilder.BaseType;
4530 // ptype is only null for System.Object while compiling corlib.
4532 TypeContainer.FindMembers (
4533 ptype, MemberTypes.Method,
4534 BindingFlags.Public |
4535 BindingFlags.Static | BindingFlags.Instance,
4536 System.Type.FilterName, Name);
4540 if ((ModFlags & Modifiers.VOLATILE) != 0){
4544 if (TypeManager.IsEnumType (vt))
4545 vt = TypeManager.EnumToUnderlying (t);
4547 if (!((vt == TypeManager.bool_type) ||
4548 (vt == TypeManager.sbyte_type) ||
4549 (vt == TypeManager.byte_type) ||
4550 (vt == TypeManager.short_type) ||
4551 (vt == TypeManager.ushort_type) ||
4552 (vt == TypeManager.int32_type) ||
4553 (vt == TypeManager.uint32_type) ||
4554 (vt == TypeManager.char_type) ||
4555 (vt == TypeManager.float_type) ||
4556 (!vt.IsValueType))){
4558 677, Location, container.MakeName (Name) +
4559 " A volatile field can not be of type `" +
4560 TypeManager.CSharpName (vt) + "'");
4565 if ((ModFlags & Modifiers.READONLY) != 0){
4568 "A field can not be both volatile and readonly");
4573 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
4575 if (container is Struct &&
4576 ((fa & FieldAttributes.Static) == 0) &&
4577 t == container.TypeBuilder &&
4578 !TypeManager.IsBuiltinType (t)){
4579 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name +
4580 "' causes a cycle in the structure layout");
4585 FieldBuilder = container.TypeBuilder.DefineField (
4586 Name, t, Modifiers.FieldAttr (ModFlags));
4588 TypeManager.RegisterFieldBase (FieldBuilder, this);
4590 catch (ArgumentException) {
4591 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
4598 public override void Emit (TypeContainer tc)
4600 if (OptAttributes != null) {
4601 EmitContext ec = new EmitContext (tc, Location, null, FieldBuilder.FieldType, ModFlags);
4602 OptAttributes.Emit (ec, this);
4610 // `set' and `get' accessors are represented with an Accessor.
4612 public class Accessor {
4614 // Null if the accessor is empty, or a Block if not
4617 public Attributes Attributes;
4619 public Accessor (Block b, Attributes attrs)
4627 // Properties and Indexers both generate PropertyBuilders, we use this to share
4628 // their common bits.
4630 abstract public class PropertyBase : MethodCore {
4632 public class GetMethod: PropertyMethod
4634 static string[] attribute_targets = new string [] { "method", "return" };
4636 public GetMethod (MethodCore method, Accessor accessor):
4637 base (method, accessor)
4641 public override MethodBuilder Define(TypeContainer container)
4643 method_data = new MethodData (method, method.ParameterInfo, method.ModFlags, method.flags, false, this);
4645 if (!method_data.Define (container))
4648 return method_data.MethodBuilder;
4651 public override string MethodName {
4653 return "get_" + method.ShortName;
4657 public override Type ReturnType {
4659 return method.MemberType;
4663 protected override string[] ValidAttributeTargets {
4665 return attribute_targets;
4670 public class SetMethod: PropertyMethod {
4672 static string[] attribute_targets = new string [] { "method", "param", "return" };
4673 ImplicitParameter param_attr;
4675 public SetMethod (MethodCore method, Accessor accessor):
4676 base (method, accessor)
4680 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
4682 if (a.Target == "param") {
4683 if (param_attr == null)
4684 param_attr = new ImplicitParameter (method_data.MethodBuilder);
4686 param_attr.ApplyAttributeBuilder (a, cb);
4690 base.ApplyAttributeBuilder (a, cb);
4693 protected virtual InternalParameters GetParameterInfo (TypeContainer container)
4695 Parameter [] parms = new Parameter [1];
4696 parms [0] = new Parameter (method.Type, "value", Parameter.Modifier.NONE, null);
4697 return new InternalParameters (
4698 container, new Parameters (parms, null, method.Location));
4701 public override MethodBuilder Define(TypeContainer container)
4703 method_data = new MethodData (method, GetParameterInfo (container), method.ModFlags, method.flags, false, this);
4705 if (!method_data.Define (container))
4708 return method_data.MethodBuilder;
4711 public override string MethodName {
4713 return "set_" + method.ShortName;
4717 public override Type[] ParameterTypes {
4719 return new Type[] { method.MemberType };
4723 public override Type ReturnType {
4725 return TypeManager.void_type;
4729 protected override string[] ValidAttributeTargets {
4731 return attribute_targets;
4737 static string[] attribute_targets = new string [] { "property" };
4739 public abstract class PropertyMethod: Attributable, IMethodData
4741 protected readonly MethodCore method;
4742 protected MethodData method_data;
4745 ReturnParameter return_attributes;
4747 public PropertyMethod (MethodCore method, Accessor accessor):
4748 base (accessor.Attributes)
4750 this.method = method;
4751 this.block = accessor.Block;
4754 public override AttributeTargets AttributeTargets {
4756 return AttributeTargets.Method | AttributeTargets.ReturnValue;
4761 public override bool IsClsCompliaceRequired(DeclSpace ds)
4763 return method.IsClsCompliaceRequired (ds);
4766 public InternalParameters ParameterInfo
4769 return method_data.ParameterInfo;
4773 #region IMethodData Members
4775 public Block Block {
4781 public CallingConventions CallingConventions {
4783 return CallingConventions.Standard;
4787 public abstract MethodBuilder Define (TypeContainer container);
4789 public void Emit (TypeContainer container)
4791 method_data.Emit (container, this);
4795 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
4797 if (a.Target == "return") {
4798 if (return_attributes == null)
4799 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
4801 return_attributes.ApplyAttributeBuilder (a, cb);
4805 method_data.MethodBuilder.SetCustomAttribute (cb);
4808 public virtual Type[] ParameterTypes {
4810 return TypeManager.NoTypes;
4814 public abstract Type ReturnType { get; }
4816 public Location Location {
4818 return method.Location;
4822 public abstract string MethodName { get; }
4824 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
4826 return new EmitContext (tc, method.ds, method.Location, ig, ReturnType, method.ModFlags, false);
4833 public PropertyMethod Get, Set;
4834 public PropertyBuilder PropertyBuilder;
4835 public MethodBuilder GetBuilder, SetBuilder;
4837 protected EmitContext ec;
4839 public PropertyBase (DeclSpace ds, Expression type, int mod_flags,
4840 int allowed_mod, bool is_iface, string name,
4841 Parameters parameters, Attributes attrs,
4843 : base (ds, type, mod_flags, allowed_mod, is_iface, name,
4844 attrs, parameters, loc)
4848 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4850 PropertyBuilder.SetCustomAttribute (cb);
4853 public override AttributeTargets AttributeTargets {
4855 return AttributeTargets.Property;
4859 protected override bool DoDefine (TypeContainer container)
4861 if (!base.DoDefine (container))
4864 ec = new EmitContext (container, Location, null, MemberType, ModFlags);
4869 public override string GetSignatureForError()
4871 return TypeManager.CSharpSignature (PropertyBuilder, false);
4874 protected virtual string RealMethodName {
4880 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
4882 if (!IsIdentifierAndParamClsCompliant (ds, RealMethodName, null, null))
4885 if (Get != null && !IsIdentifierAndParamClsCompliant (ds, "get_" + RealMethodName, null, null))
4888 if (Set != null && !IsIdentifierAndParamClsCompliant (ds, "set_" + RealMethodName, null, null))
4896 // Checks our base implementation if any
4898 protected override bool CheckBase (TypeContainer container)
4900 base.CheckBase (container);
4902 // Check whether arguments were correct.
4903 if (!DoDefineParameters ())
4910 // Check in our class for dups
4912 ArrayList ar = container.Properties;
4914 int arLen = ar.Count;
4916 for (int i = 0; i < arLen; i++) {
4917 Property m = (Property) ar [i];
4918 if (IsDuplicateImplementation (container, m))
4927 MethodSignature ms, base_ms;
4928 if (this is Indexer) {
4929 string name, base_name;
4931 report_name = "this";
4932 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
4933 ms = new MethodSignature (name, null, ParameterTypes);
4934 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
4935 base_ms = new MethodSignature (base_name, null, ParameterTypes);
4938 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
4942 // Verify if the parent has a type with the same name, and then
4943 // check whether we have to create a new slot for it or not.
4945 Type ptype = container.TypeBuilder.BaseType;
4947 // ptype is only null for System.Object while compiling corlib.
4948 if (ptype == null) {
4949 if ((ModFlags & Modifiers.NEW) != 0)
4950 WarningNotHiding (container);
4955 MemberInfo parent_member = null;
4958 // Explicit implementations do not have `parent' methods, however,
4959 // the member cache stores them there. Without this check, we get
4960 // an incorrect warning in corlib.
4962 if (! IsExplicitImpl) {
4963 parent_member = ((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
4964 container.TypeBuilder, Name, ParameterTypes, true);
4967 if (parent_member is PropertyInfo) {
4968 PropertyInfo parent_property = (PropertyInfo)parent_member;
4970 string name = parent_property.DeclaringType.Name + "." +
4971 parent_property.Name;
4973 MethodInfo get, set, parent_method;
4974 get = parent_property.GetGetMethod (true);
4975 set = parent_property.GetSetMethod (true);
4978 parent_method = get;
4979 else if (set != null)
4980 parent_method = set;
4982 throw new Exception ("Internal error!");
4984 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
4987 if ((ModFlags & Modifiers.NEW) == 0) {
4988 Type parent_type = TypeManager.TypeToCoreType (
4989 parent_property.PropertyType);
4991 if (parent_type != MemberType) {
4993 508, Location, container.MakeName (Name) + ": cannot " +
4994 "change return type when overriding " +
4995 "inherited member " + name);
4999 } else if (parent_member == null){
5000 if ((ModFlags & Modifiers.NEW) != 0)
5001 WarningNotHiding (container);
5003 if ((ModFlags & Modifiers.OVERRIDE) != 0){
5004 if (this is Indexer)
5005 Report.Error (115, Location,
5006 container.MakeName (Name) +
5007 " no suitable indexers found to override");
5009 Report.Error (115, Location,
5010 container.MakeName (Name) +
5011 " no suitable properties found to override");
5018 public override void Emit (TypeContainer tc)
5021 // The PropertyBuilder can be null for explicit implementations, in that
5022 // case, we do not actually emit the ".property", so there is nowhere to
5023 // put the attribute
5025 if (PropertyBuilder != null && OptAttributes != null)
5026 OptAttributes.Emit (ec, this);
5037 protected override string[] ValidAttributeTargets {
5039 return attribute_targets;
5044 public class Property : PropertyBase, IIteratorContainer {
5045 const int AllowedModifiers =
5048 Modifiers.PROTECTED |
5049 Modifiers.INTERNAL |
5053 Modifiers.OVERRIDE |
5054 Modifiers.ABSTRACT |
5057 Modifiers.METHOD_YIELDS |
5060 const int AllowedInterfaceModifiers =
5063 public Property (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
5064 string name, Attributes attrs, Accessor get_block,
5065 Accessor set_block, Location loc)
5066 : base (ds, type, mod_flags,
5067 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5068 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
5071 if (get_block != null)
5072 Get = new GetMethod (this, get_block);
5074 if (set_block != null)
5075 Set = new SetMethod (this, set_block);
5078 public override bool Define (TypeContainer container)
5080 if (!DoDefine (container))
5083 if (!CheckBase (container))
5086 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
5090 GetBuilder = Get.Define (container);
5091 if (GetBuilder == null)
5095 // Setup iterator if we are one
5097 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
5098 IteratorHandler ih = new IteratorHandler (
5099 "get", container, MemberType,
5100 TypeManager.NoTypes, Get.ParameterInfo, ModFlags, Location);
5102 Block new_block = ih.Setup (block);
5103 if (new_block == null)
5110 SetBuilder = Set.Define (container);
5111 if (SetBuilder == null)
5114 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
5117 // FIXME - PropertyAttributes.HasDefault ?
5119 PropertyAttributes prop_attr = PropertyAttributes.None;
5121 prop_attr |= PropertyAttributes.RTSpecialName |
5122 PropertyAttributes.SpecialName;
5124 if (!IsExplicitImpl){
5125 PropertyBuilder = container.TypeBuilder.DefineProperty (
5126 Name, prop_attr, MemberType, null);
5129 PropertyBuilder.SetGetMethod (GetBuilder);
5132 PropertyBuilder.SetSetMethod (SetBuilder);
5135 // HACK for the reasons exposed above
5137 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
5140 "Class `" + container.Name +
5141 "' already contains a definition for the property `" +
5149 public void SetYields ()
5151 ModFlags |= Modifiers.METHOD_YIELDS;
5156 /// Gigantic workaround for lameness in SRE follows :
5157 /// This class derives from EventInfo and attempts to basically
5158 /// wrap around the EventBuilder so that FindMembers can quickly
5159 /// return this in it search for members
5161 public class MyEventBuilder : EventInfo {
5164 // We use this to "point" to our Builder which is
5165 // not really a MemberInfo
5167 EventBuilder MyBuilder;
5170 // We "catch" and wrap these methods
5172 MethodInfo raise, remove, add;
5174 EventAttributes attributes;
5175 Type declaring_type, reflected_type, event_type;
5180 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
5182 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
5184 // And now store the values in our own fields.
5186 declaring_type = type_builder;
5188 reflected_type = type_builder;
5190 attributes = event_attr;
5193 this.event_type = event_type;
5197 // Methods that you have to override. Note that you only need
5198 // to "implement" the variants that take the argument (those are
5199 // the "abstract" methods, the others (GetAddMethod()) are
5202 public override MethodInfo GetAddMethod (bool nonPublic)
5207 public override MethodInfo GetRemoveMethod (bool nonPublic)
5212 public override MethodInfo GetRaiseMethod (bool nonPublic)
5218 // These methods make "MyEventInfo" look like a Builder
5220 public void SetRaiseMethod (MethodBuilder raiseMethod)
5222 raise = raiseMethod;
5223 MyBuilder.SetRaiseMethod (raiseMethod);
5226 public void SetRemoveOnMethod (MethodBuilder removeMethod)
5228 remove = removeMethod;
5229 MyBuilder.SetRemoveOnMethod (removeMethod);
5232 public void SetAddOnMethod (MethodBuilder addMethod)
5235 MyBuilder.SetAddOnMethod (addMethod);
5238 public void SetCustomAttribute (CustomAttributeBuilder cb)
5240 MyBuilder.SetCustomAttribute (cb);
5243 public override object [] GetCustomAttributes (bool inherit)
5245 // FIXME : There's nothing which can be seemingly done here because
5246 // we have no way of getting at the custom attribute objects of the
5251 public override object [] GetCustomAttributes (Type t, bool inherit)
5253 // FIXME : Same here !
5257 public override bool IsDefined (Type t, bool b)
5262 public override EventAttributes Attributes {
5268 public override string Name {
5274 public override Type DeclaringType {
5276 return declaring_type;
5280 public override Type ReflectedType {
5282 return reflected_type;
5286 public Type EventType {
5292 public void SetUsed ()
5294 if (my_event != null)
5295 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
5300 /// For case when event is declared like property (with add and remove accessors).
5302 public class EventProperty: Event {
5304 static string[] attribute_targets = new string [] { "event", "property" };
5306 public EventProperty (DeclSpace ds, Expression type, int mod_flags, bool is_iface, string name,
5307 Object init, Attributes attrs, Accessor add, Accessor remove, Location loc)
5308 : base (ds, type, mod_flags, is_iface, name, init, attrs, loc)
5310 Add = new AddDelegateMethod (this, add);
5311 Remove = new RemoveDelegateMethod (this, remove);
5314 protected override string[] ValidAttributeTargets {
5316 return attribute_targets;
5322 /// Event is declared like field.
5324 public class EventField: Event {
5326 static string[] attribute_targets = new string [] { "method", "field", "event" };
5328 public EventField (DeclSpace ds, Expression type, int mod_flags, bool is_iface, string name,
5329 Object init, Attributes attrs, Location loc)
5330 : base (ds, type, mod_flags, is_iface, name, init, attrs, loc)
5332 Add = new AddDelegateMethod (this);
5333 Remove = new RemoveDelegateMethod (this);
5336 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5338 if (a.Target == "field") {
5339 FieldBuilder.SetCustomAttribute (cb);
5343 if (a.Target == "method") {
5344 AddBuilder.SetCustomAttribute (cb);
5345 RemoveBuilder.SetCustomAttribute (cb);
5349 base.ApplyAttributeBuilder (a, cb);
5352 protected override string[] ValidAttributeTargets {
5354 return attribute_targets;
5359 public abstract class Event : FieldBase {
5361 protected sealed class AddDelegateMethod: DelegateMethod
5363 public AddDelegateMethod (Event method):
5368 public AddDelegateMethod (Event method, Accessor accessor):
5369 base (method, accessor)
5373 public override string MethodName {
5375 return "add_" + method.ShortName;
5379 protected override MethodInfo DelegateMethodInfo {
5381 return TypeManager.delegate_combine_delegate_delegate;
5387 protected sealed class RemoveDelegateMethod: DelegateMethod
5389 public RemoveDelegateMethod (Event method):
5394 public RemoveDelegateMethod (Event method, Accessor accessor):
5395 base (method, accessor)
5399 public override string MethodName {
5401 return "remove_" + method.ShortName;
5405 protected override MethodInfo DelegateMethodInfo {
5407 return TypeManager.delegate_remove_delegate_delegate;
5413 public abstract class DelegateMethod: Attributable, IMethodData
5415 protected readonly Event method;
5416 protected MethodData method_data;
5418 ReturnParameter return_attributes;
5419 ImplicitParameter param_attr;
5421 static string[] attribute_targets = new string [] { "method", "param", "return" };
5423 public DelegateMethod (Event method):
5426 this.method = method;
5429 public DelegateMethod (Event method, Accessor accessor):
5430 base (accessor.Attributes)
5432 this.method = method;
5433 this.block = accessor.Block;
5436 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5438 if (a.Target == "return") {
5439 if (return_attributes == null)
5440 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
5442 return_attributes.ApplyAttributeBuilder (a, cb);
5446 if (a.Target == "param") {
5447 if (param_attr == null)
5448 param_attr = new ImplicitParameter (method_data.MethodBuilder);
5450 param_attr.ApplyAttributeBuilder (a, cb);
5454 method_data.MethodBuilder.SetCustomAttribute (cb);
5457 public override AttributeTargets AttributeTargets {
5459 return AttributeTargets.Method;
5463 public override bool IsClsCompliaceRequired(DeclSpace ds)
5465 return method.IsClsCompliaceRequired (ds);
5468 public MethodBuilder Define (TypeContainer container, InternalParameters ip)
5470 method_data = new MethodData (method, ip, method.ModFlags,
5471 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, false, this);
5473 if (!method_data.Define (container))
5476 MethodBuilder mb = method_data.MethodBuilder;
5477 mb.DefineParameter (1, ParameterAttributes.None, "value");
5481 #region IMethodData Members
5483 public Block Block {
5489 public CallingConventions CallingConventions {
5491 return CallingConventions.Standard;
5495 public void Emit (TypeContainer tc)
5497 if (block != null) {
5498 method_data.Emit (tc, this);
5503 ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
5504 EmitContext ec = CreateEmitContext (tc, ig);
5505 FieldInfo field_info = (FieldInfo)method.FieldBuilder;
5507 if ((method.ModFlags & Modifiers.STATIC) != 0) {
5508 ig.Emit (OpCodes.Ldsfld, field_info);
5509 ig.Emit (OpCodes.Ldarg_0);
5510 ig.Emit (OpCodes.Call, DelegateMethodInfo);
5511 ig.Emit (OpCodes.Castclass, method.MemberType);
5512 ig.Emit (OpCodes.Stsfld, field_info);
5514 ig.Emit (OpCodes.Ldarg_0);
5515 ig.Emit (OpCodes.Ldarg_0);
5516 ig.Emit (OpCodes.Ldfld, field_info);
5517 ig.Emit (OpCodes.Ldarg_1);
5518 ig.Emit (OpCodes.Call, DelegateMethodInfo);
5519 ig.Emit (OpCodes.Castclass, method.MemberType);
5520 ig.Emit (OpCodes.Stfld, field_info);
5522 ig.Emit (OpCodes.Ret);
5525 protected abstract MethodInfo DelegateMethodInfo { get; }
5527 public Type[] ParameterTypes {
5529 return new Type[] { method.MemberType };
5533 public Type ReturnType {
5535 return TypeManager.void_type;
5539 public Location Location {
5541 return method.Location;
5545 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
5547 return new EmitContext (tc, method.ds, Location, ig, ReturnType, method.ModFlags, false);
5550 public abstract string MethodName { get; }
5554 protected override string[] ValidAttributeTargets {
5556 return attribute_targets;
5562 const int AllowedModifiers =
5565 Modifiers.PROTECTED |
5566 Modifiers.INTERNAL |
5571 Modifiers.OVERRIDE |
5575 const int AllowedInterfaceModifiers =
5578 protected DelegateMethod Add, Remove;
5579 public MyEventBuilder EventBuilder;
5580 public MethodBuilder AddBuilder, RemoveBuilder;
5581 public DeclSpace ds;
5583 public Event (DeclSpace ds, Expression type, int mod_flags, bool is_iface, string name,
5584 Object init, Attributes attrs, Location loc)
5585 : base (type, mod_flags, is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5586 name, init, attrs, loc)
5588 IsInterface = is_iface;
5592 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5594 EventBuilder.SetCustomAttribute (cb);
5597 public override AttributeTargets AttributeTargets {
5599 return AttributeTargets.Event;
5603 public override bool Define (TypeContainer container)
5605 EventAttributes e_attr;
5607 e_attr = EventAttributes.None;
5609 e_attr = EventAttributes.RTSpecialName |
5610 EventAttributes.SpecialName;
5612 if (!DoDefine (container))
5615 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
5616 Report.Error (74, Location, "'" + container.Name + "." + Name +
5617 "': abstract event can not have an initializer");
5621 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
5622 Report.Error (66, Location, "'" + container.Name + "." + Name +
5623 "' : event must be of a delegate type");
5627 Parameter [] parms = new Parameter [1];
5628 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
5629 InternalParameters ip = new InternalParameters (
5630 container, new Parameters (parms, null, Location));
5632 if (!CheckBase (container))
5636 // Now define the accessors
5639 AddBuilder = Add.Define (container, ip);
5640 if (AddBuilder == null)
5643 RemoveBuilder = Remove.Define (container, ip);
5644 if (RemoveBuilder == null)
5647 if (!IsExplicitImpl){
5648 EventBuilder = new MyEventBuilder (this,
5649 container.TypeBuilder, Name, e_attr, MemberType);
5651 if (Add.Block == null && Remove.Block == null &&
5653 FieldBuilder = container.TypeBuilder.DefineField (
5655 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
5656 TypeManager.RegisterPrivateFieldOfEvent (
5657 (EventInfo) EventBuilder, FieldBuilder);
5658 TypeManager.RegisterFieldBase (FieldBuilder, this);
5661 EventBuilder.SetAddOnMethod (AddBuilder);
5662 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
5664 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
5665 Report.Error (111, Location,
5666 "Class `" + container.Name +
5667 "' already contains a definition for the event `" +
5676 public override void Emit (TypeContainer tc)
5678 if (OptAttributes != null) {
5679 EmitContext ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
5680 OptAttributes.Emit (ec, this);
5693 // FIXME: This does not handle:
5695 // int INTERFACENAME [ args ]
5700 // int this [ args ]
5702 public class Indexer : PropertyBase {
5704 class GetIndexerMethod: GetMethod
5706 public GetIndexerMethod (MethodCore method, Accessor accessor):
5707 base (method, accessor)
5711 public override Type[] ParameterTypes {
5713 return method.ParameterTypes;
5718 class SetIndexerMethod: SetMethod
5720 readonly Parameters parameters;
5722 public SetIndexerMethod (MethodCore method, Parameters parameters, Accessor accessor):
5723 base (method, accessor)
5725 this.parameters = parameters;
5728 public override Type[] ParameterTypes {
5730 int top = method.ParameterTypes.Length;
5731 Type [] set_pars = new Type [top + 1];
5732 method.ParameterTypes.CopyTo (set_pars, 0);
5733 set_pars [top] = method.MemberType;
5738 protected override InternalParameters GetParameterInfo (TypeContainer container)
5740 Parameter [] fixed_parms = parameters.FixedParameters;
5742 if (fixed_parms == null){
5743 throw new Exception ("We currently do not support only array arguments in an indexer at: " + method.Location);
5744 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5745 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5747 // Here is the problem: the `value' parameter has
5748 // to come *after* the array parameter in the declaration
5750 // X (object [] x, Type value)
5753 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5754 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5758 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
5760 fixed_parms.CopyTo (tmp, 0);
5761 tmp [fixed_parms.Length] = new Parameter (
5762 method.Type, "value", Parameter.Modifier.NONE, null);
5764 Parameters set_formal_params = new Parameters (tmp, null, method.Location);
5766 return new InternalParameters (container, set_formal_params);
5772 const int AllowedModifiers =
5775 Modifiers.PROTECTED |
5776 Modifiers.INTERNAL |
5780 Modifiers.OVERRIDE |
5785 const int AllowedInterfaceModifiers =
5788 public string IndexerName;
5789 public string InterfaceIndexerName;
5792 // Are we implementing an interface ?
5794 public Indexer (DeclSpace ds, Expression type, string int_type, int mod_flags,
5795 bool is_iface, Parameters parameters, Attributes attrs,
5796 Accessor get_block, Accessor set_block, Location loc)
5797 : base (ds, type, mod_flags,
5798 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5799 is_iface, "", parameters, attrs, loc)
5801 ExplicitInterfaceName = int_type;
5803 if (get_block != null)
5804 Get = new GetIndexerMethod (this, get_block);
5806 if (set_block != null)
5807 Set = new SetIndexerMethod (this, parameters, set_block);
5810 public override bool Define (TypeContainer container)
5812 PropertyAttributes prop_attr =
5813 PropertyAttributes.RTSpecialName |
5814 PropertyAttributes.SpecialName;
5816 if (!DoDefine (container))
5819 if (OptAttributes != null)
5820 IndexerName = OptAttributes.ScanForIndexerName (ec);
5822 if (IndexerName == null)
5823 IndexerName = "Item";
5825 if (! Tokenizer.IsValidIdentifier (IndexerName)) {
5826 Report.Error (633, Location, "The IndexerName specified is an invalid identifier");
5830 if (IsExplicitImpl) {
5831 Report.Error (592, Location,
5832 "Attribute 'IndexerName' is not valid on explicit implementations.");
5837 ShortName = IndexerName;
5838 if (IsExplicitImpl) {
5839 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
5840 Name = InterfaceType.FullName + "." + IndexerName;
5842 InterfaceIndexerName = IndexerName;
5846 if (!CheckNameCollision (container))
5849 if (!CheckBase (container))
5852 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
5854 GetBuilder = Get.Define (container);
5855 if (GetBuilder == null)
5860 SetBuilder = Set.Define (container);
5861 if (SetBuilder == null)
5866 // Now name the parameters
5868 Parameter [] p = Parameters.FixedParameters;
5872 for (i = 0; i < p.Length; ++i) {
5874 GetBuilder.DefineParameter (
5875 i + 1, p [i].Attributes, p [i].Name);
5878 SetBuilder.DefineParameter (
5879 i + 1, p [i].Attributes, p [i].Name);
5883 SetBuilder.DefineParameter (
5884 i + 1, ParameterAttributes.None, "value");
5886 if (i != ParameterTypes.Length) {
5887 Parameter array_param = Parameters.ArrayParameter;
5889 SetBuilder.DefineParameter (
5890 i + 1, array_param.Attributes, array_param.Name);
5895 // Define the PropertyBuilder if one of the following conditions are met:
5896 // a) we're not implementing an interface indexer.
5897 // b) the indexer has a different IndexerName and this is no
5898 // explicit interface implementation.
5900 if (!IsExplicitImpl) {
5901 PropertyBuilder = container.TypeBuilder.DefineProperty (
5902 IndexerName, prop_attr, MemberType, ParameterTypes);
5905 PropertyBuilder.SetGetMethod (GetBuilder);
5908 PropertyBuilder.SetSetMethod (SetBuilder);
5910 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
5917 bool CheckNameCollision (TypeContainer container) {
5918 switch (VerifyName (container)){
5919 case DeclSpace.AdditionResult.NameExists:
5920 Report.Error (102, Location, "The container '{0}' already contains a definition for '{1}'", container.GetSignatureForError (), Name);
5923 case DeclSpace.AdditionResult.Success:
5926 throw new NotImplementedException ();
5929 DeclSpace.AdditionResult VerifyName (TypeContainer container) {
5930 if (!AddIndexer (container, container.Name + "." + Name))
5931 return DeclSpace.AdditionResult.NameExists;
5934 if (!AddIndexer (container, container.Name + ".get_" + Name))
5935 return DeclSpace.AdditionResult.NameExists;
5939 if (!AddIndexer (container, container.Name + ".set_" + Name))
5940 return DeclSpace.AdditionResult.NameExists;
5942 return DeclSpace.AdditionResult.Success;
5945 bool AddIndexer (TypeContainer container, string fullname)
5947 object value = container.GetDefinition (fullname);
5949 if (value != null) {
5950 return value.GetType () != GetType () ? false : true;
5953 container.DefineName (fullname, this);
5957 public override string GetSignatureForError ()
5959 return TypeManager.CSharpSignature (PropertyBuilder, true);
5962 protected override string RealMethodName {
5969 public class Operator : MemberBase, IIteratorContainer {
5971 const int AllowedModifiers =
5977 const int RequiredModifiers =
5981 public enum OpType : byte {
5991 // Unary and Binary operators
6014 // Implicit and Explicit
6019 public readonly OpType OperatorType;
6020 public readonly Expression ReturnType;
6021 public readonly Expression FirstArgType, SecondArgType;
6022 public readonly string FirstArgName, SecondArgName;
6024 public MethodBuilder OperatorMethodBuilder;
6026 public string MethodName;
6027 public Method OperatorMethod;
6029 static string[] attribute_targets = new string [] { "param" };
6031 public Operator (OpType type, Expression ret_type, int mod_flags,
6032 Expression arg1type, string arg1name,
6033 Expression arg2type, string arg2name,
6034 Block block, Attributes attrs, Location loc)
6035 : base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC, "", attrs, loc)
6037 OperatorType = type;
6038 Name = "op_" + OperatorType;
6039 ReturnType = ret_type;
6040 FirstArgType = arg1type;
6041 FirstArgName = arg1name;
6042 SecondArgType = arg2type;
6043 SecondArgName = arg2name;
6047 string Prototype (TypeContainer container)
6049 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
6050 SecondArgType + ")";
6053 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6055 OperatorMethod.ApplyAttributeBuilder (a, cb);
6058 public override AttributeTargets AttributeTargets {
6060 return AttributeTargets.Method;
6064 public override bool Define (TypeContainer container)
6067 MethodName = "op_" + OperatorType;
6069 if (SecondArgType != null)
6072 Parameter [] param_list = new Parameter [length];
6074 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
6077 "User defined operators `" +
6078 Prototype (container) +
6079 "' must be declared static and public");
6083 param_list[0] = new Parameter (FirstArgType, FirstArgName,
6084 Parameter.Modifier.NONE, null);
6085 if (SecondArgType != null)
6086 param_list[1] = new Parameter (SecondArgType, SecondArgName,
6087 Parameter.Modifier.NONE, null);
6089 OperatorMethod = new Method (
6090 container, ReturnType, ModFlags, false, MethodName,
6091 new Parameters (param_list, null, Location),
6092 OptAttributes, Location);
6094 OperatorMethod.Block = Block;
6095 OperatorMethod.IsOperator = true;
6096 OperatorMethod.Define (container);
6098 if (OperatorMethod.MethodBuilder == null)
6101 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
6103 Type [] param_types = OperatorMethod.ParameterTypes;
6104 Type declaring_type = OperatorMethodBuilder.DeclaringType;
6105 Type return_type = OperatorMethod.GetReturnType ();
6106 Type first_arg_type = param_types [0];
6108 // Rules for conversion operators
6110 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
6111 if (first_arg_type == return_type && first_arg_type == declaring_type){
6114 "User-defined conversion cannot take an object of the " +
6115 "enclosing type and convert to an object of the enclosing" +
6120 if (first_arg_type != declaring_type && return_type != declaring_type){
6123 "User-defined conversion must convert to or from the " +
6128 if (first_arg_type == TypeManager.object_type ||
6129 return_type == TypeManager.object_type){
6132 "User-defined conversion cannot convert to or from " +
6137 if (first_arg_type.IsInterface || return_type.IsInterface){
6140 "User-defined conversion cannot convert to or from an " +
6145 if (first_arg_type.IsSubclassOf (return_type) ||
6146 return_type.IsSubclassOf (first_arg_type)){
6149 "User-defined conversion cannot convert between types " +
6150 "that derive from each other");
6153 } else if (SecondArgType == null) {
6154 // Checks for Unary operators
6156 if (first_arg_type != declaring_type){
6159 "The parameter of a unary operator must be the " +
6164 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
6165 if (return_type != declaring_type){
6168 "The parameter and return type for ++ and -- " +
6169 "must be the containing type");
6175 if (OperatorType == OpType.True || OperatorType == OpType.False) {
6176 if (return_type != TypeManager.bool_type){
6179 "The return type of operator True or False " +
6186 // Checks for Binary operators
6188 if (first_arg_type != declaring_type &&
6189 param_types [1] != declaring_type){
6192 "One of the parameters of a binary operator must " +
6193 "be the containing type");
6201 public override void Emit (TypeContainer container)
6204 // abstract or extern methods have no bodies
6206 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
6209 OperatorMethod.Emit (container);
6213 public static string GetName (OpType ot)
6216 case OpType.LogicalNot:
6218 case OpType.OnesComplement:
6220 case OpType.Increment:
6222 case OpType.Decrement:
6228 case OpType.Addition:
6230 case OpType.Subtraction:
6232 case OpType.UnaryPlus:
6234 case OpType.UnaryNegation:
6236 case OpType.Multiply:
6238 case OpType.Division:
6240 case OpType.Modulus:
6242 case OpType.BitwiseAnd:
6244 case OpType.BitwiseOr:
6246 case OpType.ExclusiveOr:
6248 case OpType.LeftShift:
6250 case OpType.RightShift:
6252 case OpType.Equality:
6254 case OpType.Inequality:
6256 case OpType.GreaterThan:
6258 case OpType.LessThan:
6260 case OpType.GreaterThanOrEqual:
6262 case OpType.LessThanOrEqual:
6264 case OpType.Implicit:
6266 case OpType.Explicit:
6272 public override string ToString ()
6274 Type return_type = OperatorMethod.GetReturnType();
6275 Type [] param_types = OperatorMethod.ParameterTypes;
6277 if (SecondArgType == null)
6278 return String.Format (
6279 "{0} operator {1}({2})",
6280 TypeManager.CSharpName (return_type),
6281 GetName (OperatorType),
6284 return String.Format (
6285 "{0} operator {1}({2}, {3})",
6286 TypeManager.CSharpName (return_type),
6287 GetName (OperatorType),
6288 param_types [0], param_types [1]);
6291 protected override string[] ValidAttributeTargets {
6293 return attribute_targets;
6297 public void SetYields ()
6299 ModFlags |= Modifiers.METHOD_YIELDS;
6304 // This is used to compare method signatures
6306 struct MethodSignature {
6308 public Type RetType;
6309 public Type [] Parameters;
6312 /// This delegate is used to extract methods which have the
6313 /// same signature as the argument
6315 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
6317 public MethodSignature (string name, Type ret_type, Type [] parameters)
6322 if (parameters == null)
6323 Parameters = TypeManager.NoTypes;
6325 Parameters = parameters;
6328 public override string ToString ()
6331 if (Parameters.Length != 0){
6332 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
6333 for (int i = 0; i < Parameters.Length; i++){
6334 sb.Append (Parameters [i]);
6335 if (i+1 < Parameters.Length)
6338 pars = sb.ToString ();
6341 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
6344 public override int GetHashCode ()
6346 return Name.GetHashCode ();
6349 public override bool Equals (Object o)
6351 MethodSignature other = (MethodSignature) o;
6353 if (other.Name != Name)
6356 if (other.RetType != RetType)
6359 if (Parameters == null){
6360 if (other.Parameters == null)
6365 if (other.Parameters == null)
6368 int c = Parameters.Length;
6369 if (other.Parameters.Length != c)
6372 for (int i = 0; i < c; i++)
6373 if (other.Parameters [i] != Parameters [i])
6379 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
6381 MethodSignature sig = (MethodSignature) filter_criteria;
6383 if (m.Name != sig.Name)
6387 MethodInfo mi = m as MethodInfo;
6388 PropertyInfo pi = m as PropertyInfo;
6391 ReturnType = mi.ReturnType;
6392 else if (pi != null)
6393 ReturnType = pi.PropertyType;
6398 // we use sig.RetType == null to mean `do not check the
6399 // method return value.
6401 if (sig.RetType != null)
6402 if (ReturnType != sig.RetType)
6407 args = TypeManager.GetArgumentTypes (mi);
6409 args = TypeManager.GetArgumentTypes (pi);
6410 Type [] sigp = sig.Parameters;
6412 if (args.Length != sigp.Length)
6415 for (int i = args.Length; i > 0; ){
6417 if (args [i] != sigp [i])