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;
38 namespace Mono.CSharp {
41 /// This is the base class for structs and classes.
43 public class TypeContainer : DeclSpace, IMemberContainer {
44 // Holds a list of classes and structures
47 // Holds the list of properties
50 // Holds the list of enumerations
53 // Holds the list of delegates
56 // Holds the list of constructors
57 ArrayList instance_constructors;
59 // Holds the list of fields
62 // Holds a list of fields that have initializers
63 ArrayList initialized_fields;
65 // Holds a list of static fields that have initializers
66 ArrayList initialized_static_fields;
68 // Holds the list of constants
74 // Holds order in which interfaces must be closed
75 ArrayList interface_order;
86 // Holds the operators
89 // The emit context for toplevel objects.
93 // Pointers to the default constructor and the default static constructor
95 Constructor default_constructor;
96 Constructor default_static_constructor;
99 // Whether we have seen a static constructor for this class or not
101 public bool UserDefinedStaticConstructor = false;
104 // Whether we have at least one non-static field
106 bool have_nonstatic_fields = false;
109 // This one is computed after we can distinguish interfaces
110 // from classes from the arraylist `type_bases'
112 string base_class_name;
114 ArrayList type_bases;
116 bool members_defined;
117 bool members_defined_ok;
119 // Information in the case we are an attribute type
121 public AttributeTargets Targets = AttributeTargets.All;
122 public bool AllowMultiple = false;
123 public bool Inherited;
125 // The interfaces we implement.
127 Type[] base_inteface_types;
129 // The parent member container and our member cache
130 IMemberContainer parent_container;
131 MemberCache member_cache;
134 // The indexer name for this class
136 public string IndexerName;
140 public TypeContainer ():
141 this (null, null, MemberName.Null, null, new Location (-1)) {
144 public TypeContainer (NamespaceEntry ns, TypeContainer parent,
145 MemberName name, Attributes attrs, Location l)
146 : base (ns, parent, name, attrs, l)
148 types = new ArrayList ();
150 base_class_name = null;
153 public AdditionResult AddConstant (Const constant)
156 string basename = constant.Name;
157 string fullname = Name + "." + basename;
159 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
162 if (constants == null)
163 constants = new ArrayList ();
165 constants.Add (constant);
166 DefineName (fullname, constant);
168 return AdditionResult.Success;
171 public AdditionResult AddEnum (Mono.CSharp.Enum e)
175 if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
179 enums = new ArrayList ();
182 DefineName (e.Name, e);
184 return AdditionResult.Success;
187 public AdditionResult AddClass (Class c)
190 string name = c.Basename;
192 if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
195 DefineName (c.Name, c);
198 return AdditionResult.Success;
201 public AdditionResult AddStruct (Struct s)
204 string name = s.Basename;
206 if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
209 DefineName (s.Name, s);
212 return AdditionResult.Success;
215 public AdditionResult AddDelegate (Delegate d)
218 string name = d.Basename;
220 if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
223 if (delegates == null)
224 delegates = new ArrayList ();
226 DefineName (d.Name, d);
229 return AdditionResult.Success;
232 public AdditionResult AddMethod (Method method)
234 string basename = method.Name;
235 string fullname = Name + "." + basename;
237 Object value = defined_names [fullname];
239 if (value != null && (!(value is Method)))
240 return AdditionResult.NameExists;
242 if (basename == Basename)
243 return AdditionResult.EnclosingClash;
246 methods = new ArrayList ();
248 if (method.Name.IndexOf ('.') != -1)
249 methods.Insert (0, method);
251 methods.Add (method);
254 DefineName (fullname, method);
256 return AdditionResult.Success;
259 public AdditionResult AddConstructor (Constructor c)
261 if (c.Name != Basename)
262 return AdditionResult.NotAConstructor;
264 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
267 UserDefinedStaticConstructor = true;
268 if (default_static_constructor != null)
269 return AdditionResult.MethodExists;
271 default_static_constructor = c;
274 if (default_constructor != null)
275 return AdditionResult.MethodExists;
276 default_constructor = c;
279 if (instance_constructors == null)
280 instance_constructors = new ArrayList ();
282 instance_constructors.Add (c);
285 return AdditionResult.Success;
288 public AdditionResult AddInterface (Interface iface)
291 string name = iface.Basename;
293 if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
296 if (interfaces == null)
297 interfaces = new ArrayList ();
298 interfaces.Add (iface);
299 DefineName (iface.Name, iface);
301 return AdditionResult.Success;
304 public AdditionResult AddField (Field field)
307 string basename = field.Name;
308 string fullname = Name + "." + basename;
310 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
314 fields = new ArrayList ();
318 if (field.HasInitializer){
319 if ((field.ModFlags & Modifiers.STATIC) != 0){
320 if (initialized_static_fields == null)
321 initialized_static_fields = new ArrayList ();
323 initialized_static_fields.Add (field);
326 if (initialized_fields == null)
327 initialized_fields = new ArrayList ();
329 initialized_fields.Add (field);
333 if ((field.ModFlags & Modifiers.STATIC) == 0)
334 have_nonstatic_fields = true;
336 DefineName (fullname, field);
337 return AdditionResult.Success;
340 public AdditionResult AddProperty (Property prop)
344 if ((res = AddProperty (prop, prop.Name)) != AdditionResult.Success)
347 if (prop.Get != null) {
348 if ((res = AddProperty (prop, "get_" + prop.Name)) != AdditionResult.Success)
352 if (prop.Set != null) {
353 if ((res = AddProperty (prop, "set_" + prop.Name)) != AdditionResult.Success)
357 if (properties == null)
358 properties = new ArrayList ();
360 if (prop.Name.IndexOf ('.') != -1)
361 properties.Insert (0, prop);
363 properties.Add (prop);
365 return AdditionResult.Success;
368 AdditionResult AddProperty (Property prop, string basename)
371 string fullname = Name + "." + basename;
373 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
376 DefineName (fullname, prop);
378 return AdditionResult.Success;
381 public AdditionResult AddEvent (Event e)
384 string basename = e.Name;
385 string fullname = Name + "." + basename;
387 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
391 events = new ArrayList ();
394 DefineName (fullname, e);
396 return AdditionResult.Success;
399 public void AddIndexer (Indexer i)
401 if (indexers == null)
402 indexers = new ArrayList ();
404 if (i.InterfaceType != null)
405 indexers.Insert (0, i);
410 public AdditionResult AddOperator (Operator op)
412 if (operators == null)
413 operators = new ArrayList ();
417 string basename = op.Name;
418 string fullname = Name + "." + basename;
419 if (!defined_names.Contains (fullname))
421 DefineName (fullname, op);
423 return AdditionResult.Success;
426 public void RegisterOrder (Interface iface)
428 if (interface_order == null)
429 interface_order = new ArrayList ();
431 interface_order.Add (iface);
434 public ArrayList Types {
440 public ArrayList Methods {
446 public ArrayList Constants {
452 public ArrayList Interfaces {
460 return base_class_name;
464 public ArrayList Bases {
474 public ArrayList Fields {
484 public ArrayList InstanceConstructors {
486 return instance_constructors;
490 public ArrayList Properties {
496 public ArrayList Events {
502 public ArrayList Enums {
508 public ArrayList Indexers {
514 public ArrayList Operators {
520 public ArrayList Delegates {
526 public virtual TypeAttributes TypeAttr {
528 return Modifiers.TypeAttr (ModFlags, this);
533 // Emits the instance field initializers
535 public bool EmitFieldInitializers (EmitContext ec)
538 Expression instance_expr;
541 fields = initialized_static_fields;
542 instance_expr = null;
544 fields = initialized_fields;
545 instance_expr = new This (Location.Null).Resolve (ec);
551 foreach (Field f in fields){
552 Expression e = f.GetInitializerExpression (ec);
556 Location l = f.Location;
557 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
558 fe.InstanceExpression = instance_expr;
559 ExpressionStatement a = new Assign (fe, e, l);
561 a = a.ResolveStatement (ec);
565 a.EmitStatement (ec);
572 // Defines the default constructors
574 void DefineDefaultConstructor (bool is_static)
578 // The default constructor is public
579 // If the class is abstract, the default constructor is protected
580 // The default static constructor is private
582 int mods = Modifiers.PUBLIC;
584 mods = Modifiers.STATIC | Modifiers.PRIVATE;
585 else if ((ModFlags & Modifiers.ABSTRACT) != 0)
586 mods = Modifiers.PROTECTED;
588 c = new Constructor (this, Basename, mods, Parameters.EmptyReadOnlyParameters,
589 new ConstructorBaseInitializer (
590 null, Parameters.EmptyReadOnlyParameters,
596 c.Block = new ToplevelBlock (null, Location);
600 public void ReportStructInitializedInstanceError ()
602 string n = TypeBuilder.FullName;
604 foreach (Field f in initialized_fields){
607 "`" + n + "." + f.Name + "': can not have " +
608 "instance field initializers in structs");
613 /// The pending methods that need to be implemented (interfaces or abstract methods)
615 public PendingImplementation Pending;
618 /// This function computes the Base class and also the
619 /// list of interfaces that the class or struct @c implements.
621 /// The return value is an array (might be null) of
622 /// interfaces implemented (as Types).
624 /// The @parent argument is set to the parent object or null
625 /// if this is `System.Object'.
627 TypeExpr [] GetClassBases (bool is_class, bool is_iface,
628 out TypeExpr parent, out bool error)
630 ArrayList bases = Bases;
636 if (is_class || is_iface)
639 parent = TypeManager.system_valuetype_expr;
643 if (RootContext.StdLib)
644 parent = TypeManager.system_object_expr;
645 else if (Name != "System.Object")
646 parent = TypeManager.system_object_expr;
649 // If we are compiling our runtime,
650 // and we are defining ValueType, then our
651 // parent is `System.Object'.
653 if (!RootContext.StdLib && Name == "System.ValueType")
654 parent = TypeManager.system_object_expr;
661 // Bases should be null if there are no bases at all
666 TypeExpr name = ResolveTypeExpr ((Expression) bases [0], false, Location);
673 if (name is TypeParameterExpr){
676 "Type parameter `{0}' can not be used as a " +
677 "base class or interface", name.Name);
682 if (IsGeneric && name.IsAttribute){
685 "A generic type cannot derive from `{0}' " +
686 "because it is an attribute class", name.Name);
695 parent = TypeManager.system_object_expr;
701 if (name.IsValueType)
702 detail = " (a class can not inherit from a struct/enum)";
704 Report.Error (509, "class `"+ Name +
705 "': Cannot inherit from sealed class `"+
706 name.Name + "'" + detail);
711 if (!parent.CanInheritFrom ()){
712 Report.Error (644, Location,
713 "`{0}' cannot inherit from special class `{1}'",
719 if (!parent.AsAccessible (this, ModFlags))
720 Report.Error (60, Location,
721 "Inconsistent accessibility: base class `" +
722 name.Name + "' is less accessible than class `" +
730 base_class_name = parent.Name;
732 TypeExpr [] ifaces = new TypeExpr [count-start];
734 for (i = start, j = 0; i < count; i++, j++){
735 Expression name = (Expression) bases [i];
736 TypeExpr resolved = ResolveTypeExpr (name, false, Location);
738 if (resolved == null)
741 bases [i] = resolved;
743 if (is_class == false && !resolved.IsInterface){
744 Report.Error (527, "In Struct `" + Name + "', type `"+
745 name +"' is not an interface");
750 if (resolved.IsClass) {
752 Report.Error (527, "In Class `" + Name + "', type `"+
753 name+"' is not an interface");
759 for (int x = 0; x < j; x++) {
760 if (resolved.Equals (ifaces [x])) {
761 Report.Error (528, "`" + name + "' is already listed in interface list");
768 !resolved.AsAccessible (Parent, ModFlags))
769 Report.Error (61, Location,
770 "Inconsistent accessibility: base interface `" +
771 name + "' is less accessible than interface `" +
774 ifaces [j] = resolved;
777 return TypeManager.ExpandInterfaces (ifaces);
780 bool CheckGenericInterfaces (Type[] ifaces)
782 ArrayList already_checked = new ArrayList ();
784 for (int i = 0; i < ifaces.Length; i++) {
785 Type iface = ifaces [i];
786 foreach (Type t in already_checked) {
790 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t))
795 "`{0}' cannot implement both `{1}' and `{2}' " +
796 "because they may unify for some type " +
797 "parameter substitutions",
798 TypeManager.GetFullName (TypeBuilder),
803 already_checked.Add (iface);
812 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
814 public override TypeBuilder DefineType ()
817 bool is_class, is_iface;
819 if (TypeBuilder != null)
826 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
833 if (this is Interface) {
844 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
846 ifaces = GetClassBases (is_class, is_iface, out parent, out error);
852 foreach (TypeParameter type_param in TypeParameters)
853 if (!type_param.Resolve (this)) {
859 if (!is_class && TypeManager.value_type == null)
860 throw new Exception ();
862 TypeAttributes type_attributes = TypeAttr;
865 ConstructedType constructed = parent as ConstructedType;
866 if ((constructed == null) && (parent != null))
867 ptype = parent.ResolveType (ec);
872 if (TypeManager.NamespaceClash (Name, Location)) {
877 ModuleBuilder builder = CodeGen.Module.Builder;
878 TypeBuilder = builder.DefineType (
879 Name, type_attributes, ptype, null);
881 TypeBuilder builder = Parent.DefineType ();
882 if (builder == null) {
887 TypeBuilder = builder.DefineNestedType (
888 MemberName.Basename, type_attributes, ptype, null);
891 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
894 CurrentType = new ConstructedType (
895 Name, TypeParameters, Location);
897 string[] param_names = new string [TypeParameters.Length];
898 for (int i = 0; i < TypeParameters.Length; i++)
899 param_names [i] = TypeParameters [i].Name;
901 GenericTypeParameterBuilder[] gen_params;
903 gen_params = TypeBuilder.DefineGenericParameters (param_names);
905 for (int i = 0; i < gen_params.Length; i++)
906 TypeParameters [i].Define (gen_params [i]);
909 if (constructed != null) {
910 ptype = constructed.ResolveType (ec);
916 TypeBuilder.SetParent (ptype);
920 foreach (TypeParameter type_param in TypeParameters)
921 if (!type_param.DefineType (ec))
929 // Structs with no fields need to have at least one byte.
930 // The right thing would be to set the PackingSize in a DefineType
931 // but there are no functions that allow interfaces *and* the size to
935 if (!is_class && !is_iface && !have_nonstatic_fields){
936 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
937 FieldAttributes.Private);
940 // add interfaces that were not added at type creation
941 if (ifaces != null) {
942 Type[] itypes = new Type[ifaces.Length];
943 for (int i = 0; i < ifaces.Length; ++i) {
944 Type itype = ifaces [i].ResolveType (ec);
945 TypeBuilder.AddInterfaceImplementation (itype);
952 if (!CheckGenericInterfaces (itypes)) {
959 // Finish the setup for the EmitContext
961 ec.ContainerType = TypeBuilder;
963 if ((parent != null) && parent.IsAttribute) {
964 RootContext.RegisterAttribute (this);
965 TypeManager.RegisterAttrType (TypeBuilder, this);
967 RootContext.RegisterOrder (this);
969 if (Interfaces != null) {
970 foreach (Interface iface in Interfaces)
971 if (iface.DefineType () == null) {
978 foreach (TypeContainer tc in Types)
979 if (tc.DefineType () == null) {
985 if (Delegates != null) {
986 foreach (Delegate d in Delegates)
987 if (d.DefineType () == null) {
994 foreach (Enum en in Enums)
995 if (en.DefineType () == null) {
1007 /// Defines the MemberCore objects that are in the `list' Arraylist
1009 /// The `defined_names' array contains a list of members defined in
1012 static ArrayList remove_list = new ArrayList ();
1013 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
1017 remove_list.Clear ();
1019 foreach (MemberCore mc in list){
1021 if (defined_names != null)
1022 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
1027 if (RootContext.WarningLevel >= 4){
1028 if ((mc.ModFlags & Modifiers.NEW) != 0)
1029 Warning_KeywordNewNotRequired (mc.Location, mc);
1031 } else if (mc is MethodCore)
1032 ((MethodCore) mc).OverridesSomething = true;
1034 if (!mc.Define (this)){
1035 remove_list.Add (mc);
1042 MemberInfo match = defined_names [idx];
1044 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
1048 // If we are both methods, let the method resolution emit warnings
1050 if (match is MethodBase && mc is MethodCore)
1053 if ((mc.ModFlags & Modifiers.NEW) == 0) {
1055 if (!(match is EventInfo)) {
1056 Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
1060 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
1064 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
1068 foreach (object o in remove_list)
1071 remove_list.Clear ();
1075 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
1076 // class is consisten. Either it is `Item' or it is the name defined by all the
1077 // indexers with the `IndexerName' attribute.
1079 // Turns out that the IndexerNameAttribute is applied to each indexer,
1080 // but it is never emitted, instead a DefaultName attribute is attached
1083 void DefineIndexers ()
1085 string class_indexer_name = null;
1088 // If there's both an explicit and an implicit interface implementation, the
1089 // explicit one actually implements the interface while the other one is just
1090 // a normal indexer. See bug #37714.
1093 ArrayList list = new ArrayList ();
1094 foreach (Indexer i in Indexers){
1095 if (i.MemberName.TypeName != null)
1098 foreach (Indexer i in Indexers){
1099 if (i.MemberName.TypeName == null)
1103 foreach (Indexer i in list){
1108 name = i.IndexerName;
1110 if (i.InterfaceType != null)
1113 if (class_indexer_name == null){
1114 class_indexer_name = name;
1118 if (name == class_indexer_name)
1122 668, "Two indexers have different names, " +
1123 " you should use the same name for all your indexers");
1125 if (class_indexer_name == null)
1126 class_indexer_name = "Item";
1127 IndexerName = class_indexer_name;
1130 static void Error_KeywordNotAllowed (Location loc)
1132 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1136 /// Populates our TypeBuilder with fields and methods
1138 public override bool DefineMembers (TypeContainer container)
1140 if (members_defined)
1141 return members_defined_ok;
1143 members_defined_ok = DoDefineMembers ();
1144 members_defined = true;
1146 return members_defined_ok;
1149 bool DoDefineMembers ()
1151 MemberInfo [] defined_names = null;
1154 // We need to be able to use the member cache while we are checking/defining
1157 if (TypeBuilder.BaseType != null)
1158 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1161 if (interface_order != null){
1162 foreach (Interface iface in interface_order)
1163 if ((iface.ModFlags & Modifiers.NEW) == 0)
1164 iface.DefineMembers (this);
1166 Error_KeywordNotAllowed (iface.Location);
1169 if (RootContext.WarningLevel > 1){
1173 // This code throws an exception in the comparer
1174 // I guess the string is not an object?
1176 ptype = TypeBuilder.BaseType;
1178 defined_names = (MemberInfo []) FindMembers (
1179 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1180 BindingFlags.Public | BindingFlags.Instance |
1181 BindingFlags.Static, null, null);
1183 Array.Sort (defined_names, mif_compare);
1187 Class pclass = Parent as Class;
1188 if (pclass != null) {
1189 string pname = null;
1190 TypeExpr ptype = null;
1191 Type t = pclass.TypeBuilder.BaseType;
1192 while ((t != null) && (ptype == null)) {
1193 pname = t.FullName + "." + Basename;
1194 ptype = RootContext.LookupType (this, pname, true, Location.Null);
1198 if ((ModFlags & Modifiers.NEW) != 0) {
1200 Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
1201 "inherited member. The keyword new is not required.");
1202 } else if (ptype != null) {
1203 Report.Warning (108, Location, "The keyword new is required on `" +
1204 Name + "' because it hides inherited member '" +
1207 } else if ((ModFlags & Modifiers.NEW) != 0)
1208 Error_KeywordNotAllowed (Location);
1210 if (constants != null)
1211 DefineMembers (constants, defined_names);
1214 DefineMembers (fields, defined_names);
1217 if (instance_constructors == null){
1218 if (default_constructor == null)
1219 DefineDefaultConstructor (false);
1222 if (initialized_static_fields != null &&
1223 default_static_constructor == null)
1224 DefineDefaultConstructor (true);
1227 if (this is Struct){
1229 // Structs can not have initialized instance
1232 if (initialized_static_fields != null &&
1233 default_static_constructor == null)
1234 DefineDefaultConstructor (true);
1236 if (initialized_fields != null)
1237 ReportStructInitializedInstanceError ();
1240 if (!(this is Interface))
1241 Pending = PendingImplementation.GetPendingImplementations (this);
1244 // Constructors are not in the defined_names array
1246 if (instance_constructors != null)
1247 DefineMembers (instance_constructors, null);
1249 if (default_static_constructor != null)
1250 default_static_constructor.Define (this);
1252 if (methods != null)
1253 DefineMembers (methods, defined_names);
1255 if (properties != null)
1256 DefineMembers (properties, defined_names);
1259 DefineMembers (events, defined_names);
1261 if (indexers != null) {
1264 IndexerName = "Item";
1266 if (operators != null){
1267 DefineMembers (operators, null);
1269 CheckPairedOperators ();
1273 DefineMembers (enums, defined_names);
1275 if (delegates != null)
1276 DefineMembers (delegates, defined_names);
1278 if (CurrentType != null) {
1279 GenericType = CurrentType.ResolveType (ec);
1281 ec.ContainerType = GenericType;
1286 member_cache = new MemberCache (this);
1293 public override bool Define (TypeContainer container)
1295 if (interface_order != null){
1296 foreach (Interface iface in interface_order)
1297 if ((iface.ModFlags & Modifiers.NEW) == 0)
1298 iface.Define (this);
1305 /// This function is based by a delegate to the FindMembers routine
1307 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1313 /// This filter is used by FindMembers, and we just keep
1314 /// a global for the filter to `AlwaysAccept'
1316 static MemberFilter accepting_filter;
1320 /// A member comparission method based on name only
1322 static IComparer mif_compare;
1324 static TypeContainer ()
1326 accepting_filter = new MemberFilter (AlwaysAccept);
1327 mif_compare = new MemberInfoCompare ();
1330 public MethodInfo[] GetMethods ()
1332 ArrayList members = new ArrayList ();
1334 DefineMembers (null);
1336 if (methods != null) {
1337 int len = methods.Count;
1338 for (int i = 0; i < len; i++) {
1339 Method m = (Method) methods [i];
1341 members.Add (m.MethodBuilder);
1345 if (operators != null) {
1346 int len = operators.Count;
1347 for (int i = 0; i < len; i++) {
1348 Operator o = (Operator) operators [i];
1350 members.Add (o.OperatorMethodBuilder);
1354 if (properties != null) {
1355 int len = properties.Count;
1356 for (int i = 0; i < len; i++) {
1357 Property p = (Property) properties [i];
1359 if (p.GetBuilder != null)
1360 members.Add (p.GetBuilder);
1361 if (p.SetBuilder != null)
1362 members.Add (p.SetBuilder);
1366 if (indexers != null) {
1367 int len = indexers.Count;
1368 for (int i = 0; i < len; i++) {
1369 Indexer ix = (Indexer) indexers [i];
1371 if (ix.GetBuilder != null)
1372 members.Add (ix.GetBuilder);
1373 if (ix.SetBuilder != null)
1374 members.Add (ix.SetBuilder);
1378 if (events != null) {
1379 int len = events.Count;
1380 for (int i = 0; i < len; i++) {
1381 Event e = (Event) events [i];
1383 if (e.AddBuilder != null)
1384 members.Add (e.AddBuilder);
1385 if (e.RemoveBuilder != null)
1386 members.Add (e.RemoveBuilder);
1390 MethodInfo[] retMethods = new MethodInfo [members.Count];
1391 members.CopyTo (retMethods, 0);
1396 /// This method returns the members of this type just like Type.FindMembers would
1397 /// Only, we need to use this for types which are _being_ defined because MS'
1398 /// implementation can't take care of that.
1401 // FIXME: return an empty static array instead of null, that cleans up
1402 // some code and is consistent with some coding conventions I just found
1406 // Notice that in various cases we check if our field is non-null,
1407 // something that would normally mean that there was a bug elsewhere.
1409 // The problem happens while we are defining p-invoke methods, as those
1410 // will trigger a FindMembers, but this happens before things are defined
1412 // Since the whole process is a no-op, it is fine to check for null here.
1414 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1415 MemberFilter filter, object criteria)
1417 ArrayList members = null;
1420 if ((bf & BindingFlags.Public) != 0)
1421 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1423 if ((bf & BindingFlags.NonPublic) != 0)
1424 modflags |= Modifiers.PRIVATE;
1426 int static_mask = 0, static_flags = 0;
1427 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1428 case BindingFlags.Static:
1429 static_mask = static_flags = Modifiers.STATIC;
1432 case BindingFlags.Instance:
1433 static_mask = Modifiers.STATIC;
1438 static_mask = static_flags = 0;
1442 Timer.StartTimer (TimerType.TcFindMembers);
1445 filter = accepting_filter;
1447 if ((mt & MemberTypes.Field) != 0) {
1448 if (fields != null) {
1449 int len = fields.Count;
1450 for (int i = 0; i < len; i++) {
1451 Field f = (Field) fields [i];
1453 if ((f.ModFlags & modflags) == 0)
1455 if ((f.ModFlags & static_mask) != static_flags)
1458 FieldBuilder fb = f.FieldBuilder;
1459 if (fb != null && filter (fb, criteria) == true) {
1460 if (members == null)
1461 members = new ArrayList ();
1468 if (constants != null) {
1469 int len = constants.Count;
1470 for (int i = 0; i < len; i++) {
1471 Const con = (Const) constants [i];
1473 if ((con.ModFlags & modflags) == 0)
1475 if ((con.ModFlags & static_mask) != static_flags)
1478 FieldBuilder fb = con.FieldBuilder;
1479 if (fb != null && filter (fb, criteria) == true) {
1480 if (members == null)
1481 members = new ArrayList ();
1489 if ((mt & MemberTypes.Method) != 0) {
1490 if (methods != null) {
1491 int len = methods.Count;
1492 for (int i = 0; i < len; i++) {
1493 Method m = (Method) methods [i];
1495 if ((m.ModFlags & modflags) == 0)
1497 if ((m.ModFlags & static_mask) != static_flags)
1500 MethodBuilder mb = m.MethodBuilder;
1502 if (mb != null && filter (mb, criteria) == true) {
1503 if (members == null)
1504 members = new ArrayList ();
1511 if (operators != null) {
1512 int len = operators.Count;
1513 for (int i = 0; i < len; i++) {
1514 Operator o = (Operator) operators [i];
1516 if ((o.ModFlags & modflags) == 0)
1518 if ((o.ModFlags & static_mask) != static_flags)
1521 MethodBuilder ob = o.OperatorMethodBuilder;
1522 if (ob != null && filter (ob, criteria) == true) {
1523 if (members == null)
1524 members = new ArrayList ();
1531 if (properties != null) {
1532 int len = properties.Count;
1533 for (int i = 0; i < len; i++) {
1534 Property p = (Property) properties [i];
1536 if ((p.ModFlags & modflags) == 0)
1538 if ((p.ModFlags & static_mask) != static_flags)
1544 if (b != null && filter (b, criteria) == true) {
1545 if (members == null)
1546 members = new ArrayList ();
1552 if (b != null && filter (b, criteria) == true) {
1553 if (members == null)
1554 members = new ArrayList ();
1561 if (indexers != null) {
1562 int len = indexers.Count;
1563 for (int i = 0; i < len; i++) {
1564 Indexer ix = (Indexer) indexers [i];
1566 if ((ix.ModFlags & modflags) == 0)
1568 if ((ix.ModFlags & static_mask) != static_flags)
1574 if (b != null && filter (b, criteria) == true) {
1575 if (members == null)
1576 members = new ArrayList ();
1582 if (b != null && filter (b, criteria) == true) {
1583 if (members == null)
1584 members = new ArrayList ();
1592 if ((mt & MemberTypes.Event) != 0) {
1593 if (events != null) {
1594 int len = events.Count;
1595 for (int i = 0; i < len; i++) {
1596 Event e = (Event) events [i];
1598 if ((e.ModFlags & modflags) == 0)
1600 if ((e.ModFlags & static_mask) != static_flags)
1603 MemberInfo eb = e.EventBuilder;
1604 if (eb != null && filter (eb, criteria) == true) {
1605 if (members == null)
1606 members = new ArrayList ();
1608 members.Add (e.EventBuilder);
1614 if ((mt & MemberTypes.Property) != 0){
1615 if (properties != null) {
1616 int len = properties.Count;
1617 for (int i = 0; i < len; i++) {
1618 Property p = (Property) properties [i];
1620 if ((p.ModFlags & modflags) == 0)
1622 if ((p.ModFlags & static_mask) != static_flags)
1625 MemberInfo pb = p.PropertyBuilder;
1626 if (pb != null && filter (pb, criteria) == true) {
1627 if (members == null)
1628 members = new ArrayList ();
1630 members.Add (p.PropertyBuilder);
1635 if (indexers != null) {
1636 int len = indexers.Count;
1637 for (int i = 0; i < len; i++) {
1638 Indexer ix = (Indexer) indexers [i];
1640 if ((ix.ModFlags & modflags) == 0)
1642 if ((ix.ModFlags & static_mask) != static_flags)
1645 MemberInfo ib = ix.PropertyBuilder;
1646 if (ib != null && filter (ib, criteria) == true) {
1647 if (members == null)
1648 members = new ArrayList ();
1650 members.Add (ix.PropertyBuilder);
1656 if ((mt & MemberTypes.NestedType) != 0) {
1657 if (types != null) {
1658 int len = types.Count;
1659 for (int i = 0; i < len; i++) {
1660 TypeContainer t = (TypeContainer) types [i];
1662 if ((t.ModFlags & modflags) == 0)
1665 TypeBuilder tb = t.TypeBuilder;
1666 if (tb != null && (filter (tb, criteria) == true)) {
1667 if (members == null)
1668 members = new ArrayList ();
1675 if (enums != null) {
1676 int len = enums.Count;
1677 for (int i = 0; i < len; i++) {
1678 Enum en = (Enum) enums [i];
1680 if ((en.ModFlags & modflags) == 0)
1683 TypeBuilder tb = en.TypeBuilder;
1684 if (tb != null && (filter (tb, criteria) == true)) {
1685 if (members == null)
1686 members = new ArrayList ();
1693 if (delegates != null) {
1694 int len = delegates.Count;
1695 for (int i = 0; i < len; i++) {
1696 Delegate d = (Delegate) delegates [i];
1698 if ((d.ModFlags & modflags) == 0)
1701 TypeBuilder tb = d.TypeBuilder;
1702 if (tb != null && (filter (tb, criteria) == true)) {
1703 if (members == null)
1704 members = new ArrayList ();
1711 if (interfaces != null) {
1712 int len = interfaces.Count;
1713 for (int i = 0; i < len; i++) {
1714 Interface iface = (Interface) interfaces [i];
1716 if ((iface.ModFlags & modflags) == 0)
1719 TypeBuilder tb = iface.TypeBuilder;
1720 if (tb != null && (filter (tb, criteria) == true)) {
1721 if (members == null)
1722 members = new ArrayList ();
1730 if ((mt & MemberTypes.Constructor) != 0){
1731 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1732 int len = instance_constructors.Count;
1733 for (int i = 0; i < len; i++) {
1734 Constructor c = (Constructor) instance_constructors [i];
1736 ConstructorBuilder cb = c.ConstructorBuilder;
1737 if (cb != null && filter (cb, criteria) == true) {
1738 if (members == null)
1739 members = new ArrayList ();
1746 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1747 ConstructorBuilder cb =
1748 default_static_constructor.ConstructorBuilder;
1750 if (cb != null && filter (cb, criteria) == true) {
1751 if (members == null)
1752 members = new ArrayList ();
1760 // Lookup members in parent if requested.
1762 if ((bf & BindingFlags.DeclaredOnly) == 0) {
1763 if (TypeBuilder.BaseType != null) {
1764 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1765 if (list.Count > 0) {
1766 if (members == null)
1767 members = new ArrayList ();
1769 members.AddRange (list);
1773 if (base_inteface_types != null) {
1774 foreach (Type base_type in base_inteface_types) {
1775 MemberList list = TypeContainer.FindMembers (base_type, mt, bf, filter, criteria);
1777 if (list.Count > 0) {
1778 if (members == null)
1779 members = new ArrayList ();
1780 members.AddRange (list);
1786 Timer.StopTimer (TimerType.TcFindMembers);
1788 if (members == null)
1789 return MemberList.Empty;
1791 return new MemberList (members);
1794 public override MemberCache MemberCache {
1796 return member_cache;
1800 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1801 MemberFilter filter, object criteria)
1803 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1806 return ds.FindMembers (mt, bf, filter, criteria);
1808 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1812 // FindMethods will look for methods not only in the type `t', but in
1813 // any interfaces implemented by the type.
1815 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1816 MemberFilter filter, object criteria)
1822 /// Emits the values for the constants
1824 public void EmitConstants ()
1826 if (constants != null)
1827 foreach (Const con in constants)
1833 /// Emits the code, this step is performed after all
1834 /// the types, enumerations, constructors
1838 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
1842 if (instance_constructors != null) {
1843 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && IsClsCompliaceRequired (this)) {
1844 bool has_compliant_args = false;
1846 foreach (Constructor c in instance_constructors) {
1849 if (has_compliant_args)
1852 has_compliant_args = c.HasCompliantArgs;
1854 if (!has_compliant_args)
1855 Report.Error_T (3015, Location, GetSignatureForError ());
1857 foreach (Constructor c in instance_constructors)
1862 if (default_static_constructor != null)
1863 default_static_constructor.Emit (this);
1865 if (methods != null)
1866 foreach (Method m in methods)
1869 if (operators != null)
1870 foreach (Operator o in operators)
1873 if (properties != null)
1874 foreach (Property p in properties)
1877 if (indexers != null){
1878 foreach (Indexer ix in indexers)
1881 CustomAttributeBuilder cb = EmitDefaultMemberAttr ();
1882 TypeBuilder.SetCustomAttribute (cb);
1886 foreach (Field f in fields)
1889 if (events != null){
1890 foreach (Event e in Events)
1894 if (delegates != null) {
1895 foreach (Delegate d in Delegates) {
1900 if (Pending != null)
1901 if (Pending.VerifyPendingMethods ())
1905 // Check for internal or private fields that were never assigned
1907 if (RootContext.WarningLevel >= 3) {
1908 if (fields != null){
1909 foreach (Field f in fields) {
1910 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
1913 if ((f.status & Field.Status.USED) == 0){
1915 169, f.Location, "Private field " +
1916 MakeName (f.Name) + " is never used");
1921 // Only report 649 on level 4
1923 if (RootContext.WarningLevel < 4)
1926 if ((f.status & Field.Status.ASSIGNED) != 0)
1931 "Field " + MakeName (f.Name) + " is never assigned " +
1932 " to and will always have its default value");
1936 if (events != null){
1937 foreach (Event e in events){
1939 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1944 // if (types != null)
1945 // foreach (TypeContainer tc in types)
1949 CustomAttributeBuilder EmitDefaultMemberAttr ()
1951 EmitContext ec = new EmitContext (this, Location, null, null, ModFlags);
1953 Expression ml = Expression.MemberLookup (ec, TypeManager.default_member_type,
1954 ".ctor", MemberTypes.Constructor,
1955 BindingFlags.Public | BindingFlags.Instance,
1958 MethodGroupExpr mg = (MethodGroupExpr) ml;
1960 MethodBase constructor = mg.Methods [0];
1962 string [] vals = { IndexerName };
1964 CustomAttributeBuilder cb = null;
1966 cb = new CustomAttributeBuilder ((ConstructorInfo) constructor, vals);
1968 Report.Warning (-100, "Can not set the indexer default member attribute");
1974 public override void CloseType ()
1981 TypeBuilder.CreateType ();
1982 } catch (TypeLoadException){
1984 // This is fine, the code still created the type
1986 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1987 // Console.WriteLine (e.Message);
1989 Console.WriteLine ("In type: " + Name);
1994 foreach (Enum en in Enums)
1997 if (interface_order != null){
1998 foreach (Interface iface in interface_order)
2003 foreach (TypeContainer tc in Types)
2007 foreach (TypeContainer tc in Types)
2008 if (!(tc is Struct))
2012 if (Delegates != null)
2013 foreach (Delegate d in Delegates)
2021 initialized_fields = null;
2022 initialized_static_fields = null;
2025 interface_order = null;
2031 default_constructor = null;
2032 default_static_constructor = null;
2034 OptAttributes = null;
2036 parent_container = null;
2037 member_cache = null;
2040 public string MakeName (string n)
2042 return "`" + Name + "." + n + "'";
2045 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
2048 108, l, "The keyword new is required on " +
2049 MakeName (mi.Name) + " because it hides `" +
2050 mi.ReflectedType.Name + "." + mi.Name + "'");
2053 public void Warning_KeywordNewNotRequired (Location l, MemberCore mc)
2056 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
2057 "inherited member, the keyword new is not required");
2060 public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
2063 72, l, MakeName (mi.Name) + " : cannot override; `" +
2064 mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
2067 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
2073 // Performs the validation on a Method's modifiers (properties have
2074 // the same properties).
2076 public bool MethodModifiersValid (int flags, string n, Location loc)
2078 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2079 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2080 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2084 // At most one of static, virtual or override
2086 if ((flags & Modifiers.STATIC) != 0){
2087 if ((flags & vao) != 0){
2089 112, loc, "static method " + MakeName (n) + "can not be marked " +
2090 "as virtual, abstract or override");
2095 if (this is Struct){
2096 if ((flags & va) != 0){
2097 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
2102 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2104 113, loc, MakeName (n) +
2105 " marked as override cannot be marked as new or virtual");
2110 // If the declaration includes the abstract modifier, then the
2111 // declaration does not include static, virtual or extern
2113 if ((flags & Modifiers.ABSTRACT) != 0){
2114 if ((flags & Modifiers.EXTERN) != 0){
2116 180, loc, MakeName (n) + " can not be both abstract and extern");
2120 if ((flags & Modifiers.VIRTUAL) != 0){
2122 503, loc, MakeName (n) + " can not be both abstract and virtual");
2126 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2128 513, loc, MakeName (n) +
2129 " is abstract but its container class is not");
2135 if ((flags & Modifiers.PRIVATE) != 0){
2136 if ((flags & vao) != 0){
2138 621, loc, MakeName (n) +
2139 " virtual or abstract members can not be private");
2144 if ((flags & Modifiers.SEALED) != 0){
2145 if ((flags & Modifiers.OVERRIDE) == 0){
2147 238, loc, MakeName (n) +
2148 " cannot be sealed because it is not an override");
2156 Hashtable builder_and_args;
2158 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
2160 if (builder_and_args == null)
2161 builder_and_args = new Hashtable ();
2165 protected override bool VerifyClsCompliance (DeclSpace ds)
2167 if (!base.VerifyClsCompliance (ds))
2170 // parent_container is null for System.Object
2171 if (parent_container != null && !AttributeTester.IsClsCompliant (parent_container.Type)) {
2172 Report.Error_T (3009, Location, GetSignatureForError (), TypeManager.CSharpName (parent_container.Type));
2179 /// Performs checks for an explicit interface implementation. First it
2180 /// checks whether the `interface_type' is a base inteface implementation.
2181 /// Then it checks whether `name' exists in the interface type.
2183 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
2187 if (ifaces != null){
2188 foreach (TypeExpr t in ifaces){
2189 if (t.Type == interface_type){
2197 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
2208 string IMemberContainer.Name {
2214 Type IMemberContainer.Type {
2220 IMemberContainer IMemberContainer.Parent {
2222 return parent_container;
2226 MemberCache IMemberContainer.MemberCache {
2228 return member_cache;
2232 bool IMemberContainer.IsInterface {
2234 return this is Interface;
2238 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2240 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2242 if (GenericType != null)
2243 return TypeManager.FindMembers (GenericType, mt, new_bf,
2246 return FindMembers (mt, new_bf, null, null);
2250 // Operator pair checking
2253 class OperatorEntry {
2255 public Type ret_type;
2256 public Type type1, type2;
2258 public Operator.OpType ot;
2260 public OperatorEntry (int f, Operator o)
2264 ret_type = o.OperatorMethod.GetReturnType ();
2265 Type [] pt = o.OperatorMethod.ParameterTypes;
2269 ot = o.OperatorType;
2272 public override int GetHashCode ()
2274 return ret_type.GetHashCode ();
2277 public override bool Equals (object o)
2279 OperatorEntry other = (OperatorEntry) o;
2281 if (other.ret_type != ret_type)
2283 if (other.type1 != type1)
2285 if (other.type2 != type2)
2292 // Checks that some operators come in pairs:
2298 // They are matched based on the return type and the argument types
2300 void CheckPairedOperators ()
2302 Hashtable pairs = new Hashtable (null, null);
2303 Operator true_op = null;
2304 Operator false_op = null;
2305 bool has_equality_or_inequality = false;
2307 // Register all the operators we care about.
2308 foreach (Operator op in operators){
2311 switch (op.OperatorType){
2312 case Operator.OpType.Equality:
2314 has_equality_or_inequality = true;
2316 case Operator.OpType.Inequality:
2318 has_equality_or_inequality = true;
2321 case Operator.OpType.True:
2324 case Operator.OpType.False:
2328 case Operator.OpType.GreaterThan:
2330 case Operator.OpType.LessThan:
2333 case Operator.OpType.GreaterThanOrEqual:
2335 case Operator.OpType.LessThanOrEqual:
2341 OperatorEntry oe = new OperatorEntry (reg, op);
2343 object o = pairs [oe];
2347 oe = (OperatorEntry) o;
2352 if (true_op != null){
2353 if (false_op == null)
2354 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
2355 } else if (false_op != null)
2356 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
2359 // Look for the mistakes.
2361 foreach (DictionaryEntry de in pairs){
2362 OperatorEntry oe = (OperatorEntry) de.Key;
2369 case Operator.OpType.Equality:
2372 case Operator.OpType.Inequality:
2375 case Operator.OpType.GreaterThan:
2378 case Operator.OpType.LessThan:
2381 case Operator.OpType.GreaterThanOrEqual:
2384 case Operator.OpType.LessThanOrEqual:
2388 Report.Error (216, oe.op.Location,
2389 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2392 if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2393 MethodSignature equals_ms = new MethodSignature (
2394 "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2395 MethodSignature hash_ms = new MethodSignature (
2396 "GetHashCode", TypeManager.int32_type, new Type [0]);
2398 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2399 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2401 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2402 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2405 bool equals_ok = false;
2406 if ((equals_ml != null) && (equals_ml.Count == 1))
2407 equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2408 bool hash_ok = false;
2409 if ((hash_ml != null) && (hash_ml.Count == 1))
2410 hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2413 Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2414 "not override Object.Equals (object o)");
2416 Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2417 "not override Object.GetHashCode ()");
2423 public class Class : TypeContainer {
2425 // Modifiers allowed in a class declaration
2427 public const int AllowedModifiers =
2430 Modifiers.PROTECTED |
2431 Modifiers.INTERNAL |
2433 Modifiers.ABSTRACT |
2437 public Class (NamespaceEntry ns, TypeContainer parent, MemberName name,
2438 int mod, Attributes attrs, Location l)
2439 : base (ns, parent, name, attrs, l)
2443 if (parent.Parent == null)
2444 accmods = Modifiers.INTERNAL;
2446 accmods = Modifiers.PRIVATE;
2448 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2452 // FIXME: How do we deal with the user specifying a different
2455 public override TypeAttributes TypeAttr {
2457 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2462 public class Struct : TypeContainer {
2464 // Modifiers allowed in a struct declaration
2466 public const int AllowedModifiers =
2469 Modifiers.PROTECTED |
2470 Modifiers.INTERNAL |
2474 public Struct (NamespaceEntry ns, TypeContainer parent, MemberName name,
2475 int mod, Attributes attrs, Location l)
2476 : base (ns, parent, name, attrs, l)
2480 if (parent.Parent == null)
2481 accmods = Modifiers.INTERNAL;
2483 accmods = Modifiers.PRIVATE;
2485 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2487 this.ModFlags |= Modifiers.SEALED;
2491 // FIXME: Allow the user to specify a different set of attributes
2492 // in some cases (Sealed for example is mandatory for a class,
2493 // but what SequentialLayout can be changed
2495 public override TypeAttributes TypeAttr {
2497 return base.TypeAttr |
2498 TypeAttributes.SequentialLayout |
2499 TypeAttributes.Sealed |
2500 TypeAttributes.BeforeFieldInit;
2508 public class Interface : TypeContainer, IMemberContainer {
2510 /// Modifiers allowed in a class declaration
2512 public const int AllowedModifiers =
2515 Modifiers.PROTECTED |
2516 Modifiers.INTERNAL |
2520 public Interface (NamespaceEntry ns, TypeContainer parent, MemberName name,
2521 int mod, Attributes attrs, Location l)
2522 : base (ns, parent, name, attrs, l)
2526 if (parent.Parent == null)
2527 accmods = Modifiers.INTERNAL;
2529 accmods = Modifiers.PRIVATE;
2531 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2534 public override TypeAttributes TypeAttr {
2536 return base.TypeAttr |
2537 TypeAttributes.AutoLayout |
2538 TypeAttributes.Abstract |
2539 TypeAttributes.Interface;
2544 public abstract class MethodCore : MemberBase {
2545 public readonly Parameters Parameters;
2546 public readonly GenericMethod GenericMethod;
2547 protected Block block;
2548 protected DeclSpace ds;
2551 // Parameters, cached for semantic analysis.
2553 protected InternalParameters parameter_info;
2554 protected Type [] parameter_types;
2557 // This is set from TypeContainer.DefineMembers if this method overrides something.
2559 public bool OverridesSomething;
2561 // Whether this is an operator method.
2562 public bool IsOperator;
2564 public MethodCore (DeclSpace ds, Expression type, int mod, int allowed_mod,
2565 bool is_interface, MemberName name, Attributes attrs,
2566 Parameters parameters, Location loc)
2567 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
2569 Parameters = parameters;
2570 IsInterface = is_interface;
2572 this.GenericMethod = ds as GenericMethod;
2576 // Returns the System.Type array for the parameters of this method
2578 public Type [] ParameterTypes {
2580 return parameter_types;
2584 public InternalParameters ParameterInfo
2587 return parameter_info;
2591 public Block Block {
2601 protected virtual bool DoDefineParameters ()
2603 // Check if arguments were correct
2604 parameter_types = Parameters.GetParameterInfo (ds);
2605 if ((parameter_types == null) || !CheckParameters (ds, parameter_types))
2608 parameter_info = new InternalParameters (ds, Parameters);
2610 Parameter array_param = Parameters.ArrayParameter;
2611 if ((array_param != null) &&
2612 (!array_param.ParameterType.IsArray ||
2613 (array_param.ParameterType.GetArrayRank () != 1))) {
2614 Report.Error (225, Location, "params parameter has to be a single dimensional array");
2621 void error_425 (Type old, Type t, string name)
2623 Report.Error (425, Location,
2624 "The constraints of type parameter `{0}' " +
2625 "of method `{1}' must match the constraints for " +
2626 "type parameter `{2}' of method `{3}'",
2627 TypeManager.CSharpName (old), Name,
2628 TypeManager.CSharpName (t), name);
2631 protected override bool CheckGenericOverride (MethodInfo method, string name)
2633 ParameterData pd = Invocation.GetParameterData (method);
2635 for (int i = 0; i < ParameterTypes.Length; i++) {
2636 GenericConstraints ogc = pd.GenericConstraints (i);
2637 GenericConstraints gc = ParameterInfo.GenericConstraints (i);
2639 if ((gc == null) && (ogc == null))
2642 Type ot = pd.ParameterType (i);
2643 Type t = ParameterTypes [i];
2645 if (!((gc != null) && (ogc != null))) {
2646 error_425 (ot, t, name);
2650 if (gc.HasConstructor != ogc.HasConstructor) {
2651 error_425 (ot, t, name);
2655 if (ogc.HasClassConstraint != gc.HasClassConstraint) {
2656 error_425 (ot, t, name);
2660 if (ogc.HasClassConstraint &&
2661 !ogc.ClassConstraint.Equals (gc.ClassConstraint)) {
2662 error_425 (ot, t, name);
2666 Type[] oct = ogc.InterfaceConstraints;
2667 Type[] ct = gc.InterfaceConstraints;
2669 if (oct.Length != ct.Length) {
2670 error_425 (ot, t, name);
2674 for (int j = 0; j < oct.Length; j++)
2675 if (!oct [j].Equals (ct [j])) {
2676 error_425 (ot, t, name);
2684 protected override bool VerifyClsCompliance (DeclSpace ds)
2686 if (!base.VerifyClsCompliance (ds)) {
2687 if ((ModFlags & Modifiers.ABSTRACT) != 0 && IsExposedFromAssembly (ds) && ds.IsClsCompliaceRequired (ds)) {
2688 Report.Error_T (3011, Location, GetSignatureForError ());
2693 AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location);
2695 if (!AttributeTester.IsClsCompliant (MemberType)) {
2696 Report.Error_T (3002, Location, GetSignatureForError ());
2702 protected bool IsDuplicateImplementation (TypeContainer tc, MethodCore method)
2704 if ((method == this) || (method.Name != Name))
2707 Type[] param_types = method.ParameterTypes;
2708 if (param_types == null)
2711 if (param_types.Length != ParameterTypes.Length)
2714 int type_params = 0;
2715 if (GenericMethod != null)
2716 type_params = GenericMethod.CountTypeParameters;
2718 int m_type_params = 0;
2719 if (method.GenericMethod != null)
2720 m_type_params = method.GenericMethod.CountTypeParameters;
2722 if (type_params != m_type_params)
2728 Type[] infered_types = new Type [param_types.Length];
2729 may_unify = Invocation.InferTypeArguments (
2730 param_types, ParameterTypes, ref infered_types);
2733 infered_types = new Type [param_types.Length];
2734 may_unify = Invocation.InferTypeArguments (
2735 ParameterTypes, param_types, ref infered_types);
2738 for (int i = 0; i < param_types.Length; i++) {
2739 Type a = param_types [i];
2740 Type b = ParameterTypes [i];
2748 // Try to report 663: method only differs on out/ref
2750 ParameterData info = ParameterInfo;
2751 ParameterData other_info = method.ParameterInfo;
2752 for (int i = 0; i < info.Count; i++){
2753 if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
2754 Report.Error (663, Location,
2755 "Overload method only differs " +
2756 "in parameter modifier");
2761 Report.Error (111, Location,
2762 "Class `{0}' already defines a member called " +
2763 "`{1}' with the same parameter types",
2766 } else if (may_unify) {
2767 Report.Error (408, Location,
2768 "`{0}' cannot define overload members that " +
2769 "may unify for some type parameter substitutions",
2777 public CallingConventions GetCallingConvention (bool is_class)
2779 CallingConventions cc = 0;
2781 cc = Parameters.GetCallingConvention ();
2784 if ((ModFlags & Modifiers.STATIC) == 0)
2785 cc |= CallingConventions.HasThis;
2787 // FIXME: How is `ExplicitThis' used in C#?
2793 // The method's attributes are passed in because we need to extract
2794 // the "return:" attribute from there to apply on the return type
2796 static public void LabelParameters (EmitContext ec,
2798 Parameters parameters,
2799 Attributes method_attrs,
2803 // Define each type attribute (in/out/ref) and
2804 // the argument names.
2806 Parameter [] p = parameters.FixedParameters;
2809 MethodBuilder mb = null;
2810 ConstructorBuilder cb = null;
2812 if (builder is MethodBuilder)
2813 mb = (MethodBuilder) builder;
2815 cb = (ConstructorBuilder) builder;
2818 for (i = 0; i < p.Length; i++) {
2819 ParameterBuilder pb;
2820 ParameterAttributes par_attr = p [i].Attributes;
2823 pb = cb.DefineParameter (
2824 i + 1, par_attr, p [i].Name);
2826 pb = mb.DefineParameter (
2827 i + 1, par_attr, p [i].Name);
2829 Attributes attr = p [i].OptAttributes;
2831 Attribute.ApplyAttributes (ec, pb, pb, attr);
2833 if (par_attr == ParameterAttributes.Out){
2834 if (attr.Contains (TypeManager.in_attribute_type))
2835 Report.Error (36, loc,
2836 "Can not use [In] attribute on out parameter");
2842 if (parameters.ArrayParameter != null){
2843 ParameterBuilder pb;
2844 Parameter array_param = parameters.ArrayParameter;
2847 pb = cb.DefineParameter (
2848 i + 1, array_param.Attributes,
2851 pb = mb.DefineParameter (
2852 i + 1, array_param.Attributes,
2855 CustomAttributeBuilder a = new CustomAttributeBuilder (
2856 TypeManager.cons_param_array_attribute, new object [0]);
2858 pb.SetCustomAttribute (a);
2862 // And now for the return type attribute decoration
2864 ParameterBuilder ret_pb;
2865 Attributes ret_attrs = null;
2867 if (mb == null || method_attrs == null)
2870 foreach (AttributeSection asec in method_attrs.AttributeSections) {
2872 if (asec.Target != "return")
2875 if (ret_attrs == null)
2876 ret_attrs = new Attributes (asec);
2878 ret_attrs.AddAttributeSection (asec);
2881 if (ret_attrs != null) {
2883 ret_pb = mb.DefineParameter (0, ParameterAttributes.None, "");
2884 Attribute.ApplyAttributes (ec, ret_pb, ret_pb, ret_attrs);
2886 } catch (ArgumentOutOfRangeException) {
2889 ".NET SDK 1.0 does not permit setting custom attributes" +
2890 " on the return type of a method");
2896 public class Method : MethodCore, IIteratorContainer {
2897 public MethodBuilder MethodBuilder;
2898 public MethodData MethodData;
2901 /// Modifiers allowed in a class declaration
2903 const int AllowedModifiers =
2906 Modifiers.PROTECTED |
2907 Modifiers.INTERNAL |
2912 Modifiers.OVERRIDE |
2913 Modifiers.ABSTRACT |
2915 Modifiers.METHOD_YIELDS |
2918 const int AllowedInterfaceModifiers =
2922 // return_type can be "null" for VOID values.
2924 public Method (DeclSpace ds, Expression return_type, int mod, bool is_iface,
2925 MemberName name, Parameters parameters, Attributes attrs,
2927 : base (ds, return_type, mod,
2928 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
2929 is_iface, name, attrs, parameters, l)
2934 // Returns the `System.Type' for the ReturnType of this
2935 // function. Provides a nice cache. (used between semantic analysis
2936 // and actual code generation
2938 public Type GetReturnType ()
2943 public override string GetSignatureForError()
2945 return TypeManager.CSharpSignature (MethodBuilder);
2948 void DuplicateEntryPoint (MethodInfo b, Location location)
2952 "Program `" + CodeGen.FileName +
2953 "' has more than one entry point defined: `" +
2954 TypeManager.CSharpSignature(b) + "'");
2957 void Report28 (MethodInfo b)
2961 "`" + TypeManager.CSharpSignature(b) +
2962 "' has the wrong signature to be an entry point");
2965 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2967 if (b.ReturnType != TypeManager.void_type &&
2968 b.ReturnType != TypeManager.int32_type)
2971 if (pinfo.Count == 0)
2974 if (pinfo.Count > 1)
2977 Type t = pinfo.ParameterType(0);
2979 (t.GetArrayRank() == 1) &&
2980 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
2981 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2988 // Checks our base implementation if any
2990 protected override bool CheckBase (TypeContainer container)
2992 base.CheckBase (container);
2994 // Check whether arguments were correct.
2995 if (!DoDefineParameters ())
2998 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
3000 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
3003 // Check in our class for dups
3005 ArrayList ar = container.Methods;
3007 int arLen = ar.Count;
3009 for (int i = 0; i < arLen; i++) {
3010 Method m = (Method) ar [i];
3011 if (IsDuplicateImplementation (container, m))
3019 // Verify if the parent has a type with the same name, and then
3020 // check whether we have to create a new slot for it or not.
3022 Type ptype = container.TypeBuilder.BaseType;
3024 // ptype is only null for System.Object while compiling corlib.
3025 if (ptype != null) {
3028 // Explicit implementations do not have `parent' methods, however,
3029 // the member cache stores them there. Without this check, we get
3030 // an incorrect warning in corlib.
3032 if (! IsExplicitImpl) {
3033 parent_method = (MethodInfo)((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
3034 container.TypeBuilder, Name, ParameterTypes, false);
3037 if (parent_method != null) {
3038 string name = parent_method.DeclaringType.Name + "." +
3041 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
3044 if ((ModFlags & Modifiers.NEW) == 0) {
3045 Type parent_ret = TypeManager.TypeToCoreType (
3046 parent_method.ReturnType);
3048 if (!parent_ret.Equals (MemberType)) {
3050 508, Location, container.MakeName (Name) + ": cannot " +
3051 "change return type when overriding " +
3052 "inherited member " + name);
3057 if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
3058 WarningNotHiding (container);
3060 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3061 Report.Error (115, Location,
3062 container.MakeName (Name) +
3063 " no suitable methods found to override");
3066 } else if ((ModFlags & Modifiers.NEW) != 0)
3067 WarningNotHiding (container);
3075 public override bool Define (TypeContainer container)
3078 MethodBuilder mb = null;
3079 if (GenericMethod != null) {
3080 mb = container.TypeBuilder.DefineGenericMethod (Name, flags);
3081 if (!GenericMethod.Define (container, mb))
3083 decl = GenericMethod;
3087 if (!DoDefine (decl, container))
3090 if (!CheckBase (container))
3093 CallingConventions cc = GetCallingConvention (container is Class);
3095 MethodData = new MethodData (ds, this, null, MemberType,
3096 ParameterTypes, ParameterInfo, cc,
3097 OptAttributes, ModFlags, flags, true,
3100 if (!MethodData.Define (container))
3104 // Setup iterator if we are one
3106 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
3107 IteratorHandler ih = new IteratorHandler (
3108 Name, container, MemberType,
3109 ParameterTypes, ParameterInfo,
3110 ModFlags, Location);
3112 Block new_block = ih.Setup (block);
3113 if (new_block == null)
3118 MethodBuilder = MethodData.MethodBuilder;
3121 // This is used to track the Entry Point,
3123 if (Name == "Main" &&
3124 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
3125 (RootContext.MainClass == null ||
3126 RootContext.MainClass == container.TypeBuilder.FullName)){
3127 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
3128 if (RootContext.EntryPoint == null) {
3129 if (container.IsGeneric){
3130 Report.Error (-201, Location,
3131 "Entry point can not be defined in a generic class");
3134 RootContext.EntryPoint = MethodBuilder;
3135 RootContext.EntryPointLocation = Location;
3137 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
3138 DuplicateEntryPoint (MethodBuilder, Location);
3141 Report28(MethodBuilder);
3150 public override void Emit (TypeContainer container)
3152 MethodData.Emit (container, Block, this);
3153 base.Emit (container);
3158 void IIteratorContainer.SetYields ()
3160 ModFlags |= Modifiers.METHOD_YIELDS;
3163 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
3165 return IsIdentifierAndParamClsCompliant (ds, Name, MethodBuilder, parameter_types);
3169 public abstract class ConstructorInitializer {
3170 ArrayList argument_list;
3171 ConstructorInfo parent_constructor;
3172 Parameters parameters;
3175 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
3178 this.argument_list = argument_list;
3179 this.parameters = parameters;
3183 public ArrayList Arguments {
3185 return argument_list;
3189 public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
3191 Expression parent_constructor_group;
3194 ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
3196 if (argument_list != null){
3197 foreach (Argument a in argument_list){
3198 if (!a.Resolve (ec, loc))
3202 ec.CurrentBlock = null;
3204 if (this is ConstructorBaseInitializer) {
3205 if (ec.ContainerType.BaseType == null)
3208 t = ec.ContainerType.BaseType;
3209 if (ec.ContainerType.IsValueType) {
3210 Report.Error (522, loc,
3211 "structs cannot call base class constructors");
3215 t = ec.ContainerType;
3217 parent_constructor_group = Expression.MemberLookup (
3218 ec, t, null, t, ".ctor",
3219 MemberTypes.Constructor,
3220 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3223 if (parent_constructor_group == null){
3224 Report.Error (1501, loc,
3225 "Can not find a constructor for this argument list");
3229 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (
3230 ec, (MethodGroupExpr) parent_constructor_group, argument_list,
3233 if (parent_constructor == null){
3234 Report.Error (1501, loc,
3235 "Can not find a constructor for this argument list");
3239 if (parent_constructor == caller_builder){
3240 Report.Error (515, String.Format ("Constructor `{0}' can not call itself", TypeManager.CSharpSignature (caller_builder)));
3247 public void Emit (EmitContext ec)
3249 if (parent_constructor != null){
3250 ec.Mark (loc, false);
3252 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
3254 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
3259 public class ConstructorBaseInitializer : ConstructorInitializer {
3260 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
3261 base (argument_list, pars, l)
3266 public class ConstructorThisInitializer : ConstructorInitializer {
3267 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
3268 base (argument_list, pars, l)
3273 public class Constructor : MethodCore {
3274 public ConstructorBuilder ConstructorBuilder;
3275 public ConstructorInitializer Initializer;
3278 // Modifiers allowed for a constructor.
3280 public const int AllowedModifiers =
3282 Modifiers.PROTECTED |
3283 Modifiers.INTERNAL |
3289 bool has_compliant_args = false;
3291 // The spec claims that static is not permitted, but
3292 // my very own code has static constructors.
3294 public Constructor (DeclSpace ds, string name, int mod, Parameters args,
3295 ConstructorInitializer init, Location l)
3296 : base (ds, null, mod, AllowedModifiers, false,
3297 new MemberName (name), null, args, l)
3302 public override string GetSignatureForError()
3304 return TypeManager.CSharpSignature (ConstructorBuilder);
3307 public bool HasCompliantArgs {
3309 return has_compliant_args;
3314 // Returns true if this is a default constructor
3316 public bool IsDefault ()
3318 if ((ModFlags & Modifiers.STATIC) != 0)
3319 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3320 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
3323 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3324 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
3325 (Initializer is ConstructorBaseInitializer) &&
3326 (Initializer.Arguments == null);
3329 protected override bool CheckBase (TypeContainer container)
3331 base.CheckBase (container);
3333 // Check whether arguments were correct.
3334 if (!DoDefineParameters ())
3337 if ((ModFlags & Modifiers.STATIC) != 0)
3340 if (container is Struct && ParameterTypes.Length == 0) {
3341 Report.Error (568, Location,
3342 "Structs can not contain explicit parameterless " +
3348 // Check in our class for dups
3350 ArrayList ar = container.InstanceConstructors;
3352 int arLen = ar.Count;
3354 for (int i = 0; i < arLen; i++) {
3355 Constructor m = (Constructor) ar [i];
3356 if (IsDuplicateImplementation (container, m))
3365 // Creates the ConstructorBuilder
3367 public override bool Define (TypeContainer container)
3369 MethodAttributes ca = (MethodAttributes.RTSpecialName |
3370 MethodAttributes.SpecialName);
3372 if ((ModFlags & Modifiers.STATIC) != 0){
3373 ca |= MethodAttributes.Static | MethodAttributes.Private;
3375 ca |= MethodAttributes.HideBySig;
3377 if ((ModFlags & Modifiers.PUBLIC) != 0)
3378 ca |= MethodAttributes.Public;
3379 else if ((ModFlags & Modifiers.PROTECTED) != 0){
3380 if ((ModFlags & Modifiers.INTERNAL) != 0)
3381 ca |= MethodAttributes.FamORAssem;
3383 ca |= MethodAttributes.Family;
3384 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
3385 ca |= MethodAttributes.Assembly;
3386 else if (IsDefault ())
3387 ca |= MethodAttributes.Public;
3389 ca |= MethodAttributes.Private;
3392 // Check if arguments were correct.
3393 if (!CheckBase (container))
3396 ConstructorBuilder = container.TypeBuilder.DefineConstructor (
3397 ca, GetCallingConvention (container is Class), ParameterTypes);
3399 if ((ModFlags & Modifiers.UNSAFE) != 0)
3400 ConstructorBuilder.InitLocals = false;
3403 // HACK because System.Reflection.Emit is lame
3405 TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes);
3413 public override void Emit (TypeContainer container)
3415 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
3416 EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
3419 // extern methods have no bodies
3421 if ((ModFlags & Modifiers.EXTERN) != 0) {
3422 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
3424 179, Location, "External constructor `" +
3425 TypeManager.CSharpSignature (ConstructorBuilder) +
3426 "' can not have a body");
3429 } else if (block == null) {
3431 501, Location, "Constructor `" +
3432 TypeManager.CSharpSignature (ConstructorBuilder) +
3433 "' must declare a body since it is not marked extern");
3437 if ((ModFlags & Modifiers.STATIC) == 0){
3438 if (container is Class && Initializer == null)
3439 Initializer = new ConstructorBaseInitializer (
3440 null, Parameters.EmptyReadOnlyParameters, Location);
3444 // Spec mandates that Initializers will not have
3448 if (Initializer != null && !Initializer.Resolve (ConstructorBuilder, ec))
3450 ec.IsStatic = false;
3453 MethodCore.LabelParameters (ec, ConstructorBuilder,
3454 Parameters, OptAttributes, Location);
3456 SymbolWriter sw = CodeGen.SymbolWriter;
3457 bool generate_debugging = false;
3459 if ((sw != null) && (block != null) &&
3460 !Location.IsNull (Location) &&
3461 !Location.IsNull (block.EndLocation) &&
3462 (Location.SymbolDocument != null)) {
3463 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
3465 generate_debugging = true;
3469 // Classes can have base initializers and instance field initializers.
3471 if (container is Class){
3472 if ((ModFlags & Modifiers.STATIC) == 0){
3475 // If we use a "this (...)" constructor initializer, then
3476 // do not emit field initializers, they are initialized in the other constructor
3478 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
3479 container.EmitFieldInitializers (ec);
3482 if (Initializer != null)
3483 Initializer.Emit (ec);
3485 if ((ModFlags & Modifiers.STATIC) != 0)
3486 container.EmitFieldInitializers (ec);
3488 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes);
3490 // If this is a non-static `struct' constructor and doesn't have any
3491 // initializer, it must initialize all of the struct's fields.
3492 if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
3493 Block.AddThisVariable (container, Location);
3495 ec.EmitTopBlock (block, ParameterInfo, Location);
3497 if (generate_debugging)
3500 base.Emit (container);
3505 // For constructors is needed to test only parameters
3506 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
3508 if (parameter_types == null || parameter_types.Length == 0)
3511 TypeContainer tc = ds as TypeContainer;
3513 for (int i = 0; i < tc.InstanceConstructors.Count; i++) {
3514 Constructor c = (Constructor) tc.InstanceConstructors [i];
3516 if (c == this || c.ParameterTypes.Length == 0)
3519 if (!c.IsClsCompliaceRequired (ds))
3522 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, c.ParameterTypes)) {
3523 Report.Error_T (3006, Location, GetSignatureForError ());
3528 if (tc.TypeBuilder.BaseType == null)
3531 DeclSpace temp_ds = TypeManager.LookupDeclSpace (tc.TypeBuilder.BaseType);
3532 if (temp_ds != null)
3533 return IsIdentifierClsCompliant (temp_ds);
3535 MemberInfo[] ml = tc.TypeBuilder.BaseType.FindMembers (MemberTypes.Constructor, BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance, null, null);
3536 // Skip parameter-less ctor
3540 foreach (ConstructorInfo ci in ml) {
3541 object[] cls_attribute = ci.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false);
3542 if (cls_attribute.Length == 1 && (!((CLSCompliantAttribute)cls_attribute[0]).IsCompliant))
3545 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, TypeManager.GetArgumentTypes (ci))) {
3546 Report.Error_T (3006, Location, GetSignatureForError ());
3554 protected override bool VerifyClsCompliance (DeclSpace ds)
3556 if (!base.VerifyClsCompliance (ds)) {
3560 if (ds.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
3561 foreach (Type param in parameter_types) {
3562 if (param.IsArray) {
3567 has_compliant_args = true;
3574 // Encapsulates most of the Method's state
3576 public class MethodData {
3578 // The return type of this method
3580 public readonly Type ReturnType;
3581 public readonly Type[] ParameterTypes;
3582 public readonly GenericMethod GenericMethod;
3583 public readonly InternalParameters ParameterInfo;
3584 public readonly CallingConventions CallingConventions;
3585 public readonly Attributes OptAttributes;
3586 public readonly Location Location;
3589 // Are we implementing an interface ?
3591 public bool IsImplementing = false;
3596 protected DeclSpace ds;
3597 protected MemberBase member;
3598 protected int modifiers;
3599 protected MethodAttributes flags;
3600 protected bool is_method;
3601 protected string accessor_name;
3602 protected Type declaring_type;
3605 // It can either hold a string with the condition, or an arraylist of conditions.
3606 object conditionals;
3609 MethodBuilder builder = null;
3610 public MethodBuilder MethodBuilder {
3616 public Type DeclaringType {
3618 return declaring_type;
3622 public MethodData (DeclSpace ds, MemberBase member, string name, Type return_type,
3623 Type [] parameter_types, InternalParameters parameters,
3624 CallingConventions cc, Attributes opt_attrs,
3625 int modifiers, MethodAttributes flags, bool is_method)
3628 this.member = member;
3629 this.accessor_name = name;
3630 this.ReturnType = return_type;
3631 this.ParameterTypes = parameter_types;
3632 this.ParameterInfo = parameters;
3633 this.CallingConventions = cc;
3634 this.OptAttributes = opt_attrs;
3635 this.modifiers = modifiers;
3637 this.is_method = is_method;
3638 this.Location = member.Location;
3639 this.conditionals = null;
3642 public MethodData (DeclSpace ds, MemberBase member, string name, Type return_type,
3643 Type [] parameter_types, InternalParameters parameters,
3644 CallingConventions cc, Attributes opt_attrs,
3645 int modifiers, MethodAttributes flags, bool is_method,
3646 MethodBuilder builder, GenericMethod generic)
3647 : this (ds, member, name, return_type, parameter_types, parameters,
3648 cc, opt_attrs, modifiers, flags, is_method)
3650 this.builder = builder;
3651 this.GenericMethod = generic;
3657 Attribute dllimport_attribute = null;
3658 string obsolete = null;
3659 bool obsolete_error = false;
3661 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
3663 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
3666 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
3667 if (asec.Attributes == null)
3670 foreach (Attribute a in asec.Attributes) {
3671 if (a.Name == "Conditional") {
3672 if (!ApplyConditionalAttribute (a))
3674 } else if (a.Name == "Obsolete") {
3675 if (!ApplyObsoleteAttribute (a))
3677 } else if (a.Name.IndexOf ("DllImport") != -1) {
3679 a.Type = TypeManager.dllimport_type;
3680 Attribute.Error_AttributeNotValidForElement (a, Location);
3683 if (!ApplyDllImportAttribute (a))
3693 // Applies the `DllImport' attribute to the method.
3695 protected virtual bool ApplyDllImportAttribute (Attribute a)
3697 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3698 if ((modifiers & extern_static) != extern_static) {
3699 Report.Error (601, Location,
3700 "The DllImport attribute must be specified on a method " +
3701 "marked `static' and `extern'.");
3705 flags |= MethodAttributes.PinvokeImpl;
3706 dllimport_attribute = a;
3711 // Applies the `Obsolete' attribute to the method.
3713 protected virtual bool ApplyObsoleteAttribute (Attribute a)
3715 if (obsolete != null) {
3716 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
3720 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
3721 return obsolete != null;
3725 // Applies the `Conditional' attribute to the method.
3727 protected virtual bool ApplyConditionalAttribute (Attribute a)
3729 // The Conditional attribute is only valid on methods.
3731 Attribute.Error_AttributeNotValidForElement (a, Location);
3735 string condition = a.Conditional_GetConditionName ();
3737 if (condition == null)
3740 if (ReturnType != TypeManager.void_type) {
3741 Report.Error (578, Location,
3742 "Conditional not valid on `" + member.Name + "' " +
3743 "because its return type is not void");
3747 if ((modifiers & Modifiers.OVERRIDE) != 0) {
3748 Report.Error (243, Location,
3749 "Conditional not valid on `" + member.Name + "' " +
3750 "because it is an override method");
3754 if (member.IsExplicitImpl) {
3755 Report.Error (577, Location,
3756 "Conditional not valid on `" + member.Name + "' " +
3757 "because it is an explicit interface implementation");
3761 if (IsImplementing) {
3762 Report.Error (623, Location,
3763 "Conditional not valid on `" + member.Name + "' " +
3764 "because it is an interface method");
3769 // The likelyhood that the conditional will be more than 1 is very slim
3771 if (conditionals == null)
3772 conditionals = condition;
3773 else if (conditionals is string){
3774 string s = (string) conditionals;
3775 conditionals = new ArrayList ();
3776 ((ArrayList)conditionals).Add (s);
3778 ((ArrayList)conditionals).Add (condition);
3784 // Checks whether this method should be ignored due to its Conditional attributes.
3786 bool ShouldIgnore (Location loc)
3788 // When we're overriding a virtual method, we implicitly inherit the
3789 // Conditional attributes from our parent.
3790 if (member.ParentMethod != null) {
3791 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
3792 member.ParentMethod, loc);
3794 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
3798 if (conditionals != null){
3799 if (conditionals is string){
3800 if (RootContext.AllDefines [conditionals] == null)
3803 foreach (string condition in (ArrayList) conditionals)
3804 if (RootContext.AllDefines [condition] == null)
3812 // Returns the TypeManager.MethodFlags for this method.
3813 // This emits an error 619 / warning 618 if the method is obsolete.
3814 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
3816 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
3818 TypeManager.MethodFlags flags = 0;
3820 if (obsolete != null) {
3821 if (obsolete_error) {
3822 Report.Error (619, loc, "Method `" + member.Name +
3823 "' is obsolete: `" + obsolete + "'");
3824 return TypeManager.MethodFlags.IsObsoleteError;
3826 Report.Warning (618, loc, "Method `" + member.Name +
3827 "' is obsolete: `" + obsolete + "'");
3829 flags |= TypeManager.MethodFlags.IsObsolete;
3832 if (ShouldIgnore (loc))
3833 flags |= TypeManager.MethodFlags.ShouldIgnore;
3838 public virtual bool Define (TypeContainer container)
3840 MethodInfo implementing = null;
3841 string method_name, name, prefix;
3843 if (OptAttributes != null)
3844 if (!ApplyAttributes (OptAttributes, is_method))
3847 if (member.IsExplicitImpl)
3848 prefix = member.InterfaceType.FullName + ".";
3852 if (accessor_name != null)
3853 name = accessor_name + "_" + member.ShortName;
3855 name = member.ShortName;
3856 method_name = prefix + name;
3858 if (container.Pending != null){
3859 if (member is Indexer)
3860 implementing = container.Pending.IsInterfaceIndexer (
3861 member.InterfaceType, ReturnType, ParameterTypes);
3863 implementing = container.Pending.IsInterfaceMethod (
3864 member.InterfaceType, name, ReturnType, ParameterTypes);
3866 if (member.InterfaceType != null && implementing == null){
3867 Report.Error (539, Location, "'{0}' in explicit interface declaration is not an interface", method_name);
3873 // For implicit implementations, make sure we are public, for
3874 // explicit implementations, make sure we are private.
3876 if (implementing != null){
3878 // Setting null inside this block will trigger a more
3879 // verbose error reporting for missing interface implementations
3881 // The "candidate" function has been flagged already
3882 // but it wont get cleared
3884 if (member.IsExplicitImpl){
3885 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3886 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3887 implementing = null;
3889 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
3890 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
3892 // If this is an interface method implementation,
3893 // check for public accessibility
3895 implementing = null;
3896 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
3897 // We may never be private.
3898 implementing = null;
3899 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
3901 // We may be protected if we're overriding something.
3903 implementing = null;
3908 // Static is not allowed
3910 if ((modifiers & Modifiers.STATIC) != 0){
3911 implementing = null;
3912 Modifiers.Error_InvalidModifier (Location, "static");
3917 // If implementing is still valid, set flags
3919 if (implementing != null){
3921 // When implementing interface methods, set NewSlot
3922 // unless, we are overwriting a method.
3924 if (implementing.DeclaringType.IsInterface){
3925 if ((modifiers & Modifiers.OVERRIDE) == 0)
3926 flags |= MethodAttributes.NewSlot;
3929 MethodAttributes.Virtual |
3930 MethodAttributes.HideBySig;
3932 // Set Final unless we're virtual, abstract or already overriding a method.
3933 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
3934 flags |= MethodAttributes.Final;
3936 // Get the method name from the explicit interface.
3937 if (member.InterfaceType != null) {
3938 name = implementing.Name;
3939 method_name = prefix + name;
3942 IsImplementing = true;
3945 ec = new EmitContext (
3946 container, ds, Location, null, ReturnType, modifiers, false);
3949 // Create the MethodBuilder for the method
3951 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3952 if ((modifiers & Modifiers.STATIC) == 0) {
3953 Report.Error (601, Location,
3954 "The DllImport attribute must be specified on " +
3955 "a method marked 'static' and 'extern'.");
3958 builder = dllimport_attribute.DefinePInvokeMethod (
3959 ec, container.TypeBuilder, method_name, flags,
3960 ReturnType, ParameterTypes);
3961 } else if (builder == null)
3962 builder = container.TypeBuilder.DefineMethod (
3963 method_name, flags, CallingConventions,
3964 ReturnType, ParameterTypes);
3966 builder.SetGenericMethodSignature (
3967 flags, CallingConventions,
3968 ReturnType, ParameterTypes);
3970 if (builder == null)
3973 if (GenericMethod != null) {
3974 if (!GenericMethod.DefineType (ec, builder))
3978 if (container.CurrentType != null)
3979 declaring_type = container.CurrentType.ResolveType (ec);
3981 declaring_type = container.TypeBuilder;
3983 if ((modifiers & Modifiers.UNSAFE) != 0)
3984 builder.InitLocals = false;
3986 if (IsImplementing){
3988 // clear the pending implemntation flag
3990 if (member is Indexer) {
3991 container.Pending.ImplementIndexer (
3992 member.InterfaceType, builder, ReturnType,
3993 ParameterTypes, true);
3995 container.Pending.ImplementMethod (
3996 member.InterfaceType, name, ReturnType,
3997 ParameterTypes, member.IsExplicitImpl);
3999 if (member.IsExplicitImpl)
4000 container.TypeBuilder.DefineMethodOverride (
4001 builder, implementing);
4005 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
4006 Report.Error (111, Location,
4007 "Class `" + container.Name +
4008 "' already contains a definition with the " +
4009 "same return value and parameter types as the " +
4010 "'get' method of property `" + member.Name + "'");
4014 TypeManager.AddMethod (builder, this);
4022 public virtual void Emit (TypeContainer container, Block block, object kind)
4027 if ((flags & MethodAttributes.PinvokeImpl) == 0)
4028 ig = builder.GetILGenerator ();
4032 ec = new EmitContext (container, ds, Location, ig, ReturnType, modifiers, false);
4034 if (OptAttributes != null)
4035 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes);
4037 if (member is MethodCore)
4038 MethodCore.LabelParameters (ec, MethodBuilder,
4039 ((MethodCore) member).Parameters,
4043 SymbolWriter sw = CodeGen.SymbolWriter;
4046 // abstract or extern methods have no bodies
4048 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
4049 if (block == null) {
4050 if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0) &&
4051 !Location.IsNull (Location) &&
4052 (Location.SymbolDocument != null)) {
4053 sw.OpenMethod (container, MethodBuilder, Location, Location);
4061 // abstract or extern methods have no bodies.
4063 if ((modifiers & Modifiers.ABSTRACT) != 0)
4065 500, Location, "Abstract method `" +
4066 TypeManager.CSharpSignature (builder) +
4067 "' can not have a body");
4069 if ((modifiers & Modifiers.EXTERN) != 0)
4071 179, Location, "External method `" +
4072 TypeManager.CSharpSignature (builder) +
4073 "' can not have a body");
4079 // Methods must have a body unless they're extern or abstract
4081 if (block == null) {
4083 501, Location, "Method `" +
4084 TypeManager.CSharpSignature (builder) +
4085 "' must declare a body since it is not marked " +
4086 "abstract or extern");
4091 // Handle destructors specially
4093 // FIXME: This code generates buggy code
4095 if ((sw != null) && !Location.IsNull (Location) &&
4096 !Location.IsNull (block.EndLocation) &&
4097 (Location.SymbolDocument != null)) {
4098 sw.OpenMethod (container, MethodBuilder, Location, block.EndLocation);
4100 if (member is Destructor)
4101 EmitDestructor (ec, block);
4103 ec.EmitTopBlock (block, ParameterInfo, Location);
4107 if (member is Destructor)
4108 EmitDestructor (ec, block);
4110 ec.EmitTopBlock (block, ParameterInfo, Location);
4114 void EmitDestructor (EmitContext ec, Block block)
4116 ILGenerator ig = ec.ig;
4118 Label finish = ig.DefineLabel ();
4120 block.SetDestructor ();
4122 ig.BeginExceptionBlock ();
4123 ec.ReturnLabel = finish;
4124 ec.HasReturnLabel = true;
4125 ec.EmitTopBlock (block, null, Location);
4127 // ig.MarkLabel (finish);
4128 ig.BeginFinallyBlock ();
4130 if (ec.ContainerType.BaseType != null) {
4131 Expression member_lookup = Expression.MemberLookup (
4132 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
4133 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, Location);
4135 if (member_lookup != null){
4136 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
4138 ig.Emit (OpCodes.Ldarg_0);
4139 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
4143 ig.EndExceptionBlock ();
4144 //ig.MarkLabel (ec.ReturnLabel);
4145 ig.Emit (OpCodes.Ret);
4149 public class Destructor : Method {
4151 public Destructor (DeclSpace ds, Expression return_type, int mod, string name,
4152 Parameters parameters, Attributes attrs, Location l)
4153 : base (ds, return_type, mod, false, new MemberName (name),
4154 parameters, attrs, l)
4159 abstract public class MemberBase : MemberCore {
4160 public Expression Type;
4162 protected MethodAttributes flags;
4164 protected readonly int explicit_mod_flags;
4167 // The "short" name of this property / indexer / event. This is the
4168 // name without the explicit interface.
4170 public string ShortName;
4173 // The type of this property / indexer / event
4175 public Type MemberType;
4178 // If true, this is an explicit interface implementation
4180 public bool IsExplicitImpl = false;
4183 // The name of the interface we are explicitly implementing
4185 public Expression ExplicitInterfaceName = null;
4188 // Whether this is an interface member.
4190 public bool IsInterface;
4193 // If true, the interface type we are explicitly implementing
4195 public Type InterfaceType = null;
4198 // The method we're overriding if this is an override method.
4200 protected MethodInfo parent_method = null;
4201 public MethodInfo ParentMethod {
4203 return parent_method;
4208 // The constructor is only exposed to our children
4210 protected MemberBase (Expression type, int mod, int allowed_mod, int def_mod,
4211 MemberName name, Attributes attrs, Location loc)
4212 : base (name, attrs, loc)
4214 explicit_mod_flags = mod;
4216 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
4219 protected virtual bool CheckBase (TypeContainer container)
4221 if ((container is Struct) || (RootContext.WarningLevel > 3)){
4222 if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
4223 if (container is Struct){
4224 Report.Error (666, Location, "Protected member in struct declaration");
4227 Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
4233 protected void WarningNotHiding (TypeContainer parent)
4237 "The member " + parent.MakeName (Name) + " does not hide an " +
4238 "inherited member. The keyword new is not required");
4242 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
4246 // FIXME: report the old/new permissions?
4249 507, Location, parent.MakeName (Name) +
4250 ": can't change the access modifiers when overriding inherited " +
4251 "member `" + name + "'");
4254 protected abstract bool CheckGenericOverride (MethodInfo method, string name);
4257 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
4258 // that have been defined.
4260 // `name' is the user visible name for reporting errors (this is used to
4261 // provide the right name regarding method names and properties)
4263 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
4264 MethodInfo mb, string name)
4268 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4269 if (!(mb.IsAbstract || mb.IsVirtual)){
4271 506, Location, parent.MakeName (Name) +
4272 ": cannot override inherited member `" +
4273 name + "' because it is not " +
4274 "virtual, abstract or override");
4278 // Now we check that the overriden method is not final
4281 // This happens when implementing interface methods.
4282 if (mb.IsHideBySig && mb.IsVirtual) {
4284 506, Location, parent.MakeName (Name) +
4285 ": cannot override inherited member `" +
4286 name + "' because it is not " +
4287 "virtual, abstract or override");
4289 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
4290 "override inherited member `" + name +
4291 "' because it is sealed.");
4296 // Check that the constraints match when overriding a
4300 if (!CheckGenericOverride (mb, name))
4304 // Check that the permissions are not being changed
4306 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
4307 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
4310 // special case for "protected internal"
4313 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4315 // when overriding protected internal, the method can be declared
4316 // protected internal only within the same assembly
4319 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4320 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
4322 // assemblies differ - report an error
4325 Error_CannotChangeAccessModifiers (parent, mb, name);
4327 } else if (thisp != parentp) {
4329 // same assembly, but other attributes differ - report an error
4332 Error_CannotChangeAccessModifiers (parent, mb, name);
4335 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
4337 // if it's not "protected internal", it must be "protected"
4340 Error_CannotChangeAccessModifiers (parent, mb, name);
4342 } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
4344 // protected within the same assembly - an error
4346 Error_CannotChangeAccessModifiers (parent, mb, name);
4348 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
4349 (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
4351 // protected ok, but other attributes differ - report an error
4353 Error_CannotChangeAccessModifiers (parent, mb, name);
4357 if (thisp != parentp){
4358 Error_CannotChangeAccessModifiers (parent, mb, name);
4364 if (mb.IsVirtual || mb.IsAbstract){
4365 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4366 if (Name != "Finalize"){
4368 114, 2, Location, parent.MakeName (Name) +
4369 " hides inherited member `" + name +
4370 "'. To make the current member override that " +
4371 "implementation, add the override keyword, " +
4372 "otherwise use the new keyword");
4373 ModFlags |= Modifiers.NEW;
4377 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4378 if (Name != "Finalize"){
4380 108, 1, Location, "The keyword new is required on " +
4381 parent.MakeName (Name) + " because it hides " +
4382 "inherited member `" + name + "'");
4383 ModFlags |= Modifiers.NEW;
4391 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
4395 foreach (Type partype in parameters){
4396 if (partype.IsPointer){
4399 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
4403 if (ds.AsAccessible (partype, ModFlags))
4406 if (this is Indexer)
4407 Report.Error (55, Location,
4408 "Inconsistent accessibility: parameter type `" +
4409 TypeManager.CSharpName (partype) + "' is less " +
4410 "accessible than indexer `" + Name + "'");
4411 else if ((this is Method) && ((Method) this).IsOperator)
4412 Report.Error (57, Location,
4413 "Inconsistent accessibility: parameter type `" +
4414 TypeManager.CSharpName (partype) + "' is less " +
4415 "accessible than operator `" + Name + "'");
4417 Report.Error (51, Location,
4418 "Inconsistent accessibility: parameter type `" +
4419 TypeManager.CSharpName (partype) + "' is less " +
4420 "accessible than method `" + Name + "'");
4427 protected virtual bool DoDefine (DeclSpace decl, TypeContainer container)
4433 ModFlags = Modifiers.PUBLIC |
4434 Modifiers.ABSTRACT |
4437 flags = MethodAttributes.Public |
4438 MethodAttributes.Abstract |
4439 MethodAttributes.HideBySig |
4440 MethodAttributes.NewSlot |
4441 MethodAttributes.Virtual;
4443 if (!container.MethodModifiersValid (ModFlags, Name, Location))
4446 flags = Modifiers.MethodAttr (ModFlags);
4449 // Lookup Type, verify validity
4450 MemberType = decl.ResolveType (Type, false, Location);
4451 if (MemberType == null)
4454 if ((container.ModFlags & Modifiers.SEALED) != 0){
4455 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
4456 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
4461 // verify accessibility
4462 if (!container.AsAccessible (MemberType, ModFlags)) {
4463 if (this is Property)
4464 Report.Error (53, Location,
4465 "Inconsistent accessibility: property type `" +
4466 TypeManager.CSharpName (MemberType) + "' is less " +
4467 "accessible than property `" + Name + "'");
4468 else if (this is Indexer)
4469 Report.Error (54, Location,
4470 "Inconsistent accessibility: indexer return type `" +
4471 TypeManager.CSharpName (MemberType) + "' is less " +
4472 "accessible than indexer `" + Name + "'");
4473 else if (this is Method) {
4474 if (((Method) this).IsOperator)
4475 Report.Error (56, Location,
4476 "Inconsistent accessibility: return type `" +
4477 TypeManager.CSharpName (MemberType) + "' is less " +
4478 "accessible than operator `" + Name + "'");
4480 Report.Error (50, Location,
4481 "Inconsistent accessibility: return type `" +
4482 TypeManager.CSharpName (MemberType) + "' is less " +
4483 "accessible than method `" + Name + "'");
4485 Report.Error (52, Location,
4486 "Inconsistent accessibility: field type `" +
4487 TypeManager.CSharpName (MemberType) + "' is less " +
4488 "accessible than field `" + Name + "'");
4492 if (MemberType.IsPointer && !UnsafeOK (container))
4496 // Check for explicit interface implementation
4498 if (MemberName.TypeName != null) {
4499 ExplicitInterfaceName = MemberName.TypeName.GetTypeExpression (Location);
4500 ShortName = MemberName.Name;
4504 if (ExplicitInterfaceName != null) {
4505 InterfaceType = container.ResolveType (
4506 ExplicitInterfaceName, false, Location);
4507 if (InterfaceType == null)
4510 if (InterfaceType.IsClass) {
4511 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
4515 // Compute the full name that we need to export.
4516 Name = InterfaceType.FullName + "." + ShortName;
4518 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
4521 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
4523 IsExplicitImpl = true;
4525 IsExplicitImpl = false;
4530 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
4532 return IsIdentifierAndParamClsCompliant (ds, Name, null, null);
4535 protected override bool VerifyClsCompliance(DeclSpace ds)
4537 if (base.VerifyClsCompliance (ds)) {
4541 if (IsInterface && HasClsCompliantAttribute (ds) && ds.IsClsCompliaceRequired (ds)) {
4542 Report.Error_T (3010, Location, GetSignatureForError ());
4551 // Fields and Events both generate FieldBuilders, we use this to share
4552 // their common bits. This is also used to flag usage of the field
4554 abstract public class FieldBase : MemberBase {
4555 public FieldBuilder FieldBuilder;
4556 public Status status;
4559 public enum Status : byte { ASSIGNED = 1, USED = 2 }
4562 // The constructor is only exposed to our children
4564 protected FieldBase (Expression type, int mod, int allowed_mod, MemberName name,
4565 object init, Attributes attrs, Location loc)
4566 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
4572 // Whether this field has an initializer.
4574 public bool HasInitializer {
4576 return init != null;
4580 protected readonly Object init;
4582 Expression init_expr;
4583 bool init_expr_initialized = false;
4585 protected override bool CheckGenericOverride (MethodInfo method, string name)
4591 // Resolves and returns the field initializer.
4593 public Expression GetInitializerExpression (EmitContext ec)
4595 if (init_expr_initialized)
4599 if (init is Expression)
4600 e = (Expression) init;
4602 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
4604 ec.IsFieldInitializer = true;
4605 e = e.DoResolve (ec);
4606 ec.IsFieldInitializer = false;
4609 init_expr_initialized = true;
4614 public override string GetSignatureForError ()
4616 return TypeManager.GetFullNameSignature (FieldBuilder);
4619 protected override bool VerifyClsCompliance (DeclSpace ds)
4621 if (!base.VerifyClsCompliance (ds))
4624 if (FieldBuilder == null) {
4628 if (!AttributeTester.IsClsCompliant (FieldBuilder.FieldType)) {
4629 Report.Error_T (3003, Location, GetSignatureForError ());
4635 public void SetAssigned ()
4637 status |= Status.ASSIGNED;
4642 // The Field class is used to represents class/struct fields during parsing.
4644 public class Field : FieldBase {
4646 // Modifiers allowed in a class declaration
4648 const int AllowedModifiers =
4651 Modifiers.PROTECTED |
4652 Modifiers.INTERNAL |
4655 Modifiers.VOLATILE |
4659 public Field (Expression type, int mod, string name, Object expr_or_array_init,
4660 Attributes attrs, Location loc)
4661 : base (type, mod, AllowedModifiers, new MemberName (name),
4662 expr_or_array_init, attrs, loc)
4666 public override bool Define (TypeContainer container)
4668 Type t = container.ResolveType (Type, false, Location);
4673 CheckBase (container);
4675 if (!container.AsAccessible (t, ModFlags)) {
4676 Report.Error (52, Location,
4677 "Inconsistent accessibility: field type `" +
4678 TypeManager.CSharpName (t) + "' is less " +
4679 "accessible than field `" + Name + "'");
4683 if (t.IsPointer && !UnsafeOK (container))
4686 if (RootContext.WarningLevel > 1){
4687 Type ptype = container.TypeBuilder.BaseType;
4689 // ptype is only null for System.Object while compiling corlib.
4691 TypeContainer.FindMembers (
4692 ptype, MemberTypes.Method,
4693 BindingFlags.Public |
4694 BindingFlags.Static | BindingFlags.Instance,
4695 System.Type.FilterName, Name);
4699 if ((ModFlags & Modifiers.VOLATILE) != 0){
4703 if (TypeManager.IsEnumType (vt))
4704 vt = TypeManager.EnumToUnderlying (t);
4706 if (!((vt == TypeManager.bool_type) ||
4707 (vt == TypeManager.sbyte_type) ||
4708 (vt == TypeManager.byte_type) ||
4709 (vt == TypeManager.short_type) ||
4710 (vt == TypeManager.ushort_type) ||
4711 (vt == TypeManager.int32_type) ||
4712 (vt == TypeManager.uint32_type) ||
4713 (vt == TypeManager.char_type) ||
4714 (vt == TypeManager.float_type))){
4716 677, Location, container.MakeName (Name) +
4717 " A volatile field can not be of type `" +
4718 TypeManager.CSharpName (vt) + "'");
4723 if ((ModFlags & Modifiers.READONLY) != 0){
4726 "A field can not be both volatile and readonly");
4731 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
4733 if (container is Struct &&
4734 ((fa & FieldAttributes.Static) == 0) &&
4735 t == container.TypeBuilder &&
4736 !TypeManager.IsBuiltinType (t)){
4737 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name +
4738 "' causes a cycle in the structure layout");
4743 FieldBuilder = container.TypeBuilder.DefineField (
4744 Name, t, Modifiers.FieldAttr (ModFlags));
4746 TypeManager.RegisterFieldBase (FieldBuilder, this);
4748 catch (ArgumentException) {
4749 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
4756 public override void Emit (TypeContainer tc)
4758 if (OptAttributes != null) {
4759 EmitContext ec = new EmitContext (tc, Location, null, FieldBuilder.FieldType, ModFlags);
4760 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes);
4768 // `set' and `get' accessors are represented with an Accessor.
4770 public class Accessor {
4772 // Null if the accessor is empty, or a Block if not
4775 public Attributes OptAttributes;
4777 public Accessor (Block b, Attributes attrs)
4780 OptAttributes = attrs;
4785 // Properties and Indexers both generate PropertyBuilders, we use this to share
4786 // their common bits.
4788 abstract public class PropertyBase : MethodCore {
4789 public Accessor Get, Set;
4790 public PropertyBuilder PropertyBuilder;
4791 public MethodBuilder GetBuilder, SetBuilder;
4792 public MethodData GetData, SetData;
4794 protected EmitContext ec;
4796 public PropertyBase (DeclSpace ds, Expression type, int mod_flags,
4797 int allowed_mod, bool is_iface, MemberName name,
4798 Parameters parameters, Attributes attrs,
4799 Accessor get_block, Accessor set_block,
4801 : base (ds, type, mod_flags, allowed_mod, is_iface, name,
4802 attrs, parameters, loc)
4808 protected override bool DoDefine (DeclSpace decl, TypeContainer container)
4810 if (!base.DoDefine (decl, container))
4813 ec = new EmitContext (container, Location, null, MemberType, ModFlags);
4818 public override string GetSignatureForError()
4820 return TypeManager.CSharpSignature (PropertyBuilder, false);
4823 protected virtual string RealMethodName {
4829 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
4831 if (!IsIdentifierAndParamClsCompliant (ds, RealMethodName, null, null))
4834 if (Get != null && !IsIdentifierAndParamClsCompliant (ds, "get_" + RealMethodName, null, null))
4837 if (Set != null && !IsIdentifierAndParamClsCompliant (ds, "set_" + RealMethodName, null, null))
4845 // Checks our base implementation if any
4847 protected override bool CheckBase (TypeContainer container)
4849 base.CheckBase (container);
4851 // Check whether arguments were correct.
4852 if (!DoDefineParameters ())
4859 // Check in our class for dups
4861 ArrayList ar = container.Properties;
4863 int arLen = ar.Count;
4865 for (int i = 0; i < arLen; i++) {
4866 Property m = (Property) ar [i];
4867 if (IsDuplicateImplementation (container, m))
4876 MethodSignature ms, base_ms;
4877 if (this is Indexer) {
4878 string name, base_name;
4880 report_name = "this";
4881 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
4882 ms = new MethodSignature (name, null, ParameterTypes);
4883 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
4884 base_ms = new MethodSignature (base_name, null, ParameterTypes);
4887 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
4891 // Verify if the parent has a type with the same name, and then
4892 // check whether we have to create a new slot for it or not.
4894 Type ptype = container.TypeBuilder.BaseType;
4896 // ptype is only null for System.Object while compiling corlib.
4897 if (ptype == null) {
4898 if ((ModFlags & Modifiers.NEW) != 0)
4899 WarningNotHiding (container);
4904 PropertyInfo parent_property = null;
4907 // Explicit implementations do not have `parent' methods, however,
4908 // the member cache stores them there. Without this check, we get
4909 // an incorrect warning in corlib.
4911 if (! IsExplicitImpl) {
4912 parent_property = (PropertyInfo) ((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
4913 container.TypeBuilder, Name, ParameterTypes, true);
4916 if (parent_property != null) {
4917 string name = parent_property.DeclaringType.Name + "." +
4918 parent_property.Name;
4920 MethodInfo get, set, parent_method;
4921 get = parent_property.GetGetMethod (true);
4922 set = parent_property.GetSetMethod (true);
4925 parent_method = get;
4926 else if (set != null)
4927 parent_method = set;
4929 throw new Exception ("Internal error!");
4931 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
4934 if ((ModFlags & Modifiers.NEW) == 0) {
4935 Type parent_type = TypeManager.TypeToCoreType (
4936 parent_property.PropertyType);
4938 if (parent_type != MemberType) {
4940 508, Location, container.MakeName (Name) + ": cannot " +
4941 "change return type when overriding " +
4942 "inherited member " + name);
4947 if ((ModFlags & Modifiers.NEW) != 0)
4948 WarningNotHiding (container);
4950 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4951 if (this is Indexer)
4952 Report.Error (115, Location,
4953 container.MakeName (Name) +
4954 " no suitable indexers found to override");
4956 Report.Error (115, Location,
4957 container.MakeName (Name) +
4958 " no suitable properties found to override");
4965 public override void Emit (TypeContainer tc)
4968 // The PropertyBuilder can be null for explicit implementations, in that
4969 // case, we do not actually emit the ".property", so there is nowhere to
4970 // put the attribute
4972 if (PropertyBuilder != null)
4973 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes);
4975 if (GetData != null) {
4976 GetData.Emit (tc, Get.Block, Get);
4980 if (SetData != null) {
4981 SetData.Emit (tc, Set.Block, Set);
4989 public class Property : PropertyBase, IIteratorContainer {
4990 const int AllowedModifiers =
4993 Modifiers.PROTECTED |
4994 Modifiers.INTERNAL |
4998 Modifiers.OVERRIDE |
4999 Modifiers.ABSTRACT |
5002 Modifiers.METHOD_YIELDS |
5005 const int AllowedInterfaceModifiers =
5008 public Property (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
5009 MemberName name, Attributes attrs, Accessor get_block,
5010 Accessor set_block, Location loc)
5011 : base (ds, type, mod_flags,
5012 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5013 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
5014 get_block, set_block, loc)
5018 public override bool Define (TypeContainer container)
5020 if (!DoDefine (container, container))
5023 if (!CheckBase (container))
5026 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
5029 Type [] parameters = TypeManager.NoTypes;
5031 InternalParameters ip = new InternalParameters (
5032 container, Parameters.EmptyReadOnlyParameters);
5034 GetData = new MethodData (container, this, "get", MemberType,
5035 parameters, ip, CallingConventions.Standard,
5036 Get.OptAttributes, ModFlags, flags, false);
5039 // Setup iterator if we are one
5041 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
5042 IteratorHandler ih = new IteratorHandler (
5043 "get", container, MemberType,
5044 parameters, ip, ModFlags, Location);
5046 Block new_block = ih.Setup (block);
5047 if (new_block == null)
5052 if (!GetData.Define (container))
5055 GetBuilder = GetData.MethodBuilder;
5059 Type [] parameters = new Type [1];
5060 parameters [0] = MemberType;
5062 Parameter [] parms = new Parameter [1];
5063 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
5064 InternalParameters ip = new InternalParameters (
5065 container, new Parameters (parms, null, Location));
5067 SetData = new MethodData (container, this, "set", TypeManager.void_type,
5068 parameters, ip, CallingConventions.Standard,
5069 Set.OptAttributes, ModFlags, flags, false);
5071 if (!SetData.Define (container))
5074 SetBuilder = SetData.MethodBuilder;
5075 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
5078 // FIXME - PropertyAttributes.HasDefault ?
5080 PropertyAttributes prop_attr = PropertyAttributes.None;
5082 prop_attr |= PropertyAttributes.RTSpecialName |
5083 PropertyAttributes.SpecialName;
5085 if (!IsExplicitImpl){
5086 PropertyBuilder = container.TypeBuilder.DefineProperty (
5087 Name, prop_attr, MemberType, null);
5090 PropertyBuilder.SetGetMethod (GetBuilder);
5093 PropertyBuilder.SetSetMethod (SetBuilder);
5096 // HACK for the reasons exposed above
5098 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
5101 "Class `" + container.Name +
5102 "' already contains a definition for the property `" +
5110 public void SetYields ()
5112 ModFlags |= Modifiers.METHOD_YIELDS;
5117 /// Gigantic workaround for lameness in SRE follows :
5118 /// This class derives from EventInfo and attempts to basically
5119 /// wrap around the EventBuilder so that FindMembers can quickly
5120 /// return this in it search for members
5122 public class MyEventBuilder : EventInfo {
5125 // We use this to "point" to our Builder which is
5126 // not really a MemberInfo
5128 EventBuilder MyBuilder;
5131 // We "catch" and wrap these methods
5133 MethodInfo raise, remove, add;
5135 EventAttributes attributes;
5136 Type declaring_type, reflected_type, event_type;
5141 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
5143 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
5145 // And now store the values in our own fields.
5147 declaring_type = type_builder;
5149 reflected_type = type_builder;
5151 attributes = event_attr;
5154 this.event_type = event_type;
5158 // Methods that you have to override. Note that you only need
5159 // to "implement" the variants that take the argument (those are
5160 // the "abstract" methods, the others (GetAddMethod()) are
5163 public override MethodInfo GetAddMethod (bool nonPublic)
5168 public override MethodInfo GetRemoveMethod (bool nonPublic)
5173 public override MethodInfo GetRaiseMethod (bool nonPublic)
5179 // These methods make "MyEventInfo" look like a Builder
5181 public void SetRaiseMethod (MethodBuilder raiseMethod)
5183 raise = raiseMethod;
5184 MyBuilder.SetRaiseMethod (raiseMethod);
5187 public void SetRemoveOnMethod (MethodBuilder removeMethod)
5189 remove = removeMethod;
5190 MyBuilder.SetRemoveOnMethod (removeMethod);
5193 public void SetAddOnMethod (MethodBuilder addMethod)
5196 MyBuilder.SetAddOnMethod (addMethod);
5199 public void SetCustomAttribute (CustomAttributeBuilder cb)
5201 MyBuilder.SetCustomAttribute (cb);
5204 public override object [] GetCustomAttributes (bool inherit)
5206 // FIXME : There's nothing which can be seemingly done here because
5207 // we have no way of getting at the custom attribute objects of the
5212 public override object [] GetCustomAttributes (Type t, bool inherit)
5214 // FIXME : Same here !
5218 public override bool IsDefined (Type t, bool b)
5223 public override EventAttributes Attributes {
5229 public override string Name {
5235 public override Type DeclaringType {
5237 return declaring_type;
5241 public override Type ReflectedType {
5243 return reflected_type;
5247 public Type EventType {
5253 public void SetUsed ()
5255 if (my_event != null)
5256 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
5260 public class Event : FieldBase {
5261 const int AllowedModifiers =
5264 Modifiers.PROTECTED |
5265 Modifiers.INTERNAL |
5270 Modifiers.OVERRIDE |
5274 const int AllowedInterfaceModifiers =
5277 public readonly Accessor Add;
5278 public readonly Accessor Remove;
5279 public MyEventBuilder EventBuilder;
5281 public MethodBuilder AddBuilder, RemoveBuilder;
5282 MethodData AddData, RemoveData;
5284 public Event (Expression type, int mod_flags, bool is_iface, MemberName name,
5285 Object init, Attributes attrs, Accessor add, Accessor remove,
5287 : base (type, mod_flags,
5288 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5289 name, init, attrs, loc)
5293 IsInterface = is_iface;
5296 public override bool Define (TypeContainer container)
5298 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
5299 MethodAttributes m_attr = MethodAttributes.HideBySig | MethodAttributes.SpecialName
5301 if (!DoDefine (container, container))
5304 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
5305 Report.Error (74, Location, "'" + container.Name + "." + Name +
5306 "': abstract event can not have an initializer");
5310 if (!TypeManager.IsDelegateType (MemberType)) {
5311 Report.Error (66, Location, "'" + container.Name + "." + Name +
5312 "' : event must be of a delegate type");
5316 Type [] parameter_types = new Type [1];
5317 parameter_types [0] = MemberType;
5319 Parameter [] parms = new Parameter [1];
5320 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
5321 InternalParameters ip = new InternalParameters (
5322 container, new Parameters (parms, null, Location));
5324 if (!CheckBase (container))
5328 // Now define the accessors
5330 AddData = new MethodData (container, this, "add", TypeManager.void_type,
5331 parameter_types, ip, CallingConventions.Standard,
5332 (Add != null) ? Add.OptAttributes : null,
5333 ModFlags, flags | m_attr, false);
5335 if (!AddData.Define (container))
5338 AddBuilder = AddData.MethodBuilder;
5339 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
5341 RemoveData = new MethodData (container, this, "remove", TypeManager.void_type,
5342 parameter_types, ip, CallingConventions.Standard,
5343 (Remove != null) ? Remove.OptAttributes : null,
5344 ModFlags, flags | m_attr, false);
5346 if (!RemoveData.Define (container))
5349 RemoveBuilder = RemoveData.MethodBuilder;
5350 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
5352 if (!IsExplicitImpl){
5353 EventBuilder = new MyEventBuilder (this,
5354 container.TypeBuilder, Name, e_attr, MemberType);
5356 if (Add == null && Remove == null) {
5357 FieldBuilder = container.TypeBuilder.DefineField (
5359 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
5360 TypeManager.RegisterPrivateFieldOfEvent (
5361 (EventInfo) EventBuilder, FieldBuilder);
5362 TypeManager.RegisterFieldBase (FieldBuilder, this);
5365 EventBuilder.SetAddOnMethod (AddBuilder);
5366 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
5368 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
5369 Report.Error (111, Location,
5370 "Class `" + container.Name +
5371 "' already contains a definition for the event `" +
5380 void EmitDefaultMethod (EmitContext ec, bool is_add)
5382 ILGenerator ig = ec.ig;
5383 MethodInfo method = null;
5386 method = TypeManager.delegate_combine_delegate_delegate;
5388 method = TypeManager.delegate_remove_delegate_delegate;
5390 if ((ModFlags & Modifiers.STATIC) != 0) {
5391 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
5392 ig.Emit (OpCodes.Ldarg_0);
5393 ig.Emit (OpCodes.Call, method);
5394 ig.Emit (OpCodes.Castclass, MemberType);
5395 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
5397 ig.Emit (OpCodes.Ldarg_0);
5398 ig.Emit (OpCodes.Ldarg_0);
5399 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
5400 ig.Emit (OpCodes.Ldarg_1);
5401 ig.Emit (OpCodes.Call, method);
5402 ig.Emit (OpCodes.Castclass, MemberType);
5403 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
5405 ig.Emit (OpCodes.Ret);
5408 public override void Emit (TypeContainer tc)
5411 if (OptAttributes != null) {
5412 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
5413 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes);
5417 AddData.Emit (tc, Add.Block, Add);
5420 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
5421 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
5422 EmitDefaultMethod (ec, true);
5425 if (Remove != null) {
5426 RemoveData.Emit (tc, Remove.Block, Remove);
5427 Remove.Block = null;
5429 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
5430 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
5431 EmitDefaultMethod (ec, false);
5439 // FIXME: This does not handle:
5441 // int INTERFACENAME [ args ]
5446 // int this [ args ]
5448 public class Indexer : PropertyBase {
5450 const int AllowedModifiers =
5453 Modifiers.PROTECTED |
5454 Modifiers.INTERNAL |
5458 Modifiers.OVERRIDE |
5463 const int AllowedInterfaceModifiers =
5466 public string IndexerName;
5467 public string InterfaceIndexerName;
5470 // Are we implementing an interface ?
5472 public Indexer (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
5473 MemberName name, Parameters parameters, Attributes attrs,
5474 Accessor get_block, Accessor set_block, Location loc)
5475 : base (ds, type, mod_flags,
5476 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5477 is_iface, name, parameters, attrs, get_block, set_block, loc)
5481 void CheckIndexerName (string name)
5483 if (name.IndexOf (' ') != -1)
5484 Report.Error (633, Location, "The IndexerName specified is an invalid identifier");
5487 public override bool Define (TypeContainer container)
5489 PropertyAttributes prop_attr =
5490 PropertyAttributes.RTSpecialName |
5491 PropertyAttributes.SpecialName;
5493 if (!DoDefine (container, container))
5496 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
5497 if (IndexerName == null)
5498 IndexerName = "Item";
5500 CheckIndexerName (IndexerName);
5502 Report.Error (592, Location,
5503 "Attribute 'IndexerName' is not valid on explicit " +
5504 "implementations.");
5507 ShortName = IndexerName;
5508 if (IsExplicitImpl) {
5509 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
5510 Name = InterfaceType.FullName + "." + IndexerName;
5512 InterfaceIndexerName = IndexerName;
5516 if (!CheckNameCollision (container))
5519 if (!CheckBase (container))
5522 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
5524 InternalParameters ip = new InternalParameters (container, Parameters);
5526 GetData = new MethodData (container, this, "get", MemberType,
5527 ParameterTypes, ip, CallingConventions.Standard,
5528 Get.OptAttributes, ModFlags, flags, false);
5530 if (!GetData.Define (container))
5533 GetBuilder = GetData.MethodBuilder;
5537 int top = ParameterTypes.Length;
5538 Type [] set_pars = new Type [top + 1];
5539 ParameterTypes.CopyTo (set_pars, 0);
5540 set_pars [top] = MemberType;
5542 Parameter [] fixed_parms = Parameters.FixedParameters;
5544 if (fixed_parms == null){
5545 throw new Exception ("We currently do not support only array arguments in an indexer at: " + Location);
5546 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5547 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5549 // Here is the problem: the `value' parameter has
5550 // to come *after* the array parameter in the declaration
5552 // X (object [] x, Type value)
5555 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5556 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5560 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
5563 fixed_parms.CopyTo (tmp, 0);
5564 tmp [fixed_parms.Length] = new Parameter (
5565 Type, "value", Parameter.Modifier.NONE, null);
5567 Parameters set_formal_params = new Parameters (tmp, null, Location);
5569 InternalParameters ip = new InternalParameters (container, set_formal_params);
5571 SetData = new MethodData (container, this, "set", TypeManager.void_type,
5572 set_pars, ip, CallingConventions.Standard,
5573 Set.OptAttributes, ModFlags, flags, false);
5575 if (!SetData.Define (container))
5578 SetBuilder = SetData.MethodBuilder;
5582 // Now name the parameters
5584 Parameter [] p = Parameters.FixedParameters;
5588 for (i = 0; i < p.Length; ++i) {
5590 GetBuilder.DefineParameter (
5591 i + 1, p [i].Attributes, p [i].Name);
5594 SetBuilder.DefineParameter (
5595 i + 1, p [i].Attributes, p [i].Name);
5599 SetBuilder.DefineParameter (
5600 i + 1, ParameterAttributes.None, "value");
5602 if (i != ParameterTypes.Length) {
5603 Parameter array_param = Parameters.ArrayParameter;
5605 SetBuilder.DefineParameter (
5606 i + 1, array_param.Attributes, array_param.Name);
5611 // Define the PropertyBuilder if one of the following conditions are met:
5612 // a) we're not implementing an interface indexer.
5613 // b) the indexer has a different IndexerName and this is no
5614 // explicit interface implementation.
5616 if (!IsExplicitImpl) {
5617 PropertyBuilder = container.TypeBuilder.DefineProperty (
5618 IndexerName, prop_attr, MemberType, ParameterTypes);
5620 if (GetData != null)
5621 PropertyBuilder.SetGetMethod (GetBuilder);
5623 if (SetData != null)
5624 PropertyBuilder.SetSetMethod (SetBuilder);
5626 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
5633 bool CheckNameCollision (TypeContainer container) {
5634 switch (VerifyName (container)){
5635 case DeclSpace.AdditionResult.NameExists:
5636 Report.Error (102, Location, "The container '{0}' already contains a definition for '{1}'", container.GetSignatureForError (), Name);
5639 case DeclSpace.AdditionResult.Success:
5642 throw new NotImplementedException ();
5645 DeclSpace.AdditionResult VerifyName (TypeContainer container) {
5646 if (!AddIndexer (container, container.Name + "." + Name))
5647 return DeclSpace.AdditionResult.NameExists;
5650 if (!AddIndexer (container, container.Name + ".get_" + Name))
5651 return DeclSpace.AdditionResult.NameExists;
5655 if (!AddIndexer (container, container.Name + ".set_" + Name))
5656 return DeclSpace.AdditionResult.NameExists;
5658 return DeclSpace.AdditionResult.Success;
5661 bool AddIndexer (TypeContainer container, string fullname)
5663 object value = container.GetDefinition (fullname);
5665 if (value != null) {
5666 return value.GetType () != GetType () ? false : true;
5669 container.DefineName (fullname, this);
5673 public override string GetSignatureForError ()
5675 return TypeManager.CSharpSignature (PropertyBuilder, true);
5678 protected override string RealMethodName {
5685 public class Operator : MemberBase, IIteratorContainer {
5687 const int AllowedModifiers =
5693 const int RequiredModifiers =
5697 public enum OpType : byte {
5707 // Unary and Binary operators
5730 // Implicit and Explicit
5735 public readonly OpType OperatorType;
5736 public readonly Expression ReturnType;
5737 public readonly Expression FirstArgType, SecondArgType;
5738 public readonly string FirstArgName, SecondArgName;
5740 public MethodBuilder OperatorMethodBuilder;
5742 public string MethodName;
5743 public Method OperatorMethod;
5745 public Operator (OpType type, Expression ret_type, int mod_flags,
5746 Expression arg1type, string arg1name,
5747 Expression arg2type, string arg2name,
5748 Block block, Attributes attrs, Location loc)
5749 : base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC,
5750 MemberName.Null, attrs, loc)
5752 OperatorType = type;
5753 Name = "op_" + OperatorType;
5754 ReturnType = ret_type;
5755 FirstArgType = arg1type;
5756 FirstArgName = arg1name;
5757 SecondArgType = arg2type;
5758 SecondArgName = arg2name;
5762 string Prototype (TypeContainer container)
5764 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
5765 SecondArgType + ")";
5768 protected override bool CheckGenericOverride (MethodInfo method, string name)
5773 public override bool Define (TypeContainer container)
5776 MethodName = "op_" + OperatorType;
5778 if (SecondArgType != null)
5781 Parameter [] param_list = new Parameter [length];
5783 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
5786 "User defined operators `" +
5787 Prototype (container) +
5788 "' must be declared static and public");
5792 param_list[0] = new Parameter (FirstArgType, FirstArgName,
5793 Parameter.Modifier.NONE, null);
5794 if (SecondArgType != null)
5795 param_list[1] = new Parameter (SecondArgType, SecondArgName,
5796 Parameter.Modifier.NONE, null);
5798 OperatorMethod = new Method (
5799 container, ReturnType, ModFlags, false,
5800 new MemberName (MethodName),
5801 new Parameters (param_list, null, Location),
5802 OptAttributes, Location);
5804 OperatorMethod.Block = Block;
5805 OperatorMethod.IsOperator = true;
5806 OperatorMethod.Define (container);
5808 if (OperatorMethod.MethodBuilder == null)
5811 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
5813 Type [] param_types = OperatorMethod.ParameterTypes;
5814 Type declaring_type = OperatorMethod.MethodData.DeclaringType;
5815 Type return_type = OperatorMethod.GetReturnType ();
5816 Type first_arg_type = param_types [0];
5818 // Rules for conversion operators
5820 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
5821 if (first_arg_type == return_type && first_arg_type == declaring_type){
5824 "User-defined conversion cannot take an object of the " +
5825 "enclosing type and convert to an object of the enclosing" +
5830 if (first_arg_type != declaring_type && return_type != declaring_type){
5833 "User-defined conversion must convert to or from the " +
5838 if (first_arg_type == TypeManager.object_type ||
5839 return_type == TypeManager.object_type){
5842 "User-defined conversion cannot convert to or from " +
5847 if (first_arg_type.IsInterface || return_type.IsInterface){
5850 "User-defined conversion cannot convert to or from an " +
5855 if (first_arg_type.IsSubclassOf (return_type) ||
5856 return_type.IsSubclassOf (first_arg_type)){
5859 "User-defined conversion cannot convert between types " +
5860 "that derive from each other");
5863 } else if (SecondArgType == null) {
5864 // Checks for Unary operators
5866 if (first_arg_type != declaring_type){
5869 "The parameter of a unary operator must be the " +
5874 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
5875 if (return_type != declaring_type){
5878 "The parameter and return type for ++ and -- " +
5879 "must be the containing type");
5885 if (OperatorType == OpType.True || OperatorType == OpType.False) {
5886 if (return_type != TypeManager.bool_type){
5889 "The return type of operator True or False " +
5896 // Checks for Binary operators
5898 if (first_arg_type != declaring_type &&
5899 param_types [1] != declaring_type){
5902 "One of the parameters of a binary operator must " +
5903 "be the containing type");
5911 public override void Emit (TypeContainer container)
5914 // abstract or extern methods have no bodies
5916 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
5919 OperatorMethod.Emit (container);
5923 public static string GetName (OpType ot)
5926 case OpType.LogicalNot:
5928 case OpType.OnesComplement:
5930 case OpType.Increment:
5932 case OpType.Decrement:
5938 case OpType.Addition:
5940 case OpType.Subtraction:
5942 case OpType.UnaryPlus:
5944 case OpType.UnaryNegation:
5946 case OpType.Multiply:
5948 case OpType.Division:
5950 case OpType.Modulus:
5952 case OpType.BitwiseAnd:
5954 case OpType.BitwiseOr:
5956 case OpType.ExclusiveOr:
5958 case OpType.LeftShift:
5960 case OpType.RightShift:
5962 case OpType.Equality:
5964 case OpType.Inequality:
5966 case OpType.GreaterThan:
5968 case OpType.LessThan:
5970 case OpType.GreaterThanOrEqual:
5972 case OpType.LessThanOrEqual:
5974 case OpType.Implicit:
5976 case OpType.Explicit:
5982 public override string ToString ()
5984 Type return_type = OperatorMethod.GetReturnType();
5985 Type [] param_types = OperatorMethod.ParameterTypes;
5987 if (SecondArgType == null)
5988 return String.Format (
5989 "{0} operator {1}({2})",
5990 TypeManager.CSharpName (return_type),
5991 GetName (OperatorType),
5994 return String.Format (
5995 "{0} operator {1}({2}, {3})",
5996 TypeManager.CSharpName (return_type),
5997 GetName (OperatorType),
5998 param_types [0], param_types [1]);
6001 public void SetYields ()
6003 ModFlags |= Modifiers.METHOD_YIELDS;
6008 // This is used to compare method signatures
6010 struct MethodSignature {
6012 public Type RetType;
6013 public Type [] Parameters;
6016 /// This delegate is used to extract methods which have the
6017 /// same signature as the argument
6019 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
6021 public MethodSignature (string name, Type ret_type, Type [] parameters)
6026 if (parameters == null)
6027 Parameters = TypeManager.NoTypes;
6029 Parameters = parameters;
6032 public override string ToString ()
6035 if (Parameters.Length != 0){
6036 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
6037 for (int i = 0; i < Parameters.Length; i++){
6038 sb.Append (Parameters [i]);
6039 if (i+1 < Parameters.Length)
6042 pars = sb.ToString ();
6045 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
6048 public override int GetHashCode ()
6050 return Name.GetHashCode ();
6053 public override bool Equals (Object o)
6055 MethodSignature other = (MethodSignature) o;
6057 if (other.Name != Name)
6060 if (other.RetType != RetType)
6063 if (Parameters == null){
6064 if (other.Parameters == null)
6069 if (other.Parameters == null)
6072 int c = Parameters.Length;
6073 if (other.Parameters.Length != c)
6076 for (int i = 0; i < c; i++)
6077 if (other.Parameters [i] != Parameters [i])
6083 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
6085 MethodSignature sig = (MethodSignature) filter_criteria;
6087 if (m.Name != sig.Name)
6091 MethodInfo mi = m as MethodInfo;
6092 PropertyInfo pi = m as PropertyInfo;
6095 ReturnType = mi.ReturnType;
6096 else if (pi != null)
6097 ReturnType = pi.PropertyType;
6102 // we use sig.RetType == null to mean `do not check the
6103 // method return value.
6105 if (sig.RetType != null)
6106 if (ReturnType != sig.RetType)
6111 args = TypeManager.GetArgumentTypes (mi);
6113 args = TypeManager.GetArgumentTypes (pi);
6114 Type [] sigp = sig.Parameters;
6116 if (args.Length != sigp.Length)
6119 for (int i = args.Length; i > 0; ){
6121 if (args [i] != sigp [i])