2 // class.cs: Class and Struct handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // Licensed under the terms of the GNU GPL
10 // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // (C) 2004 Novell, Inc
14 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
16 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
17 // have fixed a remaining problem: not every AddXXXX was adding a
18 // fully qualified name.
20 // Now everyone registers a fully qualified name in the DeclSpace as
21 // being defined instead of the partial name.
23 // Downsides: we are slower than we need to be due to the excess
24 // copies and the names being registered this way.
26 // The reason for this is that we currently depend (on the corlib
27 // bootstrap for instance) that types are fully qualified, because
28 // we dump all the types in the namespace, and we should really have
29 // types inserted into the proper namespace, so we can only store the
30 // basenames in the defined_names array.
36 using System.Collections;
37 using System.Collections.Specialized;
38 using System.Reflection;
39 using System.Reflection.Emit;
40 using System.Runtime.CompilerServices;
41 using System.Runtime.InteropServices;
42 using System.Security;
43 using System.Security.Permissions;
46 using Mono.CompilerServices.SymbolWriter;
48 namespace Mono.CSharp {
58 /// This is the base class for structs and classes.
60 public abstract class TypeContainer : DeclSpace, IMemberContainer {
62 public class MemberCoreArrayList: ArrayList
65 /// Defines the MemberCore objects that are in this array
67 public virtual void DefineContainerMembers ()
69 foreach (MemberCore mc in this) {
74 public virtual void Emit ()
76 foreach (MemberCore mc in this)
81 public class MethodArrayList: MemberCoreArrayList
89 CachedMethods cached_method;
90 TypeContainer container;
92 public MethodArrayList (TypeContainer container)
94 this.container = container;
98 /// Method container contains Equals method
100 public bool HasEquals {
102 cached_method |= CachedMethods.Equals;
106 return (cached_method & CachedMethods.Equals) != 0;
111 /// Method container contains GetHashCode method
113 public bool HasGetHashCode {
115 cached_method |= CachedMethods.GetHashCode;
119 return (cached_method & CachedMethods.GetHashCode) != 0;
123 public override void DefineContainerMembers ()
125 base.DefineContainerMembers ();
127 if ((RootContext.WarningLevel >= 3) && HasEquals && !HasGetHashCode) {
128 Report.Warning (659, container.Location, "'{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", container.GetSignatureForError ());
134 public sealed class IndexerArrayList: MemberCoreArrayList
137 /// The indexer name for this container
139 public string IndexerName = DefaultIndexerName;
141 bool seen_normal_indexers = false;
143 TypeContainer container;
145 public IndexerArrayList (TypeContainer container)
147 this.container = container;
151 /// Defines the indexers, and also verifies that the IndexerNameAttribute in the
152 /// class is consistent. Either it is `Item' or it is the name defined by all the
153 /// indexers with the `IndexerName' attribute.
155 /// Turns out that the IndexerNameAttribute is applied to each indexer,
156 /// but it is never emitted, instead a DefaultMember attribute is attached
159 public override void DefineContainerMembers()
161 base.DefineContainerMembers ();
163 string class_indexer_name = null;
166 // If there's both an explicit and an implicit interface implementation, the
167 // explicit one actually implements the interface while the other one is just
168 // a normal indexer. See bug #37714.
171 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
172 foreach (Indexer i in this) {
173 if (i.InterfaceType != null) {
174 if (seen_normal_indexers)
175 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
179 seen_normal_indexers = true;
181 if (class_indexer_name == null) {
182 class_indexer_name = i.ShortName;
186 if (i.ShortName != class_indexer_name)
187 Report.Error (668, i.Location, "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
190 if (class_indexer_name != null)
191 IndexerName = class_indexer_name;
194 public override void Emit ()
198 if (!seen_normal_indexers)
201 CustomAttributeBuilder cb = new CustomAttributeBuilder (TypeManager.default_member_ctor, new string [] { IndexerName });
202 container.TypeBuilder.SetCustomAttribute (cb);
206 public class OperatorArrayList: MemberCoreArrayList
208 TypeContainer container;
210 public OperatorArrayList (TypeContainer container)
212 this.container = container;
216 // Operator pair checking
221 public Type ret_type;
222 public Type type1, type2;
224 public Operator.OpType ot;
226 public OperatorEntry (int f, Operator o)
230 ret_type = o.OperatorMethod.ReturnType;
231 Type [] pt = o.OperatorMethod.ParameterTypes;
238 public override int GetHashCode ()
240 return ret_type.GetHashCode ();
243 public override bool Equals (object o)
245 OperatorEntry other = (OperatorEntry) o;
247 if (other.ret_type != ret_type)
249 if (other.type1 != type1)
251 if (other.type2 != type2)
258 // Checks that some operators come in pairs:
264 // They are matched based on the return type and the argument types
266 void CheckPairedOperators ()
268 Hashtable pairs = new Hashtable (null, null);
269 Operator true_op = null;
270 Operator false_op = null;
271 bool has_equality_or_inequality = false;
273 // Register all the operators we care about.
274 foreach (Operator op in this){
277 switch (op.OperatorType){
278 case Operator.OpType.Equality:
280 has_equality_or_inequality = true;
282 case Operator.OpType.Inequality:
284 has_equality_or_inequality = true;
287 case Operator.OpType.True:
290 case Operator.OpType.False:
294 case Operator.OpType.GreaterThan:
296 case Operator.OpType.LessThan:
299 case Operator.OpType.GreaterThanOrEqual:
301 case Operator.OpType.LessThanOrEqual:
307 OperatorEntry oe = new OperatorEntry (reg, op);
309 object o = pairs [oe];
313 oe = (OperatorEntry) o;
318 if (true_op != null){
319 if (false_op == null)
320 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
321 } else if (false_op != null)
322 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
325 // Look for the mistakes.
327 foreach (DictionaryEntry de in pairs){
328 OperatorEntry oe = (OperatorEntry) de.Key;
335 case Operator.OpType.Equality:
338 case Operator.OpType.Inequality:
341 case Operator.OpType.GreaterThan:
344 case Operator.OpType.LessThan:
347 case Operator.OpType.GreaterThanOrEqual:
350 case Operator.OpType.LessThanOrEqual:
354 Report.Error (216, oe.op.Location,
355 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
358 if (has_equality_or_inequality && (RootContext.WarningLevel > 2)) {
359 if (container.Methods == null || !container.Methods.HasEquals)
360 Report.Warning (660, container.Location, "'{0}' defines operator == or operator != but does not override Object.Equals(object o)", container.GetSignatureForError ());
362 if (container.Methods == null || !container.Methods.HasGetHashCode)
363 Report.Warning (661, container.Location, "'{0}' defines operator == or operator != but does not override Object.GetHashCode()", container.GetSignatureForError ());
367 public override void DefineContainerMembers ()
369 base.DefineContainerMembers ();
370 CheckPairedOperators ();
375 // Whether this is a struct, class or interface
376 public readonly Kind Kind;
378 // Holds a list of classes and structures
381 // Holds the list of properties
382 MemberCoreArrayList properties;
384 // Holds the list of enumerations
385 MemberCoreArrayList enums;
387 // Holds the list of delegates
388 MemberCoreArrayList delegates;
390 // Holds the list of constructors
391 protected MemberCoreArrayList instance_constructors;
393 // Holds the list of fields
394 MemberCoreArrayList fields;
396 // Holds a list of fields that have initializers
397 protected ArrayList initialized_fields;
399 // Holds a list of static fields that have initializers
400 protected ArrayList initialized_static_fields;
402 // Holds the list of constants
403 MemberCoreArrayList constants;
406 MemberCoreArrayList interfaces;
408 // Holds the methods.
409 MethodArrayList methods;
412 protected MemberCoreArrayList events;
414 // Holds the indexers
415 IndexerArrayList indexers;
417 // Holds the operators
418 MemberCoreArrayList operators;
420 // Holds the iterators
423 // Holds the parts of a partial class;
427 // Pointers to the default constructor and the default static constructor
429 protected Constructor default_constructor;
430 protected Constructor default_static_constructor;
433 // Whether we have at least one non-static field
435 bool have_nonstatic_fields = false;
438 // This one is computed after we can distinguish interfaces
439 // from classes from the arraylist `type_bases'
441 string base_class_name;
444 ArrayList type_bases;
446 bool members_defined;
447 bool members_defined_ok;
449 // The interfaces we implement.
450 protected Type[] ifaces;
451 protected Type ptype;
453 // The base member cache and our member cache
454 MemberCache base_cache;
455 MemberCache member_cache;
457 public const string DefaultIndexerName = "Item";
461 public TypeContainer (NamespaceEntry ns, TypeContainer parent, MemberName name,
462 Attributes attrs, Kind kind, Location l)
463 : base (ns, parent, name, attrs, l)
465 if (parent != null && parent != RootContext.Tree.Types && parent.NamespaceEntry != ns)
466 throw new InternalErrorException ("A nested type should be in the same NamespaceEntry as its enclosing class");
470 types = new ArrayList ();
472 base_class_name = null;
475 public bool AddToMemberContainer (MemberCore symbol)
477 return AddToContainer (symbol, String.Concat (Name, ".", symbol.Name), symbol.Name);
480 bool AddToTypeContainer (DeclSpace ds)
482 return AddToContainer (ds, ds.Name, ds.Basename);
485 public void AddConstant (Const constant)
487 if (!AddToMemberContainer (constant))
490 if (constants == null)
491 constants = new MemberCoreArrayList ();
493 constants.Add (constant);
496 public void AddEnum (Mono.CSharp.Enum e)
498 if (!AddToTypeContainer (e))
502 enums = new MemberCoreArrayList ();
507 public void AddClassOrStruct (TypeContainer c)
509 if (!AddToTypeContainer (c))
515 public void AddDelegate (Delegate d)
517 if (!AddToTypeContainer (d))
520 if (delegates == null)
521 delegates = new MemberCoreArrayList ();
526 public void AddMethod (Method method)
528 if (!AddToMemberContainer (method))
532 methods = new MethodArrayList (this);
534 if (method.Name.IndexOf ('.') != -1)
535 methods.Insert (0, method);
537 methods.Add (method);
540 public void AddConstructor (Constructor c)
542 if (c.Name != Basename) {
543 Report.Error (1520, c.Location, "Class, struct, or interface method must have a return type");
546 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
549 if (default_static_constructor != null) {
550 Report.SymbolRelatedToPreviousError (default_static_constructor);
551 Report.Error (111, c.Location, "Type '{0}' already defines a member " +
552 "called '{1}' with the same parameter types", Name, c.Name);
556 default_static_constructor = c;
559 if (default_constructor != null) {
560 Report.SymbolRelatedToPreviousError (default_constructor);
561 Report.Error (111, c.Location, "Type '{0}' already defines a member " +
562 "called '{1}' with the same parameter types", Name, c.Name);
565 default_constructor = c;
568 if (instance_constructors == null)
569 instance_constructors = new MemberCoreArrayList ();
571 instance_constructors.Add (c);
575 public void AddInterface (TypeContainer iface)
577 if (!AddToTypeContainer (iface))
580 if (interfaces == null) {
581 interfaces = new MemberCoreArrayList ();
584 interfaces.Add (iface);
587 public void AddField (FieldMember field)
589 if (!AddToMemberContainer (field))
593 fields = new MemberCoreArrayList ();
597 if (field.HasInitializer){
598 if ((field.ModFlags & Modifiers.STATIC) != 0){
599 if (initialized_static_fields == null)
600 initialized_static_fields = new ArrayList ();
602 initialized_static_fields.Add (field);
605 if (initialized_fields == null)
606 initialized_fields = new ArrayList ();
608 initialized_fields.Add (field);
612 if ((field.ModFlags & Modifiers.STATIC) == 0)
613 have_nonstatic_fields = true;
616 public void AddProperty (Property prop)
618 if (!AddToMemberContainer (prop) ||
619 !AddToMemberContainer (prop.Get) || !AddToMemberContainer (prop.Set))
622 if (properties == null)
623 properties = new MemberCoreArrayList ();
625 if (prop.Name.IndexOf ('.') != -1)
626 properties.Insert (0, prop);
628 properties.Add (prop);
631 public void AddEvent (Event e)
633 if (!AddToMemberContainer (e))
636 if (e is EventProperty) {
637 if (!AddToMemberContainer (e.Add))
640 if (!AddToMemberContainer (e.Remove))
645 events = new MemberCoreArrayList ();
651 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
653 public void AddIndexer (Indexer i)
655 if (indexers == null)
656 indexers = new IndexerArrayList (this);
658 if (i.IsExplicitImpl)
659 indexers.Insert (0, i);
664 public void AddOperator (Operator op)
666 if (!AddToMemberContainer (op))
669 if (operators == null)
670 operators = new OperatorArrayList (this);
675 public void AddIterator (Iterator i)
677 if (iterators == null)
678 iterators = new ArrayList ();
683 public void AddType (TypeContainer tc)
688 public void AddPart (ClassPart part)
691 parts = new ArrayList ();
696 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
698 if (a.Type == TypeManager.default_member_type) {
699 if (Indexers != null) {
700 Report.Error (646, a.Location,
701 "Cannot specify the DefaultMember attribute on" +
702 " a type containing an indexer");
707 base.ApplyAttributeBuilder (a, cb);
710 public override AttributeTargets AttributeTargets {
714 return AttributeTargets.Class;
716 return AttributeTargets.Struct;
718 return AttributeTargets.Interface;
720 throw new NotSupportedException ();
725 public ArrayList Types {
731 public MethodArrayList Methods {
737 public ArrayList Constants {
743 public ArrayList Interfaces {
749 public ArrayList Iterators {
757 return base_class_name;
761 public ArrayList Bases {
771 public ArrayList Fields {
777 public ArrayList InstanceConstructors {
779 return instance_constructors;
783 public ArrayList Properties {
789 public ArrayList Events {
795 public ArrayList Enums {
801 public ArrayList Indexers {
807 public ArrayList Operators {
813 public ArrayList Delegates {
819 public ArrayList Parts {
825 public virtual TypeAttributes TypeAttr {
827 return Modifiers.TypeAttr (ModFlags, this);
831 public string IndexerName {
833 return indexers == null ? DefaultIndexerName : indexers.IndexerName;
838 // Emits the instance field initializers
840 public virtual bool EmitFieldInitializers (EmitContext ec)
843 Expression instance_expr;
846 fields = initialized_static_fields;
847 instance_expr = null;
849 fields = initialized_fields;
850 instance_expr = new This (Location.Null).Resolve (ec);
856 foreach (Field f in fields){
857 Expression e = f.GetInitializerExpression (ec);
861 Location l = f.Location;
862 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
863 fe.InstanceExpression = instance_expr;
864 fe.IsFieldInitializer = true;
866 ExpressionStatement a = new Assign (fe, e, l);
868 a = a.ResolveStatement (ec);
872 if (RootContext.Optimize) {
873 Constant c = e as Constant;
875 if (c.IsDefaultValue)
880 a.EmitStatement (ec);
887 // Defines the default constructors
889 protected void DefineDefaultConstructor (bool is_static)
893 // The default constructor is public
894 // If the class is abstract, the default constructor is protected
895 // The default static constructor is private
897 int mods = Modifiers.PUBLIC;
899 mods = Modifiers.STATIC | Modifiers.PRIVATE;
900 else if ((ModFlags & Modifiers.ABSTRACT) != 0)
901 mods = Modifiers.PROTECTED;
903 TypeContainer constructor_parent = this;
905 constructor_parent = (TypeContainer) Parts [0];
907 c = new Constructor (constructor_parent, Basename, mods,
908 Parameters.EmptyReadOnlyParameters,
909 new ConstructorBaseInitializer (
910 null, Parameters.EmptyReadOnlyParameters,
916 c.Block = new ToplevelBlock (null, Location);
921 /// The pending methods that need to be implemented
922 // (interfaces or abstract methods)
924 public PendingImplementation Pending;
926 public abstract PendingImplementation GetPendingImplementations ();
928 TypeExpr[] GetPartialBases (out TypeExpr base_class, out bool error)
930 ArrayList ifaces = new ArrayList ();
933 Location base_loc = Location.Null;
935 foreach (ClassPart part in parts) {
936 TypeExpr new_base_class;
937 TypeExpr[] new_ifaces;
939 new_ifaces = part.GetClassBases (out new_base_class, out error);
943 if ((base_class != null) && (new_base_class != null) &&
944 !base_class.Equals (new_base_class)) {
945 Report.Error (263, part.Location,
946 "Partial declarations of `{0}' must " +
947 "not specify different base classes",
950 if (!Location.IsNull (base_loc))
951 Report.LocationOfPreviousError (base_loc);
957 if ((base_class == null) && (new_base_class != null)) {
958 base_class = new_base_class;
959 base_loc = part.Location;
962 if (new_ifaces == null)
965 foreach (TypeExpr iface in new_ifaces) {
967 foreach (TypeExpr old_iface in ifaces) {
968 if (old_iface.Equals (iface)) {
981 TypeExpr[] retval = new TypeExpr [ifaces.Count];
982 ifaces.CopyTo (retval, 0);
986 TypeExpr[] GetNormalBases (out TypeExpr base_class, out bool error)
990 int count = Bases.Count;
993 if (Kind == Kind.Class){
994 TypeExpr name = ResolveBaseTypeExpr (
995 (Expression) Bases [0], false, Location);
1002 if (!name.IsInterface) {
1003 // base_class could be a class, struct, enum, delegate.
1004 // This is validated in GetClassBases.
1010 TypeExpr [] ifaces = new TypeExpr [count-start];
1012 for (i = start, j = 0; i < count; i++, j++){
1013 TypeExpr resolved = ResolveBaseTypeExpr ((Expression) Bases [i], false, Location);
1014 if (resolved == null) {
1019 ifaces [j] = resolved;
1027 /// This function computes the Base class and also the
1028 /// list of interfaces that the class or struct @c implements.
1030 /// The return value is an array (might be null) of
1031 /// interfaces implemented (as Types).
1033 /// The @base_class argument is set to the base object or null
1034 /// if this is `System.Object'.
1036 TypeExpr [] GetClassBases (out TypeExpr base_class, out bool error)
1045 ifaces = GetPartialBases (out base_class, out error);
1046 else if (Bases == null){
1050 ifaces = GetNormalBases (out base_class, out error);
1055 if ((base_class != null) && (Kind == Kind.Class)){
1056 if (base_class is TypeParameterExpr){
1058 689, base_class.Location,
1059 "Type parameter `{0}' can not be used as a " +
1060 "base class or interface", base_class.Name);
1065 if (IsGeneric && base_class.Type.IsSubclassOf (TypeManager.attribute_type)){
1067 698, base_class.Location,
1068 "A generic type cannot derive from `{0}' " +
1069 "because it is an attribute class",
1075 if (base_class.Type.IsArray || base_class.Type.IsPointer) {
1076 Report.Error (1521, base_class.Location, "Invalid base type");
1081 if (base_class.IsSealed){
1083 Report.SymbolRelatedToPreviousError (base_class.Type);
1084 if (base_class.Type.IsAbstract) {
1085 Report.Error (709, Location, "'{0}': Cannot derive from static class", GetSignatureForError ());
1087 Report.Error (509, Location, "'{0}': Cannot derive from sealed class", GetSignatureForError ());
1092 if (!base_class.CanInheritFrom ()){
1093 Report.Error (644, Location,
1094 "`{0}' cannot inherit from special class `{1}'",
1095 Name, base_class.Name);
1100 if (!base_class.AsAccessible (this, ModFlags)) {
1101 Report.SymbolRelatedToPreviousError (base_class.Type);
1102 Report.Error (60, Location, "Inconsistent accessibility: base class '{0}' is less accessible than class '{1}'",
1103 TypeManager.CSharpName (base_class.Type), GetSignatureForError ());
1107 if (base_class != null)
1108 base_class_name = base_class.Name;
1113 int count = ifaces != null ? ifaces.Length : 0;
1115 for (i = 0; i < count; i++) {
1116 TypeExpr iface = (TypeExpr) ifaces [i];
1118 if (!iface.IsInterface) {
1120 if (Kind != Kind.Class) {
1121 string what = Kind == Kind.Struct ? "Struct" : "Interface";
1123 Report.Error (527, Location,
1124 "In {0} `{1}', type `{2}' is not "+
1125 "an interface", what, Name, iface.Name);
1127 else if (base_class != null)
1128 Report.Error (1721, Location,
1129 "In Class `{0}', `{1}' is not an interface, and a base class has already been defined",
1132 Report.Error (1722, Location,
1133 "In Class `{0}', `{1}' is not " +
1134 "an interface, a base class must be listed first", Name, iface.Name);
1139 for (int x = 0; x < i; x++) {
1140 if (iface.Equals (ifaces [x])) {
1141 Report.Error (528, Location,
1142 "`{0}' is already listed in " +
1143 "interface list", iface.Name);
1148 if ((Kind == Kind.Interface) &&
1149 !iface.AsAccessible (Parent, ModFlags)) {
1150 Report.Error (61, Location,
1151 "Inconsistent accessibility: base " +
1152 "interface `{0}' is less accessible " +
1153 "than interface `{1}'", iface.Name,
1165 bool CheckGenericInterfaces (Type[] ifaces)
1167 ArrayList already_checked = new ArrayList ();
1169 for (int i = 0; i < ifaces.Length; i++) {
1170 Type iface = ifaces [i];
1171 foreach (Type t in already_checked) {
1175 Type[] infered = new Type [CountTypeParameters];
1176 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t, infered, null))
1181 "`{0}' cannot implement both `{1}' and `{2}' " +
1182 "because they may unify for some type " +
1183 "parameter substitutions",
1184 TypeManager.GetFullName (TypeBuilder),
1189 already_checked.Add (iface);
1198 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1200 public override TypeBuilder DefineType ()
1205 if (TypeBuilder != null)
1208 TypeAttributes type_attributes = TypeAttr;
1212 if (TypeManager.NamespaceClash (Name, Location)) {
1217 ModuleBuilder builder = CodeGen.Module.Builder;
1218 TypeBuilder = builder.DefineType (
1219 Name, type_attributes, null, null);
1221 TypeBuilder builder;
1222 if (Parent.TypeBuilder != null)
1223 builder = Parent.TypeBuilder;
1225 builder = Parent.DefineType ();
1227 if (builder == null) {
1232 TypeBuilder = builder.DefineNestedType (
1233 MemberName.Basename, type_attributes,
1237 catch (ArgumentException) {
1238 Report.RuntimeMissingSupport (Location, "static classes");
1242 TypeManager.AddUserType (Name, TypeBuilder, this);
1244 if (Parts != null) {
1246 foreach (ClassPart part in Parts) {
1247 part.TypeBuilder = TypeBuilder;
1249 part.ec = new EmitContext (part, Mono.CSharp.Location.Null, null, null, ModFlags);
1250 part.ec.ContainerType = TypeBuilder;
1253 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
1254 ec.ContainerType = TypeBuilder;
1257 Expression current_type = null;
1260 string[] param_names = new string [TypeParameters.Length];
1261 for (int i = 0; i < TypeParameters.Length; i++)
1262 param_names [i] = TypeParameters [i].Name;
1264 GenericTypeParameterBuilder[] gen_params;
1265 gen_params = TypeBuilder.DefineGenericParameters (param_names);
1267 int offset = CountTypeParameters - CurrentTypeParameters.Length;
1268 for (int i = offset; i < gen_params.Length; i++)
1269 CurrentTypeParameters [i - offset].Define (gen_params [i]);
1271 if (Parts != null) {
1272 foreach (ClassPart part in Parts) {
1273 if (!part.DefineTypeParameters ()) {
1279 foreach (TypeParameter type_param in CurrentTypeParameters) {
1280 if (!type_param.Resolve (this)) {
1286 for (int i = offset; i < gen_params.Length; i++)
1287 CurrentTypeParameters [i - offset].DefineConstraints ();
1289 foreach (TypeParameter type_param in TypeParameters) {
1290 if (!type_param.DefineType (ec)) {
1296 current_type = new SimpleName (Name, TypeParameters, Location);
1300 if (!CheckConstraints (ec)) {
1305 if ((Kind == Kind.Struct) && TypeManager.value_type == null)
1306 throw new Exception ();
1308 TypeExpr[] iface_exprs = GetClassBases (out base_type, out error);
1312 if (base_type == null) {
1313 if (Kind == Kind.Class){
1314 if (RootContext.StdLib)
1315 base_type = TypeManager.system_object_expr;
1316 else if (Name != "System.Object")
1317 base_type = TypeManager.system_object_expr;
1318 } else if (Kind == Kind.Struct){
1320 // If we are compiling our runtime,
1321 // and we are defining ValueType, then our
1322 // base is `System.Object'.
1324 if (!RootContext.StdLib && Name == "System.ValueType")
1325 base_type = TypeManager.system_object_expr;
1326 else if (Kind == Kind.Struct)
1327 base_type = TypeManager.system_valuetype_expr;
1331 if (base_type != null) {
1332 // FIXME: I think this should be ...ResolveType (Parent.EmitContext).
1333 // However, if Parent == RootContext.Tree.Types, its NamespaceEntry will be null.
1334 ptype = base_type.ResolveType (TypeResolveEmitContext);
1335 if (ptype == null) {
1340 ptype = base_type.Type;
1343 if (!CheckRecursiveDefinition ()) {
1349 TypeBuilder.SetParent (ptype);
1352 // Structs with no fields need to have at least one byte.
1353 // The right thing would be to set the PackingSize in a DefineType
1354 // but there are no functions that allow interfaces *and* the size to
1358 if ((Kind == Kind.Struct) && !have_nonstatic_fields){
1359 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
1360 FieldAttributes.Private);
1363 // add interfaces that were not added at type creation
1364 if (iface_exprs != null) {
1365 // FIXME: I think this should be ...ExpandInterfaces (Parent.EmitContext, ...).
1366 // However, if Parent == RootContext.Tree.Types, its NamespaceEntry will be null.
1367 TypeResolveEmitContext.ContainerType = TypeBuilder;
1368 ifaces = TypeManager.ExpandInterfaces (TypeResolveEmitContext, iface_exprs);
1369 if (ifaces == null) {
1374 foreach (Type itype in ifaces)
1375 TypeBuilder.AddInterfaceImplementation (itype);
1377 if (!CheckGenericInterfaces (ifaces)) {
1382 TypeManager.RegisterBuilder (TypeBuilder, ifaces);
1386 foreach (TypeParameter type_param in TypeParameters)
1387 if (!type_param.CheckDependencies (ec)) {
1393 if (current_type != null) {
1394 current_type = current_type.ResolveAsTypeTerminal (ec);
1395 if (current_type == null) {
1400 CurrentType = current_type.Type;
1403 if (!(this is Iterator))
1404 RootContext.RegisterOrder (this);
1406 if (!DefineNestedTypes ()) {
1414 protected virtual bool CheckConstraints (EmitContext ec)
1419 protected virtual bool DefineNestedTypes ()
1421 if (Interfaces != null) {
1422 foreach (TypeContainer iface in Interfaces)
1423 if (iface.DefineType () == null)
1427 if (Types != null) {
1428 foreach (TypeContainer tc in Types)
1429 if (tc.DefineType () == null)
1433 if (Delegates != null) {
1434 foreach (Delegate d in Delegates)
1435 if (d.DefineType () == null)
1439 if (Enums != null) {
1440 foreach (Enum en in Enums)
1441 if (en.DefineType () == null)
1448 protected bool CheckRecursiveDefinition ()
1451 Report.Error (146, Location,
1452 "Class definition is circular: `{0}'",
1453 GetSignatureForError ());
1460 Type parent = ptype;
1461 if (parent != null) {
1462 if (parent.IsGenericInstance)
1463 parent = parent.GetGenericTypeDefinition ();
1465 TypeContainer ptc = TypeManager.LookupTypeContainer (parent);
1466 if ((ptc != null) && !ptc.CheckRecursiveDefinition ())
1474 static void Error_KeywordNotAllowed (Location loc)
1476 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1480 /// Populates our TypeBuilder with fields and methods
1482 public override bool DefineMembers (TypeContainer container)
1484 if (members_defined)
1485 return members_defined_ok;
1487 members_defined_ok = DoDefineMembers ();
1488 members_defined = true;
1490 return members_defined_ok;
1493 protected virtual bool DoDefineMembers ()
1496 if ((ModFlags & Modifiers.NEW) != 0)
1497 Error_KeywordNotAllowed (Location);
1499 MemberInfo conflict_symbol = Parent.MemberCache.FindMemberWithSameName (Basename, false, TypeBuilder);
1500 if (conflict_symbol == null) {
1501 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0))
1502 Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
1504 if ((ModFlags & Modifiers.NEW) == 0) {
1505 Report.SymbolRelatedToPreviousError (conflict_symbol);
1506 Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError ());
1511 DefineContainerMembers (constants);
1512 DefineContainerMembers (fields);
1514 if ((Kind == Kind.Class) && !(this is ClassPart)){
1515 if ((instance_constructors == null) &&
1516 !(this is StaticClass)) {
1517 if (default_constructor == null)
1518 DefineDefaultConstructor (false);
1521 if (initialized_static_fields != null &&
1522 default_static_constructor == null)
1523 DefineDefaultConstructor (true);
1526 if (Kind == Kind.Struct){
1528 // Structs can not have initialized instance
1531 if (initialized_static_fields != null &&
1532 default_static_constructor == null)
1533 DefineDefaultConstructor (true);
1535 if (initialized_fields != null)
1536 ReportStructInitializedInstanceError ();
1539 Pending = GetPendingImplementations ();
1541 if (parts != null) {
1542 foreach (ClassPart part in parts) {
1543 if (!part.DefineMembers (this))
1549 // Constructors are not in the defined_names array
1551 DefineContainerMembers (instance_constructors);
1553 if (default_static_constructor != null)
1554 default_static_constructor.Define ();
1556 DefineContainerMembers (properties);
1557 DefineContainerMembers (events);
1558 DefineContainerMembers (indexers);
1559 DefineContainerMembers (methods);
1560 DefineContainerMembers (operators);
1561 DefineContainerMembers (enums);
1562 DefineContainerMembers (delegates);
1564 if (CurrentType != null) {
1565 GenericType = CurrentType;
1567 ec.ContainerType = GenericType;
1572 if (!(this is ClassPart))
1573 member_cache = new MemberCache (this);
1576 if (parts != null) {
1577 foreach (ClassPart part in parts)
1578 part.member_cache = member_cache;
1581 if (iterators != null) {
1582 foreach (Iterator iterator in iterators) {
1583 if (iterator.DefineType () == null)
1587 foreach (Iterator iterator in iterators) {
1588 if (!iterator.DefineMembers (this))
1596 void ReportStructInitializedInstanceError ()
1598 string n = TypeBuilder.FullName;
1600 foreach (Field f in initialized_fields){
1603 "`" + n + "." + f.Name + "': can not have " +
1604 "instance field initializers in structs");
1608 protected virtual void DefineContainerMembers (MemberCoreArrayList mcal)
1611 mcal.DefineContainerMembers ();
1614 public override bool Define ()
1616 if (parts != null) {
1617 foreach (ClassPart part in parts) {
1618 if (!part.Define ())
1626 public MemberInfo FindBaseMemberWithSameName (string name, bool ignore_methods)
1628 return BaseCache.FindMemberWithSameName (name, ignore_methods, null);
1632 /// This function is based by a delegate to the FindMembers routine
1634 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1640 /// This filter is used by FindMembers, and we just keep
1641 /// a global for the filter to `AlwaysAccept'
1643 static MemberFilter accepting_filter;
1646 static TypeContainer ()
1648 accepting_filter = new MemberFilter (AlwaysAccept);
1651 public MethodInfo[] GetMethods ()
1653 ArrayList members = new ArrayList ();
1655 DefineMembers (null);
1657 if (methods != null) {
1658 int len = methods.Count;
1659 for (int i = 0; i < len; i++) {
1660 Method m = (Method) methods [i];
1662 members.Add (m.MethodBuilder);
1666 if (operators != null) {
1667 int len = operators.Count;
1668 for (int i = 0; i < len; i++) {
1669 Operator o = (Operator) operators [i];
1671 members.Add (o.OperatorMethodBuilder);
1675 if (properties != null) {
1676 int len = properties.Count;
1677 for (int i = 0; i < len; i++) {
1678 Property p = (Property) properties [i];
1680 if (p.GetBuilder != null)
1681 members.Add (p.GetBuilder);
1682 if (p.SetBuilder != null)
1683 members.Add (p.SetBuilder);
1687 if (indexers != null) {
1688 int len = indexers.Count;
1689 for (int i = 0; i < len; i++) {
1690 Indexer ix = (Indexer) indexers [i];
1692 if (ix.GetBuilder != null)
1693 members.Add (ix.GetBuilder);
1694 if (ix.SetBuilder != null)
1695 members.Add (ix.SetBuilder);
1699 if (events != null) {
1700 int len = events.Count;
1701 for (int i = 0; i < len; i++) {
1702 Event e = (Event) events [i];
1704 if (e.AddBuilder != null)
1705 members.Add (e.AddBuilder);
1706 if (e.RemoveBuilder != null)
1707 members.Add (e.RemoveBuilder);
1711 MethodInfo[] retMethods = new MethodInfo [members.Count];
1712 members.CopyTo (retMethods, 0);
1716 // Indicated whether container has StructLayout attribute set Explicit
1717 public virtual bool HasExplicitLayout {
1723 public override Type FindNestedType (string name)
1725 ArrayList [] lists = { types, enums, delegates, interfaces };
1727 for (int j = 0; j < lists.Length; ++j) {
1728 ArrayList list = lists [j];
1732 int len = list.Count;
1733 for (int i = 0; i < len; ++i) {
1734 DeclSpace ds = (DeclSpace) list [i];
1735 if (ds.Basename_with_arity == name) {
1737 return ds.TypeBuilder;
1745 private void FindMembers_NestedTypes (int modflags,
1746 BindingFlags bf, MemberFilter filter, object criteria,
1747 ref ArrayList members)
1749 ArrayList [] lists = { types, enums, delegates, interfaces };
1751 for (int j = 0; j < lists.Length; ++j) {
1752 ArrayList list = lists [j];
1756 int len = list.Count;
1757 for (int i = 0; i < len; i++) {
1758 DeclSpace ds = (DeclSpace) list [i];
1760 if ((ds.ModFlags & modflags) == 0)
1763 TypeBuilder tb = ds.TypeBuilder;
1765 if (!(criteria is string) || ds.Basename.Equals (criteria))
1766 tb = ds.DefineType ();
1769 if (tb != null && (filter (tb, criteria) == true)) {
1770 if (members == null)
1771 members = new ArrayList ();
1780 /// This method returns the members of this type just like Type.FindMembers would
1781 /// Only, we need to use this for types which are _being_ defined because MS'
1782 /// implementation can't take care of that.
1785 // FIXME: return an empty static array instead of null, that cleans up
1786 // some code and is consistent with some coding conventions I just found
1790 // Notice that in various cases we check if our field is non-null,
1791 // something that would normally mean that there was a bug elsewhere.
1793 // The problem happens while we are defining p-invoke methods, as those
1794 // will trigger a FindMembers, but this happens before things are defined
1796 // Since the whole process is a no-op, it is fine to check for null here.
1798 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1799 MemberFilter filter, object criteria)
1801 ArrayList members = null;
1804 if ((bf & BindingFlags.Public) != 0)
1805 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1807 if ((bf & BindingFlags.NonPublic) != 0)
1808 modflags |= Modifiers.PRIVATE;
1810 int static_mask = 0, static_flags = 0;
1811 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1812 case BindingFlags.Static:
1813 static_mask = static_flags = Modifiers.STATIC;
1816 case BindingFlags.Instance:
1817 static_mask = Modifiers.STATIC;
1822 static_mask = static_flags = 0;
1826 Timer.StartTimer (TimerType.TcFindMembers);
1829 filter = accepting_filter;
1831 if ((mt & MemberTypes.Field) != 0) {
1832 if (fields != null) {
1833 int len = fields.Count;
1834 for (int i = 0; i < len; i++) {
1835 FieldMember f = (FieldMember) fields [i];
1837 if ((f.ModFlags & modflags) == 0)
1839 if ((f.ModFlags & static_mask) != static_flags)
1842 FieldBuilder fb = f.FieldBuilder;
1843 if (fb != null && filter (fb, criteria) == true) {
1844 if (members == null)
1845 members = new ArrayList ();
1852 if (constants != null) {
1853 int len = constants.Count;
1854 for (int i = 0; i < len; i++) {
1855 Const con = (Const) constants [i];
1857 if ((con.ModFlags & modflags) == 0)
1859 if ((con.ModFlags & static_mask) != static_flags)
1862 FieldBuilder fb = con.FieldBuilder;
1865 fb = con.FieldBuilder;
1867 if (fb != null && filter (fb, criteria) == true) {
1868 if (members == null)
1869 members = new ArrayList ();
1877 if ((mt & MemberTypes.Method) != 0) {
1878 if (methods != null) {
1879 int len = methods.Count;
1880 for (int i = 0; i < len; i++) {
1881 Method m = (Method) methods [i];
1883 if ((m.ModFlags & modflags) == 0)
1885 if ((m.ModFlags & static_mask) != static_flags)
1888 MethodBuilder mb = m.MethodBuilder;
1890 if (mb != null && filter (mb, criteria) == true) {
1891 if (members == null)
1892 members = new ArrayList ();
1899 if (operators != null) {
1900 int len = operators.Count;
1901 for (int i = 0; i < len; i++) {
1902 Operator o = (Operator) operators [i];
1904 if ((o.ModFlags & modflags) == 0)
1906 if ((o.ModFlags & static_mask) != static_flags)
1909 MethodBuilder ob = o.OperatorMethodBuilder;
1910 if (ob != null && filter (ob, criteria) == true) {
1911 if (members == null)
1912 members = new ArrayList ();
1919 if (properties != null) {
1920 int len = properties.Count;
1921 for (int i = 0; i < len; i++) {
1922 Property p = (Property) properties [i];
1924 if ((p.ModFlags & modflags) == 0)
1926 if ((p.ModFlags & static_mask) != static_flags)
1932 if (b != null && filter (b, criteria) == true) {
1933 if (members == null)
1934 members = new ArrayList ();
1940 if (b != null && filter (b, criteria) == true) {
1941 if (members == null)
1942 members = new ArrayList ();
1949 if (indexers != null) {
1950 int len = indexers.Count;
1951 for (int i = 0; i < len; i++) {
1952 Indexer ix = (Indexer) indexers [i];
1954 if ((ix.ModFlags & modflags) == 0)
1956 if ((ix.ModFlags & static_mask) != static_flags)
1962 if (b != null && filter (b, criteria) == true) {
1963 if (members == null)
1964 members = new ArrayList ();
1970 if (b != null && filter (b, criteria) == true) {
1971 if (members == null)
1972 members = new ArrayList ();
1980 if ((mt & MemberTypes.Event) != 0) {
1981 if (events != null) {
1982 int len = events.Count;
1983 for (int i = 0; i < len; i++) {
1984 Event e = (Event) events [i];
1986 if ((e.ModFlags & modflags) == 0)
1988 if ((e.ModFlags & static_mask) != static_flags)
1991 MemberInfo eb = e.EventBuilder;
1992 if (eb != null && filter (eb, criteria) == true) {
1993 if (members == null)
1994 members = new ArrayList ();
1996 members.Add (e.EventBuilder);
2002 if ((mt & MemberTypes.Property) != 0){
2003 if (properties != null) {
2004 int len = properties.Count;
2005 for (int i = 0; i < len; i++) {
2006 Property p = (Property) properties [i];
2008 if ((p.ModFlags & modflags) == 0)
2010 if ((p.ModFlags & static_mask) != static_flags)
2013 MemberInfo pb = p.PropertyBuilder;
2014 if (pb != null && filter (pb, criteria) == true) {
2015 if (members == null)
2016 members = new ArrayList ();
2018 members.Add (p.PropertyBuilder);
2023 if (indexers != null) {
2024 int len = indexers.Count;
2025 for (int i = 0; i < len; i++) {
2026 Indexer ix = (Indexer) indexers [i];
2028 if ((ix.ModFlags & modflags) == 0)
2030 if ((ix.ModFlags & static_mask) != static_flags)
2033 MemberInfo ib = ix.PropertyBuilder;
2034 if (ib != null && filter (ib, criteria) == true) {
2035 if (members == null)
2036 members = new ArrayList ();
2038 members.Add (ix.PropertyBuilder);
2044 if ((mt & MemberTypes.NestedType) != 0)
2045 FindMembers_NestedTypes (modflags, bf, filter, criteria, ref members);
2047 if ((mt & MemberTypes.Constructor) != 0){
2048 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
2049 int len = instance_constructors.Count;
2050 for (int i = 0; i < len; i++) {
2051 Constructor c = (Constructor) instance_constructors [i];
2053 ConstructorBuilder cb = c.ConstructorBuilder;
2054 if (cb != null && filter (cb, criteria) == true) {
2055 if (members == null)
2056 members = new ArrayList ();
2063 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
2064 ConstructorBuilder cb =
2065 default_static_constructor.ConstructorBuilder;
2067 if (cb != null && filter (cb, criteria) == true) {
2068 if (members == null)
2069 members = new ArrayList ();
2077 // Lookup members in base if requested.
2079 if ((bf & BindingFlags.DeclaredOnly) == 0) {
2080 if (TypeBuilder.BaseType != null) {
2081 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
2082 if (list.Count > 0) {
2083 if (members == null)
2084 members = new ArrayList ();
2086 members.AddRange (list);
2092 Timer.StopTimer (TimerType.TcFindMembers);
2094 if (members == null)
2095 return MemberList.Empty;
2097 return new MemberList (members);
2100 public override MemberCache MemberCache {
2102 return member_cache;
2106 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
2107 MemberFilter filter, object criteria)
2109 DeclSpace ds = TypeManager.LookupDeclSpace (t);
2112 return ds.FindMembers (mt, bf, filter, criteria);
2114 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
2118 // FindMethods will look for methods not only in the type `t', but in
2119 // any interfaces implemented by the type.
2121 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
2122 MemberFilter filter, object criteria)
2128 /// Emits the values for the constants
2130 public void EmitConstants ()
2132 if (constants != null)
2133 foreach (Const con in constants)
2138 protected virtual void VerifyMembers (EmitContext ec)
2141 // Check for internal or private fields that were never assigned
2143 if (RootContext.WarningLevel >= 4) {
2144 if (fields != null){
2145 foreach (Field f in fields) {
2146 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
2149 if ((f.status & Field.Status.USED) == 0){
2150 Report.Warning (169, f.Location, "The private field '{0}' is never used", f.GetSignatureForError ());
2155 // Only report 649 on level 4
2157 if (RootContext.WarningLevel < 4)
2160 if ((f.status & Field.Status.ASSIGNED) != 0)
2163 Report.Warning (649, f.Location, "Field '{0}' is never assigned to, and will always have its default value '{1}'", f.GetSignatureForError (), "");
2170 /// Emits the code, this step is performed after all
2171 /// the types, enumerations, constructors
2173 public void EmitType ()
2175 if (OptAttributes != null)
2176 OptAttributes.Emit (ec, this);
2180 if (instance_constructors != null) {
2181 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && RootContext.VerifyClsCompliance && IsClsCompliaceRequired (this)) {
2182 bool has_compliant_args = false;
2184 foreach (Constructor c in instance_constructors) {
2187 if (has_compliant_args)
2190 has_compliant_args = c.HasCompliantArgs;
2192 if (!has_compliant_args)
2193 Report.Error (3015, Location, "'{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2195 foreach (Constructor c in instance_constructors)
2202 if (default_static_constructor != null)
2203 default_static_constructor.Emit ();
2205 if (methods != null)
2206 foreach (Method m in methods)
2209 if (operators != null)
2210 foreach (Operator o in operators)
2213 if (properties != null)
2214 foreach (Property p in properties)
2217 if (indexers != null){
2222 foreach (FieldMember f in fields)
2225 if (events != null){
2226 foreach (Event e in Events)
2230 if (delegates != null) {
2231 foreach (Delegate d in Delegates) {
2236 if (enums != null) {
2237 foreach (Enum e in enums) {
2242 if (parts != null) {
2243 foreach (ClassPart part in parts)
2247 if ((Pending != null) && !(this is ClassPart))
2248 if (Pending.VerifyPendingMethods ())
2253 if (iterators != null)
2254 foreach (Iterator iterator in iterators)
2255 iterator.EmitType ();
2257 // if (types != null)
2258 // foreach (TypeContainer tc in types)
2262 public override void CloseType ()
2264 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2268 caching_flags |= Flags.CloseTypeCreated;
2269 TypeBuilder.CreateType ();
2270 } catch (TypeLoadException){
2272 // This is fine, the code still created the type
2274 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
2275 // Console.WriteLine (e.Message);
2277 Console.WriteLine ("In type: " + Name);
2282 foreach (Enum en in Enums)
2286 foreach (TypeContainer tc in Types)
2287 if (tc.Kind == Kind.Struct)
2290 foreach (TypeContainer tc in Types)
2291 if (tc.Kind != Kind.Struct)
2295 if (Delegates != null)
2296 foreach (Delegate d in Delegates)
2299 if (Iterators != null)
2300 foreach (Iterator i in Iterators)
2308 initialized_fields = null;
2309 initialized_static_fields = null;
2318 default_constructor = null;
2319 default_static_constructor = null;
2321 OptAttributes = null;
2324 member_cache = null;
2327 // TODO: make it obsolete and use GetSignatureForError
2328 public string MakeName (string n)
2330 return "`" + Name + "." + n + "'";
2334 // Performs the validation on a Method's modifiers (properties have
2335 // the same properties).
2337 public bool MethodModifiersValid (MemberCore mc)
2339 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2340 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2341 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2343 int flags = mc.ModFlags;
2346 // At most one of static, virtual or override
2348 if ((flags & Modifiers.STATIC) != 0){
2349 if ((flags & vao) != 0){
2350 Report.Error (112, mc.Location, "static method '{0}' can not be marked as virtual, abstract or override",
2351 GetSignatureForError ());
2356 if (Kind == Kind.Struct){
2357 if ((flags & va) != 0){
2358 Modifiers.Error_InvalidModifier (mc.Location, "virtual or abstract");
2363 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2364 Report.Error (113, mc.Location, "'{0}' marked as override cannot be marked as new or virtual", mc.GetSignatureForError ());
2369 // If the declaration includes the abstract modifier, then the
2370 // declaration does not include static, virtual or extern
2372 if ((flags & Modifiers.ABSTRACT) != 0){
2373 if ((flags & Modifiers.EXTERN) != 0){
2375 180, mc.Location, "'{0}' can not be both abstract and extern", mc.GetSignatureForError ());
2379 if ((flags & Modifiers.SEALED) != 0) {
2380 Report.Error (502, mc.Location, "'{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2384 if ((flags & Modifiers.VIRTUAL) != 0){
2385 Report.Error (503, mc.Location, "'{0}' can not be both abstract and virtual", mc.GetSignatureForError ());
2389 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2390 Report.Error (513, mc.Location, "'{0}' is abstract but its container class is not", mc.GetSignatureForError ());
2395 if ((flags & Modifiers.PRIVATE) != 0){
2396 if ((flags & vao) != 0){
2397 Report.Error (621, mc.Location, "'{0}' virtual or abstract members can not be private", mc.GetSignatureForError ());
2402 if ((flags & Modifiers.SEALED) != 0){
2403 if ((flags & Modifiers.OVERRIDE) == 0){
2404 Report.Error (238, mc.Location, "'{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2412 public bool UserDefinedStaticConstructor {
2414 return default_static_constructor != null;
2418 public Constructor DefaultStaticConstructor {
2419 get { return default_static_constructor; }
2422 protected override bool VerifyClsCompliance (DeclSpace ds)
2424 if (!base.VerifyClsCompliance (ds))
2430 Report.Error (3024, Location, "'{0}': type parameters are not CLS-compliant",
2431 GetSignatureForError ());
2435 Type base_type = TypeBuilder.BaseType;
2436 if (base_type != null && !AttributeTester.IsClsCompliant (base_type)) {
2437 Report.Error (3009, Location, "'{0}': base type '{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (base_type));
2440 if (!Parent.IsClsCompliaceRequired (ds)) {
2441 Report.Error (3018, Location, "'{0}' cannot be marked as CLS-Compliant because it is a member of non CLS-Compliant type '{1}'",
2442 GetSignatureForError (), Parent.GetSignatureForError ());
2449 /// Checks whether container name is CLS Compliant
2451 void VerifyClsName ()
2453 Hashtable base_members = base_cache == null ?
2455 base_cache.GetPublicMembers ();
2456 Hashtable this_members = new Hashtable ();
2458 foreach (DictionaryEntry entry in defined_names) {
2459 MemberCore mc = (MemberCore)entry.Value;
2460 if (!mc.IsClsCompliaceRequired (this))
2463 string name = (string)entry.Key;
2464 string basename = name.Substring (name.LastIndexOf ('.') + 1);
2466 string lcase = basename.ToLower (System.Globalization.CultureInfo.InvariantCulture);
2467 object found = base_members [lcase];
2468 if (found == null) {
2469 found = this_members [lcase];
2470 if (found == null) {
2471 this_members.Add (lcase, mc);
2476 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
2479 if (found is MemberInfo) {
2480 if (basename == ((MemberInfo)found).Name)
2482 Report.SymbolRelatedToPreviousError ((MemberInfo)found);
2484 Report.SymbolRelatedToPreviousError ((MemberCore) found);
2486 Report.Error (3005, mc.Location, "Identifier '{0}' differing only in case is not CLS-compliant", mc.GetSignatureForError ());
2492 /// Performs checks for an explicit interface implementation. First it
2493 /// checks whether the `interface_type' is a base inteface implementation.
2494 /// Then it checks whether `name' exists in the interface type.
2496 public virtual bool VerifyImplements (Type interface_type, string full,
2497 string name, Location loc)
2501 if (ifaces != null){
2502 foreach (Type t in ifaces){
2503 if (t == interface_type){
2511 Report.Error (540, loc, "`{0}': containing class does not implement interface `{1}'",
2512 full, interface_type.FullName);
2519 protected override void VerifyObsoleteAttribute()
2521 CheckUsageOfObsoleteAttribute (TypeBuilder.BaseType);
2526 foreach (Type iface in ifaces) {
2527 CheckUsageOfObsoleteAttribute (iface);
2535 string IMemberContainer.Name {
2541 Type IMemberContainer.Type {
2547 MemberCache IMemberContainer.MemberCache {
2549 return member_cache;
2553 bool IMemberContainer.IsInterface {
2555 return Kind == Kind.Interface;
2559 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2561 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2563 if (GenericType != null)
2564 return TypeManager.FindMembers (GenericType, mt, new_bf,
2567 return FindMembers (mt, new_bf, null, null);
2571 // Generates xml doc comments (if any), and if required,
2572 // handle warning report.
2574 internal override void GenerateDocComment (DeclSpace ds)
2576 DocUtil.GenerateTypeDocComment (this, ds);
2579 public override string DocCommentHeader {
2580 get { return "T:"; }
2583 public virtual MemberCache BaseCache {
2585 if (base_cache != null)
2587 if (TypeBuilder.BaseType != null)
2588 base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
2589 if (TypeBuilder.IsInterface)
2590 base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
2597 public class PartialContainer : TypeContainer {
2599 public readonly Namespace Namespace;
2600 public readonly int OriginalModFlags;
2601 public readonly int AllowedModifiers;
2602 public readonly TypeAttributes DefaultTypeAttributes;
2604 static PartialContainer Create (NamespaceEntry ns, TypeContainer parent,
2605 MemberName member_name, int mod_flags, Kind kind,
2608 PartialContainer pc;
2609 string full_name = member_name.GetName (true);
2610 DeclSpace ds = (DeclSpace) RootContext.Tree.Decls [full_name];
2612 pc = ds as PartialContainer;
2616 260, ds.Location, "Missing partial modifier " +
2617 "on declaration of type `{0}'; another " +
2618 "partial implementation of this type exists",
2619 member_name.GetTypeName());
2621 Report.LocationOfPreviousError (loc);
2625 if (pc.Kind != kind) {
2627 261, loc, "Partial declarations of `{0}' " +
2628 "must be all classes, all structs or " +
2629 "all interfaces", member_name.GetTypeName ());
2633 if (pc.OriginalModFlags != mod_flags) {
2635 262, loc, "Partial declarations of `{0}' " +
2636 "have conflicting accessibility modifiers",
2637 member_name.GetTypeName ());
2642 if (pc.CountTypeParameters != member_name.CountTypeArguments) {
2644 264, loc, "Partial declarations of `{0}' " +
2645 "must have the same type parameter names in " +
2646 "the same order", member_name.GetTypeName ());
2650 string[] pc_names = pc.MemberName.TypeArguments.GetDeclarations ();
2651 string[] names = member_name.TypeArguments.GetDeclarations ();
2653 for (int i = 0; i < pc.CountTypeParameters; i++) {
2654 if (pc_names [i] == names [i])
2658 264, loc, "Partial declarations of `{0}' " +
2659 "must have the same type parameter names in " +
2660 "the same order", member_name.GetTypeName ());
2668 if (parent is ClassPart)
2669 parent = ((ClassPart) parent).PartialContainer;
2671 pc = new PartialContainer (ns.NS, parent, member_name, mod_flags, kind, loc);
2672 RootContext.Tree.RecordDecl (full_name, pc);
2674 if (kind == Kind.Interface)
2675 parent.AddInterface (pc);
2676 else if (kind == Kind.Class || kind == Kind.Struct)
2677 parent.AddClassOrStruct (pc);
2679 throw new InvalidOperationException ();
2681 // This is needed to define our type parameters; we define the constraints later.
2682 pc.SetParameterInfo (null);
2686 public static ClassPart CreatePart (NamespaceEntry ns, TypeContainer parent,
2687 MemberName name, int mod, Attributes attrs,
2688 Kind kind, Location loc)
2690 PartialContainer pc = Create (ns, parent, name, mod, kind, loc);
2692 // An error occured; create a dummy container, but don't
2694 pc = new PartialContainer (ns.NS, parent, name, mod, kind, loc);
2697 ClassPart part = new ClassPart (ns, pc, parent, mod, attrs, kind, loc);
2702 protected PartialContainer (Namespace ns, TypeContainer parent,
2703 MemberName name, int mod, Kind kind, Location l)
2704 : base (null, parent, name, null, kind, l)
2706 this.Namespace = ns;
2710 AllowedModifiers = Class.AllowedModifiers;
2711 DefaultTypeAttributes = Class.DefaultTypeAttributes;
2715 AllowedModifiers = Struct.AllowedModifiers;
2716 DefaultTypeAttributes = Struct.DefaultTypeAttributes;
2719 case Kind.Interface:
2720 AllowedModifiers = Interface.AllowedModifiers;
2721 DefaultTypeAttributes = Interface.DefaultTypeAttributes;
2725 throw new InvalidOperationException ();
2729 if (parent.Parent == null)
2730 accmods = Modifiers.INTERNAL;
2732 accmods = Modifiers.PRIVATE;
2734 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2735 this.OriginalModFlags = mod;
2738 public override PendingImplementation GetPendingImplementations ()
2740 return PendingImplementation.GetPendingImplementations (this);
2743 public override TypeAttributes TypeAttr {
2745 return base.TypeAttr | DefaultTypeAttributes;
2750 public class ClassPart : TypeContainer, IMemberContainer {
2751 public readonly PartialContainer PartialContainer;
2752 public readonly bool IsPartial;
2754 Constraints[] constraints;
2756 public ClassPart (NamespaceEntry ns, PartialContainer pc, TypeContainer parent,
2757 int mod, Attributes attrs, Kind kind, Location l)
2758 : base (ns, parent, pc.MemberName, attrs, kind, l)
2760 this.PartialContainer = pc;
2761 this.IsPartial = true;
2764 if (parent == null || parent == RootContext.Tree.Types)
2765 accmods = Modifiers.INTERNAL;
2767 accmods = Modifiers.PRIVATE;
2769 this.ModFlags = Modifiers.Check (pc.AllowedModifiers, mod, accmods, l);
2772 constraints = new Constraints [pc.CountCurrentTypeParameters];
2775 public override PendingImplementation GetPendingImplementations ()
2777 return PartialContainer.Pending;
2780 public override bool VerifyImplements (Type interface_type, string full,
2781 string name, Location loc)
2783 return PartialContainer.VerifyImplements (
2784 interface_type, full, name, loc);
2787 public override void SetParameterInfo (ArrayList constraints_list)
2789 if (constraints_list == null)
2792 TypeParameter[] current_params = PartialContainer.CurrentTypeParameters;
2793 for (int i = 0; i < constraints.Length; i++) {
2794 foreach (Constraints constraint in constraints_list) {
2795 if (constraint.TypeParameter == current_params [i].Name) {
2796 constraints [i] = constraint;
2803 public bool DefineTypeParameters ()
2805 TypeParameter[] current_params = PartialContainer.CurrentTypeParameters;
2807 for (int i = 0; i < current_params.Length; i++) {
2808 Constraints new_constraints = constraints [i];
2809 if (new_constraints == null)
2812 if (!current_params [i].UpdateConstraints (ec, new_constraints)) {
2813 Report.Error (265, Location, "Partial declarations of `{0}' have " +
2814 "inconsistent constraints for type parameter `{1}'.",
2815 MemberName.GetTypeName (), current_params [i].Name);
2820 for (int i = 0; i < current_params.Length; i++) {
2821 if (!current_params [i].Resolve (this))
2825 for (int i = 0; i < current_params.Length; i++)
2826 current_params [i].DefineConstraints ();
2828 foreach (TypeParameter type_param in PartialContainer.TypeParameters) {
2829 if (!type_param.DefineType (ec))
2836 public override bool EmitFieldInitializers (EmitContext ec)
2838 return PartialContainer.EmitFieldInitializers (ec);
2841 public override Type FindNestedType (string name)
2843 return PartialContainer.FindNestedType (name);
2846 public override MemberCache BaseCache {
2848 return PartialContainer.BaseCache;
2853 public abstract class ClassOrStruct : TypeContainer {
2854 bool hasExplicitLayout = false;
2855 ListDictionary declarative_security;
2857 public ClassOrStruct (NamespaceEntry ns, TypeContainer parent,
2858 MemberName name, Attributes attrs, Kind kind,
2860 : base (ns, parent, name, attrs, kind, l)
2864 public override PendingImplementation GetPendingImplementations ()
2866 return PendingImplementation.GetPendingImplementations (this);
2869 public override bool HasExplicitLayout {
2871 return hasExplicitLayout;
2875 protected override void VerifyMembers (EmitContext ec)
2877 base.VerifyMembers (ec);
2879 if ((events != null) && (RootContext.WarningLevel >= 3)) {
2880 foreach (Event e in events){
2882 Report.Warning (67, e.Location, "The event '{0}' is never used", e.GetSignatureForError ());
2887 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2889 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
2890 if (declarative_security == null)
2891 declarative_security = new ListDictionary ();
2893 a.ExtractSecurityPermissionSet (declarative_security);
2897 if (a.Type == TypeManager.struct_layout_attribute_type &&
2898 a.GetLayoutKindValue () == LayoutKind.Explicit)
2899 hasExplicitLayout = true;
2901 base.ApplyAttributeBuilder (a, cb);
2904 public override void Emit()
2908 if (declarative_security != null) {
2909 foreach (DictionaryEntry de in declarative_security) {
2910 TypeBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
2917 /// Class handles static classes declaration
2919 public sealed class StaticClass: Class {
2920 public StaticClass (NamespaceEntry ns, TypeContainer parent, MemberName name, int mod,
2921 Attributes attrs, Location l)
2922 : base (ns, parent, name, mod, attrs, l)
2924 if (RootContext.Version == LanguageVersion.ISO_1) {
2925 Report.FeatureIsNotStandardized (l, "static classes");
2929 protected override int AllowedModifiersProp {
2931 return Modifiers.NEW | Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE |
2932 Modifiers.STATIC | Modifiers.UNSAFE;
2936 protected override void DefineContainerMembers (MemberCoreArrayList list)
2941 foreach (MemberCore m in list) {
2942 if (m is Operator) {
2943 Report.Error (715, m.Location, "'{0}': static classes cannot contain user-defined operators", m.GetSignatureForError (this));
2947 if ((m.ModFlags & Modifiers.PROTECTED) != 0)
2948 Report.Warning (628, 4, m.Location, "'{0}': new protected member declared in static class", m.GetSignatureForError (this));
2950 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is Enum || m is Delegate)
2953 if (m is Constructor) {
2954 Report.Error (710, m.Location, "'{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2958 if (m is Destructor) {
2959 Report.Error (711, m.Location, "'{0}': Static class cannot contain destructor", GetSignatureForError ());
2962 Report.Error (708, m.Location, "'{0}': cannot declare instance members in a static class", m.GetSignatureForError (this));
2965 base.DefineContainerMembers (list);
2968 public override TypeBuilder DefineType()
2970 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2971 Report.Error (441, Location, "'{0}': a class cannot be both static and sealed", GetSignatureForError ());
2975 TypeBuilder tb = base.DefineType ();
2979 if ((ptype != null) && (ptype != TypeManager.object_type)) {
2982 "Static class '{0}' cannot derive from type '{1}'. " +
2983 "Static classes must derive from object",
2984 GetSignatureForError (), ptype);
2988 if (ifaces != null) {
2989 foreach (Type t in ifaces)
2990 Report.SymbolRelatedToPreviousError (t);
2993 "'{0}': static classes cannot implement interfaces",
2994 GetSignatureForError ());
2999 public override TypeAttributes TypeAttr {
3001 return base.TypeAttr | TypeAttributes.Abstract | TypeAttributes.Sealed;
3006 public class Class : ClassOrStruct {
3007 // TODO: remove this and use only AllowedModifiersProp to fix partial classes bugs
3008 public const int AllowedModifiers =
3011 Modifiers.PROTECTED |
3012 Modifiers.INTERNAL |
3014 Modifiers.ABSTRACT |
3018 public Class (NamespaceEntry ns, TypeContainer parent, MemberName name, int mod,
3019 Attributes attrs, Location l)
3020 : base (ns, parent, name, attrs, Kind.Class, l)
3022 this.ModFlags = mod;
3025 virtual protected int AllowedModifiersProp {
3027 return AllowedModifiers;
3031 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
3033 if (a.Type == TypeManager.attribute_usage_type) {
3034 if (ptype != TypeManager.attribute_type &&
3035 !ptype.IsSubclassOf (TypeManager.attribute_type) &&
3036 TypeBuilder.FullName != "System.Attribute") {
3037 Report.Error (641, a.Location, "Attribute '{0}' is only valid on classes derived from System.Attribute", a.Name);
3041 base.ApplyAttributeBuilder (a, cb);
3044 public const TypeAttributes DefaultTypeAttributes =
3045 TypeAttributes.AutoLayout | TypeAttributes.Class;
3047 public override TypeBuilder DefineType()
3049 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
3050 Report.Error (418, Location, "'{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
3054 int accmods = Parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3055 ModFlags = Modifiers.Check (AllowedModifiersProp, ModFlags, accmods, Location);
3057 return base.DefineType ();
3061 // FIXME: How do we deal with the user specifying a different
3064 public override TypeAttributes TypeAttr {
3066 return base.TypeAttr | DefaultTypeAttributes;
3071 public class Struct : ClassOrStruct {
3073 // Modifiers allowed in a struct declaration
3075 public const int AllowedModifiers =
3078 Modifiers.PROTECTED |
3079 Modifiers.INTERNAL |
3083 public Struct (NamespaceEntry ns, TypeContainer parent, MemberName name,
3084 int mod, Attributes attrs, Location l)
3085 : base (ns, parent, name, attrs, Kind.Struct, l)
3089 if (parent.Parent == null)
3090 accmods = Modifiers.INTERNAL;
3092 accmods = Modifiers.PRIVATE;
3094 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
3096 this.ModFlags |= Modifiers.SEALED;
3099 public const TypeAttributes DefaultTypeAttributes =
3100 TypeAttributes.SequentialLayout |
3101 TypeAttributes.Sealed |
3102 TypeAttributes.BeforeFieldInit;
3105 // FIXME: Allow the user to specify a different set of attributes
3106 // in some cases (Sealed for example is mandatory for a class,
3107 // but what SequentialLayout can be changed
3109 public override TypeAttributes TypeAttr {
3111 return base.TypeAttr | DefaultTypeAttributes;
3119 public class Interface : TypeContainer, IMemberContainer {
3121 /// Modifiers allowed in a class declaration
3123 public const int AllowedModifiers =
3126 Modifiers.PROTECTED |
3127 Modifiers.INTERNAL |
3131 public Interface (NamespaceEntry ns, TypeContainer parent, MemberName name,
3132 int mod, Attributes attrs, Location l)
3133 : base (ns, parent, name, attrs, Kind.Interface, l)
3137 if (parent.Parent == null)
3138 accmods = Modifiers.INTERNAL;
3140 accmods = Modifiers.PRIVATE;
3142 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
3145 public override PendingImplementation GetPendingImplementations ()
3150 public const TypeAttributes DefaultTypeAttributes =
3151 TypeAttributes.AutoLayout |
3152 TypeAttributes.Abstract |
3153 TypeAttributes.Interface;
3155 public override TypeAttributes TypeAttr {
3157 return base.TypeAttr | DefaultTypeAttributes;
3162 public abstract class MethodCore : MemberBase {
3163 public readonly Parameters Parameters;
3164 public readonly GenericMethod GenericMethod;
3165 public readonly DeclSpace ds;
3166 protected ToplevelBlock block;
3169 // Parameters, cached for semantic analysis.
3171 protected InternalParameters parameter_info;
3172 protected Type [] parameter_types;
3174 // Whether this is an operator method.
3175 public bool IsOperator;
3178 // The method we're overriding if this is an override method.
3180 protected MethodInfo base_method = null;
3182 static string[] attribute_targets = new string [] { "method", "return" };
3184 public MethodCore (TypeContainer parent, GenericMethod generic,
3185 Expression type, int mod, int allowed_mod, bool is_iface,
3186 MemberName name, Attributes attrs, Parameters parameters,
3188 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name,
3191 Parameters = parameters;
3192 IsInterface = is_iface;
3193 this.GenericMethod = generic;
3195 if (generic != null)
3202 // Returns the System.Type array for the parameters of this method
3204 public Type [] ParameterTypes {
3206 return parameter_types;
3210 public InternalParameters ParameterInfo
3213 return parameter_info;
3217 public ToplevelBlock Block {
3227 protected override bool CheckBase ()
3229 if (!base.CheckBase ())
3232 // Check whether arguments were correct.
3233 if (!DoDefineParameters ())
3236 if ((caching_flags & Flags.TestMethodDuplication) != 0 && !CheckForDuplications ())
3242 // Is null for System.Object while compiling corlib and base interfaces
3243 if (Parent.BaseCache == null) {
3244 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
3245 Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError (Parent));
3250 Type base_ret_type = null;
3251 base_method = FindOutBaseMethod (Parent, ref base_ret_type);
3253 // method is override
3254 if (base_method != null) {
3256 if (!CheckMethodAgainstBase ())
3259 if ((ModFlags & Modifiers.NEW) == 0) {
3260 if (MemberType != TypeManager.TypeToCoreType (base_ret_type)) {
3261 Report.SymbolRelatedToPreviousError (base_method);
3262 Report.Error (508, Location, GetSignatureForError (Parent) + ": cannot " +
3263 "change return type when overriding inherited member");
3267 if (base_method.IsAbstract && !IsInterface) {
3268 Report.SymbolRelatedToPreviousError (base_method);
3269 Report.Error (533, Location, "'{0}' hides inherited abstract member", GetSignatureForError (Parent));
3274 if (base_method.IsSpecialName && !(this is PropertyBase)) {
3275 Report.Error (561, Location, "'{0}': cannot override '{1}' because it is a special compiler-generated method", GetSignatureForError (Parent), TypeManager.GetFullNameSignature (base_method));
3279 if (RootContext.WarningLevel > 2) {
3280 if (Name == "Equals" && parameter_types.Length == 1 && parameter_types [0] == TypeManager.object_type)
3281 Parent.Methods.HasEquals = true;
3282 else if (Name == "GetHashCode" && parameter_types.Length == 0)
3283 Parent.Methods.HasGetHashCode = true;
3286 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3287 ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (base_method);
3289 EmitContext ec = new EmitContext (this.Parent, this.Parent, Location, null, null, ModFlags, false);
3290 if (OptAttributes == null || !OptAttributes.Contains (TypeManager.obsolete_attribute_type, ec)) {
3291 Report.SymbolRelatedToPreviousError (base_method);
3292 Report.Warning (672, 1, Location, "Member '{0}' overrides obsolete member. Add the Obsolete attribute to '{0}'", GetSignatureForError (Parent));
3299 MemberInfo conflict_symbol = Parent.FindBaseMemberWithSameName (Name, !(this is Property));
3300 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3301 if (conflict_symbol != null) {
3302 Report.SymbolRelatedToPreviousError (conflict_symbol);
3303 if (this is PropertyBase)
3304 Report.Error (544, Location, "'{0}': cannot override because '{1}' is not a property", GetSignatureForError (Parent), TypeManager.GetFullNameSignature (conflict_symbol));
3306 Report.Error (505, Location, "'{0}': cannot override because '{1}' is not a method", GetSignatureForError (Parent), TypeManager.GetFullNameSignature (conflict_symbol));
3308 Report.Error (115, Location, "'{0}': no suitable methods found to override", GetSignatureForError (Parent));
3312 if (conflict_symbol == null) {
3313 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
3314 Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError (Parent));
3319 if ((ModFlags & Modifiers.NEW) == 0) {
3320 if (this is Method && conflict_symbol is MethodBase)
3323 Report.SymbolRelatedToPreviousError (conflict_symbol);
3324 Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
3332 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3333 // that have been defined.
3335 // `name' is the user visible name for reporting errors (this is used to
3336 // provide the right name regarding method names and properties)
3338 bool CheckMethodAgainstBase ()
3342 // TODO: replace with GetSignatureForError
3343 string name = base_method.DeclaringType.Name + "." + base_method.Name;
3345 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3346 if (!(base_method.IsAbstract || base_method.IsVirtual)){
3348 506, Location, Parent.MakeName (Name) +
3349 ": cannot override inherited member `" +
3350 name + "' because it is not " +
3351 "virtual, abstract or override");
3355 // Now we check that the overriden method is not final
3357 if (base_method.IsFinal) {
3358 Report.SymbolRelatedToPreviousError (base_method);
3359 Report.Error (239, Location, "'{0}': cannot override inherited member '{1}' because it is sealed",
3360 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3364 // Check that the permissions are not being changed
3366 MethodAttributes thisp = flags & MethodAttributes.MemberAccessMask;
3367 MethodAttributes base_classp = base_method.Attributes & MethodAttributes.MemberAccessMask;
3369 if (!CheckAccessModifiers (thisp, base_classp, base_method)) {
3370 Error_CannotChangeAccessModifiers (Parent, base_method, name);
3375 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0 && Name != "Finalize") {
3376 ModFlags |= Modifiers.NEW;
3377 Report.SymbolRelatedToPreviousError (base_method);
3378 if (!IsInterface && (base_method.IsVirtual || base_method.IsAbstract)) {
3379 if (RootContext.WarningLevel >= 2)
3380 Report.Warning (114, Location, "'{0}' hides inherited member '{1}'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword", GetSignatureForError (Parent), TypeManager.CSharpSignature (base_method));
3382 Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
3388 protected bool CheckAccessModifiers (MethodAttributes thisp, MethodAttributes base_classp, MethodInfo base_method)
3390 if ((base_classp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3392 // when overriding protected internal, the method can be declared
3393 // protected internal only within the same assembly
3396 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3397 if (Parent.TypeBuilder.Assembly != base_method.DeclaringType.Assembly){
3399 // assemblies differ - report an error
3403 } else if (thisp != base_classp) {
3405 // same assembly, but other attributes differ - report an error
3410 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3412 // if it's not "protected internal", it must be "protected"
3416 } else if (Parent.TypeBuilder.Assembly == base_method.DeclaringType.Assembly) {
3418 // protected within the same assembly - an error
3421 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3422 (base_classp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3424 // protected ok, but other attributes differ - report an error
3430 return (thisp == base_classp);
3434 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo base_method, string name)
3437 // FIXME: report the old/new permissions?
3440 507, Location, parent.MakeName (Name) +
3441 ": can't change the access modifiers when overriding inherited " +
3442 "member `" + name + "'");
3445 protected static string Error722 {
3447 return "'{0}': static types cannot be used as return types";
3452 /// For custom member duplication search in a container
3454 protected abstract bool CheckForDuplications ();
3457 /// Gets base method and its return type
3459 protected abstract MethodInfo FindOutBaseMethod (TypeContainer container, ref Type base_ret_type);
3461 protected virtual bool DoDefineParameters ()
3463 EmitContext ec = ds.EmitContext;
3465 throw new InternalErrorException ("DoDefineParameters invoked too early");
3467 bool old_unsafe = ec.InUnsafe;
3468 ec.InUnsafe = InUnsafe;
3469 // Check if arguments were correct
3470 parameter_types = Parameters.GetParameterInfo (ec);
3471 ec.InUnsafe = old_unsafe;
3473 if ((parameter_types == null) ||
3474 !CheckParameters (ds, parameter_types))
3477 TypeParameter[] tparam = ds.IsGeneric ? ds.TypeParameters : null;
3478 parameter_info = new InternalParameters (parameter_types, Parameters, tparam);
3480 Parameter array_param = Parameters.ArrayParameter;
3481 if ((array_param != null) &&
3482 (!array_param.ParameterType.IsArray ||
3483 (array_param.ParameterType.GetArrayRank () != 1))) {
3484 Report.Error (225, Location, "params parameter has to be a single dimensional array");
3491 void error_425 (Type old, Type t, string name)
3493 Report.Error (425, Location,
3494 "The constraints of type parameter `{0}' " +
3495 "of method `{1}' must match the constraints for " +
3496 "type parameter `{2}' of method `{3}'",
3497 TypeManager.CSharpName (old), Name,
3498 TypeManager.CSharpName (t), name);
3501 protected override bool CheckGenericOverride (MethodInfo method, string name)
3503 ParameterData pd = TypeManager.GetParameterData (method);
3505 for (int i = 0; i < ParameterTypes.Length; i++) {
3506 GenericConstraints ogc = pd.GenericConstraints (i);
3507 GenericConstraints gc = ParameterInfo.GenericConstraints (i);
3509 if ((gc == null) && (ogc == null))
3512 Type ot = pd.ParameterType (i);
3513 Type t = ParameterTypes [i];
3515 if (!((gc != null) && (ogc != null))) {
3516 error_425 (ot, t, name);
3520 if ((gc.Attributes != ogc.Attributes) ||
3521 (gc.HasClassConstraint != ogc.HasClassConstraint)) {
3522 error_425 (ot, t, name);
3526 if (ogc.HasClassConstraint &&
3527 !ogc.ClassConstraint.Equals (gc.ClassConstraint)) {
3528 error_425 (ot, t, name);
3532 Type[] oct = ogc.InterfaceConstraints;
3533 Type[] ct = gc.InterfaceConstraints;
3535 if (oct.Length != ct.Length) {
3536 error_425 (ot, t, name);
3540 for (int j = 0; j < oct.Length; j++)
3541 if (!oct [j].Equals (ct [j])) {
3542 error_425 (ot, t, name);
3550 public override string[] ValidAttributeTargets {
3552 return attribute_targets;
3556 protected override bool VerifyClsCompliance (DeclSpace ds)
3558 if (!base.VerifyClsCompliance (ds)) {
3559 if ((ModFlags & Modifiers.ABSTRACT) != 0 && IsExposedFromAssembly (ds) && ds.IsClsCompliaceRequired (ds)) {
3560 Report.Error (3011, Location, "'{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
3565 if (Parameters.HasArglist) {
3566 Report.Error (3000, Location, "Methods with variable arguments are not CLS-compliant");
3569 if (!AttributeTester.IsClsCompliant (MemberType)) {
3570 if (this is PropertyBase)
3571 Report.Error (3003, Location, "Type of `{0}' is not CLS-compliant",
3572 GetSignatureForError ());
3574 Report.Error (3002, Location, "Return type of '{0}' is not CLS-compliant",
3575 GetSignatureForError ());
3578 AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location);
3583 bool MayUnify (MethodCore first, MethodCore second)
3585 int a_type_params = 0;
3586 if (first.GenericMethod != null)
3587 a_type_params = first.GenericMethod.CountTypeParameters;
3589 int b_type_params = 0;
3590 if (second.GenericMethod != null)
3591 b_type_params = second.GenericMethod.CountTypeParameters;
3593 if (a_type_params != b_type_params)
3596 Type[] class_infered, method_infered;
3597 if (Parent.CountTypeParameters > 0)
3598 class_infered = new Type [Parent.CountTypeParameters];
3600 class_infered = null;
3602 if (a_type_params > 0)
3603 method_infered = new Type [a_type_params];
3605 method_infered = null;
3607 return TypeManager.MayBecomeEqualGenericInstances (
3608 first.ParameterTypes, second.ParameterTypes, class_infered, method_infered);
3611 protected bool IsDuplicateImplementation (MethodCore method)
3613 if ((method == this) ||
3614 (method.MemberName.GetTypeName () != MemberName.GetTypeName ()))
3617 Type[] param_types = method.ParameterTypes;
3618 if (param_types == null)
3621 if (param_types.Length != ParameterTypes.Length)
3625 bool may_unify = MayUnify (this, method);
3627 for (int i = 0; i < param_types.Length; i++) {
3628 if (param_types [i] != ParameterTypes [i])
3632 // TODO: make operator compatible with MethodCore to avoid this
3633 if (this is Operator && method is Operator) {
3634 if (MemberType != method.MemberType)
3635 equal = may_unify = false;
3640 // Try to report 663: method only differs on out/ref
3642 ParameterData info = ParameterInfo;
3643 ParameterData other_info = method.ParameterInfo;
3644 for (int i = 0; i < info.Count; i++){
3645 if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
3646 Report.Error (663, Location,
3647 "Overload method only differs " +
3648 "in parameter modifier");
3653 Report.SymbolRelatedToPreviousError (method);
3654 if (this is Operator && method is Operator)
3655 Report.Error (557, Location,
3656 "Duplicate user-defined conversion in type '{0}'",
3659 Report.Error (111, Location,
3660 "Type '{0}' already defines a member called '{1}' " +
3661 "with the same parameter types", Parent.Name, Name);
3663 } else if (may_unify) {
3664 Report.Error (408, Location,
3665 "`{0}' cannot define overload members that " +
3666 "may unify for some type parameter substitutions",
3674 // Returns a string that represents the signature for this
3675 // member which should be used in XML documentation.
3677 public override string GetDocCommentName (DeclSpace ds)
3679 return DocUtil.GetMethodDocCommentName (this, ds);
3683 // Raised (and passed an XmlElement that contains the comment)
3684 // when GenerateDocComment is writing documentation expectedly.
3686 // FIXME: with a few effort, it could be done with XmlReader,
3687 // that means removal of DOM use.
3689 internal override void OnGenerateDocComment (DeclSpace ds, XmlElement el)
3691 DocUtil.OnMethodGenerateDocComment (this, ds, el);
3695 // Represents header string for documentation comment.
3697 public override string DocCommentHeader {
3698 get { return "M:"; }
3701 protected override void VerifyObsoleteAttribute()
3703 base.VerifyObsoleteAttribute ();
3705 if (parameter_types == null)
3708 foreach (Type type in parameter_types) {
3709 CheckUsageOfObsoleteAttribute (type);
3714 public class SourceMethod : ISourceMethod
3716 TypeContainer container;
3719 protected SourceMethod (TypeContainer container, MethodBase builder,
3720 ISourceFile file, Location start, Location end)
3722 this.container = container;
3723 this.builder = builder;
3725 CodeGen.SymbolWriter.OpenMethod (
3726 file, this, start.Row, 0, end.Row, 0);
3729 public string Name {
3730 get { return builder.Name; }
3733 public int NamespaceID {
3734 get { return container.NamespaceEntry.SymbolFileID; }
3739 if (builder is MethodBuilder)
3740 return ((MethodBuilder) builder).GetToken ().Token;
3741 else if (builder is ConstructorBuilder)
3742 return ((ConstructorBuilder) builder).GetToken ().Token;
3744 throw new NotSupportedException ();
3748 public void CloseMethod ()
3750 if (CodeGen.SymbolWriter != null)
3751 CodeGen.SymbolWriter.CloseMethod ();
3754 public static SourceMethod Create (TypeContainer parent,
3755 MethodBase builder, Block block)
3757 if (CodeGen.SymbolWriter == null)
3762 Location start_loc = block.StartLocation;
3763 if (Location.IsNull (start_loc))
3766 Location end_loc = block.EndLocation;
3767 if (Location.IsNull (end_loc))
3770 ISourceFile file = start_loc.SourceFile;
3774 return new SourceMethod (
3775 parent, builder, file, start_loc, end_loc);
3779 public class Method : MethodCore, IIteratorContainer, IMethodData {
3780 public MethodBuilder MethodBuilder;
3781 public MethodData MethodData;
3782 ReturnParameter return_attributes;
3783 ListDictionary declarative_security;
3786 /// Modifiers allowed in a class declaration
3788 const int AllowedModifiers =
3791 Modifiers.PROTECTED |
3792 Modifiers.INTERNAL |
3797 Modifiers.OVERRIDE |
3798 Modifiers.ABSTRACT |
3800 Modifiers.METHOD_YIELDS |
3803 const int AllowedInterfaceModifiers =
3804 Modifiers.NEW | Modifiers.UNSAFE;
3807 // return_type can be "null" for VOID values.
3809 public Method (TypeContainer parent, GenericMethod generic,
3810 Expression return_type, int mod, bool is_iface,
3811 MemberName name, Parameters parameters, Attributes attrs,
3813 : base (parent, generic, return_type, mod,
3814 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
3815 is_iface, name, attrs, parameters, l)
3819 public override AttributeTargets AttributeTargets {
3821 return AttributeTargets.Method;
3825 public override string GetSignatureForError()
3827 if (MethodBuilder == null) {
3828 return GetSignatureForError (Parent);
3830 return TypeManager.CSharpSignature (MethodBuilder);
3834 /// Use this method when MethodBuilder is null
3836 public override string GetSignatureForError (TypeContainer tc)
3838 // TODO: get params from somewhere
3839 if (parameter_info == null)
3840 return base.GetSignatureForError (tc);
3842 // TODO: move to parameters
3843 System.Text.StringBuilder args = new System.Text.StringBuilder ();
3844 if (parameter_info.Parameters.FixedParameters != null) {
3845 for (int i = 0; i < parameter_info.Parameters.FixedParameters.Length; ++i) {
3846 Parameter p = parameter_info.Parameters.FixedParameters [i];
3847 args.Append (p.GetSignatureForError ());
3849 if (i < parameter_info.Parameters.FixedParameters.Length - 1)
3854 return String.Concat (base.GetSignatureForError (tc), "(", args.ToString (), ")");
3857 void DuplicateEntryPoint (MethodInfo b, Location location)
3861 "Program `" + CodeGen.FileName +
3862 "' has more than one entry point defined: `" +
3863 TypeManager.CSharpSignature(b) + "'");
3866 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
3868 if (b.ReturnType != TypeManager.void_type &&
3869 b.ReturnType != TypeManager.int32_type)
3872 if (pinfo.Count == 0)
3875 if (pinfo.Count > 1)
3878 Type t = pinfo.ParameterType(0);
3880 (t.GetArrayRank() == 1) &&
3881 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
3882 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
3888 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3890 if (a.Target == AttributeTargets.ReturnValue) {
3891 if (return_attributes == null)
3892 return_attributes = new ReturnParameter (MethodBuilder, Location);
3894 return_attributes.ApplyAttributeBuilder (a, cb);
3898 if (a.Type == TypeManager.methodimpl_attr_type &&
3899 (a.GetMethodImplOptions () & MethodImplOptions.InternalCall) != 0) {
3900 MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
3903 if (a.Type == TypeManager.dllimport_type) {
3904 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3905 if ((ModFlags & extern_static) != extern_static) {
3906 Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
3912 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
3913 if (declarative_security == null)
3914 declarative_security = new ListDictionary ();
3915 a.ExtractSecurityPermissionSet (declarative_security);
3919 if (a.Type == TypeManager.conditional_attribute_type) {
3920 if (IsOperator || IsExplicitImpl) {
3921 Report.Error (577, Location, "Conditional not valid on '{0}' because it is a destructor, operator, or explicit interface implementation", GetSignatureForError ());
3925 if (ReturnType != TypeManager.void_type) {
3926 Report.Error (578, Location, "Conditional not valid on '{0}' because its return new ErrorData ( type is not void", GetSignatureForError ());
3930 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3931 Report.Error (243, Location, "Conditional not valid on '{0}' because it is an override method", GetSignatureForError ());
3936 Report.Error (582, Location, "Conditional not valid on interface members");
3940 if (MethodData.IsImplementing) {
3941 Report.Error (629, Location, "Conditional member '{0}' cannot implement interface member", GetSignatureForError ());
3945 for (int i = 0; i < parameter_info.Count; ++i) {
3946 if ((parameter_info.ParameterModifier (i) & Parameter.Modifier.OUT) != 0) {
3947 Report.Error (685, Location, "Conditional method '{0}' cannot have an out parameter", GetSignatureForError ());
3953 MethodBuilder.SetCustomAttribute (cb);
3956 protected override bool CheckForDuplications ()
3958 ArrayList ar = Parent.Methods;
3960 int arLen = ar.Count;
3962 for (int i = 0; i < arLen; i++) {
3963 Method m = (Method) ar [i];
3964 if (IsDuplicateImplementation (m))
3969 ar = Parent.Properties;
3971 for (int i = 0; i < ar.Count; ++i) {
3972 PropertyBase pb = (PropertyBase) ar [i];
3973 if (pb.AreAccessorsDuplicateImplementation (this))
3978 ar = Parent.Indexers;
3980 for (int i = 0; i < ar.Count; ++i) {
3981 PropertyBase pb = (PropertyBase) ar [i];
3982 if (pb.AreAccessorsDuplicateImplementation (this))
3989 for (int i = 0; i < ar.Count; ++i) {
3990 Event ev = (Event) ar [i];
3991 if (ev.AreAccessorsDuplicateImplementation (this))
4002 public override bool Define ()
4004 if (!DoDefineBase ())
4007 MethodBuilder mb = null;
4008 if (GenericMethod != null) {
4009 string mname = MemberName.GetMethodName ();
4010 mb = Parent.TypeBuilder.DefineGenericMethod (mname, flags);
4011 if (!GenericMethod.Define (mb, ReturnType))
4018 if (RootContext.StdLib && (ReturnType == TypeManager.arg_iterator_type || ReturnType == TypeManager.typed_reference_type)) {
4019 Error1599 (Location, ReturnType);
4027 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
4029 MethodData = new MethodData (this, ParameterInfo, ModFlags, flags,
4030 this, mb, GenericMethod, base_method);
4032 if (!MethodData.Define (Parent))
4036 // Setup iterator if we are one
4038 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
4039 Iterator iterator = new Iterator (
4040 Parent, Name, MemberType, ParameterTypes,
4041 ParameterInfo, ModFlags, block, Location);
4043 if (!iterator.DefineIterator ())
4046 block = iterator.Block;
4049 MethodBuilder = MethodData.MethodBuilder;
4052 // This is used to track the Entry Point,
4054 if (Name == "Main" &&
4055 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
4056 (RootContext.MainClass == null ||
4057 RootContext.MainClass == Parent.TypeBuilder.FullName)){
4058 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
4059 if (RootContext.EntryPoint == null) {
4060 if (Parent.IsGeneric){
4061 Report.Error (-201, Location,
4062 "Entry point can not be defined in a generic class");
4065 RootContext.EntryPoint = MethodBuilder;
4066 RootContext.EntryPointLocation = Location;
4068 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
4069 DuplicateEntryPoint (MethodBuilder, Location);
4072 if (RootContext.WarningLevel >= 4)
4073 Report.Warning (28, Location, "'{0}' has the wrong signature to be an entry point", TypeManager.CSharpSignature(MethodBuilder) );
4077 if (MemberType.IsAbstract && MemberType.IsSealed) {
4078 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
4088 public override void Emit ()
4090 MethodData.Emit (Parent, this);
4093 if (declarative_security != null) {
4094 foreach (DictionaryEntry de in declarative_security) {
4095 MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
4103 public static void Error1599 (Location loc, Type t)
4105 Report.Error (1599, loc, "Method or delegate cannot return type '{0}'", TypeManager.CSharpName (t));
4108 protected override MethodInfo FindOutBaseMethod (TypeContainer container, ref Type base_ret_type)
4110 MethodInfo mi = (MethodInfo) container.BaseCache.FindMemberToOverride (
4111 container.TypeBuilder, Name, ParameterTypes, false);
4116 base_ret_type = mi.ReturnType;
4120 public override bool MarkForDuplicationCheck ()
4122 caching_flags |= Flags.TestMethodDuplication;
4126 protected override bool VerifyClsCompliance(DeclSpace ds)
4128 if (!base.VerifyClsCompliance (ds))
4131 if (parameter_types.Length > 0) {
4132 ArrayList al = (ArrayList)ds.MemberCache.Members [Name];
4134 ds.MemberCache.VerifyClsParameterConflict (al, this, MethodBuilder);
4141 void IIteratorContainer.SetYields ()
4143 ModFlags |= Modifiers.METHOD_YIELDS;
4146 #region IMethodData Members
4148 public CallingConventions CallingConventions {
4150 CallingConventions cc = Parameters.GetCallingConvention ();
4151 if (Parameters.HasArglist)
4152 block.HasVarargs = true;
4155 if ((ModFlags & Modifiers.STATIC) == 0)
4156 cc |= CallingConventions.HasThis;
4158 // FIXME: How is `ExplicitThis' used in C#?
4164 public Type ReturnType {
4170 public MemberName MethodName {
4176 public new Location Location {
4178 return base.Location;
4182 protected override bool CheckBase() {
4183 if (!base.CheckBase ())
4186 // TODO: Destructor should derive from MethodCore
4187 if (base_method != null && (ModFlags & Modifiers.OVERRIDE) != 0 && Name == "Finalize" &&
4188 base_method.DeclaringType == TypeManager.object_type && !(this is Destructor)) {
4189 Report.Error (249, Location, "Do not override object.Finalize. Instead, provide a destructor");
4196 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
4198 return new EmitContext (
4199 tc, ds, Location, ig, ReturnType, ModFlags, false);
4202 public ObsoleteAttribute GetObsoleteAttribute ()
4204 return GetObsoleteAttribute (ds);
4208 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
4210 public bool IsExcluded (EmitContext ec)
4212 if ((caching_flags & Flags.Excluded_Undetected) == 0)
4213 return (caching_flags & Flags.Excluded) != 0;
4215 caching_flags &= ~Flags.Excluded_Undetected;
4217 if (base_method == null) {
4218 if (OptAttributes == null)
4221 Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type, ec);
4226 foreach (Attribute a in attrs) {
4227 string condition = a.GetConditionalAttributeValue (Parent.EmitContext);
4228 if (RootContext.AllDefines.Contains (condition))
4232 caching_flags |= Flags.Excluded;
4236 IMethodData md = TypeManager.GetMethod (base_method);
4238 if (AttributeTester.IsConditionalMethodExcluded (base_method)) {
4239 caching_flags |= Flags.Excluded;
4245 if (md.IsExcluded (ec)) {
4246 caching_flags |= Flags.Excluded;
4252 GenericMethod IMethodData.GenericMethod {
4254 return GenericMethod;
4261 public abstract class ConstructorInitializer {
4262 ArrayList argument_list;
4263 protected ConstructorInfo base_constructor;
4264 Parameters parameters;
4267 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
4270 this.argument_list = argument_list;
4271 this.parameters = parameters;
4275 public ArrayList Arguments {
4277 return argument_list;
4281 public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
4283 Expression base_constructor_group;
4287 ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
4289 if (argument_list != null){
4290 foreach (Argument a in argument_list){
4291 if (!a.Resolve (ec, loc))
4295 ec.CurrentBlock = null;
4297 if (this is ConstructorBaseInitializer) {
4298 if (ec.ContainerType.BaseType == null)
4301 t = ec.ContainerType.BaseType;
4302 if (ec.ContainerType.IsValueType) {
4303 Report.Error (522, loc,
4304 "structs cannot call base class constructors");
4308 t = ec.ContainerType;
4310 base_constructor_group = Expression.MemberLookup (
4311 ec, t, ".ctor", MemberTypes.Constructor,
4312 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
4315 if (base_constructor_group == null){
4317 base_constructor_group = Expression.MemberLookup (
4318 ec, t, null, t, ".ctor", MemberTypes.Constructor,
4319 BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
4323 int errors = Report.Errors;
4324 if (base_constructor_group != null)
4325 base_constructor = (ConstructorInfo) Invocation.OverloadResolve (
4326 ec, (MethodGroupExpr) base_constructor_group, argument_list,
4329 if (base_constructor == null) {
4330 if (errors == Report.Errors)
4331 Report.Error (1501, loc, "Can not find a constructor for this argument list");
4336 Report.Error (122, loc, "`{0}' is inaccessible due to its protection level",
4337 TypeManager.CSharpSignature (base_constructor));
4338 base_constructor = null;
4342 if (base_constructor == caller_builder){
4343 Report.Error (516, loc, "Constructor `{0}' can not call itself", TypeManager.CSharpSignature (caller_builder));
4350 public void Emit (EmitContext ec)
4352 if (base_constructor != null){
4353 ec.Mark (loc, false);
4355 Invocation.EmitCall (ec, true, true, null, base_constructor, argument_list, loc);
4357 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), base_constructor, argument_list, loc);
4362 /// Method search for base ctor. (We do not cache it).
4364 Constructor GetOverloadedConstructor (TypeContainer tc)
4366 if (tc.InstanceConstructors == null)
4369 foreach (Constructor c in tc.InstanceConstructors) {
4370 if (Arguments == null) {
4371 if (c.ParameterTypes.Length == 0)
4379 int count = c.ParameterInfo.Count;
4381 c.ParameterInfo.ParameterModifier (count - 1) == Parameter.Modifier.PARAMS) {
4382 for (int i = 0; i < count-1; i++)
4383 if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type) {
4388 if (c.ParameterTypes.Length != Arguments.Count)
4391 for (int i = 0; i < Arguments.Count; ++i)
4392 if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type) {
4407 //TODO: implement caching when it will be necessary
4408 public virtual void CheckObsoleteAttribute (TypeContainer tc, Location loc)
4410 Constructor ctor = GetOverloadedConstructor (tc);
4414 ObsoleteAttribute oa = ctor.GetObsoleteAttribute (tc);
4418 AttributeTester.Report_ObsoleteMessage (oa, ctor.GetSignatureForError (), loc);
4422 public class ConstructorBaseInitializer : ConstructorInitializer {
4423 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
4424 base (argument_list, pars, l)
4428 public override void CheckObsoleteAttribute(TypeContainer tc, Location loc) {
4429 if (base_constructor == null)
4432 TypeContainer type_ds = TypeManager.LookupTypeContainer (tc.TypeBuilder.BaseType);
4433 if (type_ds == null) {
4434 ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (base_constructor);
4437 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (base_constructor), loc);
4442 base.CheckObsoleteAttribute (type_ds, loc);
4447 public class ConstructorThisInitializer : ConstructorInitializer {
4448 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
4449 base (argument_list, pars, l)
4454 public class Constructor : MethodCore, IMethodData {
4455 public ConstructorBuilder ConstructorBuilder;
4456 public ConstructorInitializer Initializer;
4457 ListDictionary declarative_security;
4460 // Modifiers allowed for a constructor.
4462 public const int AllowedModifiers =
4464 Modifiers.PROTECTED |
4465 Modifiers.INTERNAL |
4471 bool has_compliant_args = false;
4473 // The spec claims that static is not permitted, but
4474 // my very own code has static constructors.
4476 public Constructor (TypeContainer ds, string name, int mod, Parameters args,
4477 ConstructorInitializer init, Location l)
4478 : base (ds, null, null, mod, AllowedModifiers, false,
4479 new MemberName (name), null, args, l)
4484 public override string GetSignatureForError()
4486 if (ConstructorBuilder == null)
4487 return GetSignatureForError (Parent);
4489 return TypeManager.CSharpSignature (ConstructorBuilder);
4492 public bool HasCompliantArgs {
4494 return has_compliant_args;
4498 public override AttributeTargets AttributeTargets {
4500 return AttributeTargets.Constructor;
4506 // Returns true if this is a default constructor
4508 public bool IsDefault ()
4510 if ((ModFlags & Modifiers.STATIC) != 0)
4511 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
4512 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
4515 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
4516 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
4517 (Initializer is ConstructorBaseInitializer) &&
4518 (Initializer.Arguments == null);
4521 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4523 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
4524 if (declarative_security == null) {
4525 declarative_security = new ListDictionary ();
4527 a.ExtractSecurityPermissionSet (declarative_security);
4531 ConstructorBuilder.SetCustomAttribute (cb);
4534 protected override bool CheckForDuplications ()
4536 ArrayList ar = Parent.InstanceConstructors;
4538 int arLen = ar.Count;
4540 for (int i = 0; i < arLen; i++) {
4541 Constructor m = (Constructor) ar [i];
4542 if (IsDuplicateImplementation (m))
4549 protected override bool CheckBase ()
4551 // Check whether arguments were correct.
4552 if (!DoDefineParameters ())
4555 // TODO: skip the rest for generated ctor
4556 if ((ModFlags & Modifiers.STATIC) != 0)
4559 if (!CheckForDuplications ())
4562 if (Parent.Kind == Kind.Struct) {
4563 if (ParameterTypes.Length == 0) {
4564 Report.Error (568, Location,
4565 "Structs can not contain explicit parameterless " +
4570 if ((ModFlags & Modifiers.PROTECTED) != 0) {
4571 Report.Error (666, Location, "Protected member in struct declaration");
4576 if ((RootContext.WarningLevel >= 4) && ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.PROTECTED) != 0)) {
4577 Report.Warning (628, Location, "'{0}': new protected member declared in sealed class", GetSignatureForError (Parent));
4584 // Creates the ConstructorBuilder
4586 public override bool Define ()
4588 MethodAttributes ca = (MethodAttributes.RTSpecialName |
4589 MethodAttributes.SpecialName);
4591 if ((ModFlags & Modifiers.STATIC) != 0){
4592 ca |= MethodAttributes.Static | MethodAttributes.Private;
4594 ca |= MethodAttributes.HideBySig;
4596 if ((ModFlags & Modifiers.PUBLIC) != 0)
4597 ca |= MethodAttributes.Public;
4598 else if ((ModFlags & Modifiers.PROTECTED) != 0){
4599 if ((ModFlags & Modifiers.INTERNAL) != 0)
4600 ca |= MethodAttributes.FamORAssem;
4602 ca |= MethodAttributes.Family;
4603 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
4604 ca |= MethodAttributes.Assembly;
4605 else if (IsDefault ())
4606 ca |= MethodAttributes.Public;
4608 ca |= MethodAttributes.Private;
4611 // Check if arguments were correct.
4615 ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
4616 ca, CallingConventions,
4619 if ((ModFlags & Modifiers.UNSAFE) != 0)
4620 ConstructorBuilder.InitLocals = false;
4622 TypeManager.AddMethod (ConstructorBuilder, this);
4625 // HACK because System.Reflection.Emit is lame
4627 TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes);
4635 public override void Emit ()
4637 EmitContext ec = CreateEmitContext (null, null);
4640 // extern methods have no bodies
4642 if ((ModFlags & Modifiers.EXTERN) != 0) {
4643 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
4645 179, Location, "External constructor `" +
4646 TypeManager.CSharpSignature (ConstructorBuilder) +
4647 "' can not have a body");
4650 } else if (block == null) {
4652 501, Location, "Constructor `" +
4653 TypeManager.CSharpSignature (ConstructorBuilder) +
4654 "' must declare a body since it is not marked extern");
4658 if ((ModFlags & Modifiers.STATIC) == 0){
4659 if (Parent.Kind == Kind.Class && Initializer == null)
4660 Initializer = new ConstructorBaseInitializer (
4661 null, Parameters.EmptyReadOnlyParameters, Location);
4665 // Spec mandates that Initializers will not have
4669 if (Initializer != null && !Initializer.Resolve (ConstructorBuilder, ec))
4671 ec.IsStatic = false;
4674 Parameters.LabelParameters (ec, ConstructorBuilder, Location);
4676 SourceMethod source = SourceMethod.Create (
4677 Parent, ConstructorBuilder, block);
4680 // Classes can have base initializers and instance field initializers.
4682 if (Parent.Kind == Kind.Class){
4683 if ((ModFlags & Modifiers.STATIC) == 0){
4686 // If we use a "this (...)" constructor initializer, then
4687 // do not emit field initializers, they are initialized in the other constructor
4689 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
4690 Parent.EmitFieldInitializers (ec);
4693 if (Initializer != null) {
4694 if (GetObsoleteAttribute (Parent) == null && Parent.GetObsoleteAttribute (Parent) == null)
4695 Initializer.CheckObsoleteAttribute (Parent, Location);
4697 ec.TestObsoleteMethodUsage = false;
4698 Initializer.Emit (ec);
4701 if ((ModFlags & Modifiers.STATIC) != 0)
4702 Parent.EmitFieldInitializers (ec);
4704 if (OptAttributes != null)
4705 OptAttributes.Emit (ec, this);
4707 // If this is a non-static `struct' constructor and doesn't have any
4708 // initializer, it must initialize all of the struct's fields.
4709 if ((Parent.Kind == Kind.Struct) &&
4710 ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
4711 Block.AddThisVariable (Parent, Location);
4713 ec.EmitTopBlock (block, ParameterInfo, Location);
4716 source.CloseMethod ();
4720 if (declarative_security != null) {
4721 foreach (DictionaryEntry de in declarative_security) {
4722 ConstructorBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
4729 // Is never override
4730 protected override MethodInfo FindOutBaseMethod (TypeContainer container, ref Type base_ret_type)
4735 protected override bool VerifyClsCompliance (DeclSpace ds)
4737 if (!base.VerifyClsCompliance (ds) || !IsExposedFromAssembly (ds)) {
4741 if (parameter_types.Length > 0) {
4742 ArrayList al = (ArrayList)ds.MemberCache.Members [".ctor"];
4744 ds.MemberCache.VerifyClsParameterConflict (al, this, ConstructorBuilder);
4746 if (ds.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
4747 foreach (Type param in parameter_types) {
4748 if (param.IsArray) {
4754 has_compliant_args = true;
4758 #region IMethodData Members
4760 public System.Reflection.CallingConventions CallingConventions {
4762 CallingConventions cc = Parameters.GetCallingConvention ();
4764 if (Parent.Kind == Kind.Class)
4765 if ((ModFlags & Modifiers.STATIC) == 0)
4766 cc |= CallingConventions.HasThis;
4768 // FIXME: How is `ExplicitThis' used in C#?
4774 public new Location Location {
4776 return base.Location;
4780 public MemberName MethodName {
4786 public Type ReturnType {
4792 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
4794 ILGenerator ig_ = ConstructorBuilder.GetILGenerator ();
4795 return new EmitContext (Parent, Location, ig_, null, ModFlags, true);
4798 public ObsoleteAttribute GetObsoleteAttribute ()
4803 public bool IsExcluded(EmitContext ec)
4808 GenericMethod IMethodData.GenericMethod {
4818 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
4820 public interface IMethodData
4822 CallingConventions CallingConventions { get; }
4823 Location Location { get; }
4824 MemberName MethodName { get; }
4825 Type[] ParameterTypes { get; }
4826 Type ReturnType { get; }
4827 GenericMethod GenericMethod { get; }
4829 Attributes OptAttributes { get; }
4830 ToplevelBlock Block { get; }
4832 EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig);
4833 ObsoleteAttribute GetObsoleteAttribute ();
4834 string GetSignatureForError (TypeContainer tc);
4835 bool IsExcluded (EmitContext ec);
4836 bool IsClsCompliaceRequired (DeclSpace ds);
4840 // Encapsulates most of the Method's state
4842 public class MethodData {
4844 readonly IMethodData method;
4847 // The return type of this method
4849 public readonly GenericMethod GenericMethod;
4850 public readonly InternalParameters ParameterInfo;
4853 // Are we implementing an interface ?
4855 public bool IsImplementing = false;
4860 protected MemberBase member;
4861 protected int modifiers;
4862 protected MethodAttributes flags;
4863 protected Type declaring_type;
4864 protected MethodInfo parent_method;
4868 MethodBuilder builder = null;
4869 public MethodBuilder MethodBuilder {
4875 public Type DeclaringType {
4877 return declaring_type;
4881 public MethodData (MemberBase member, InternalParameters parameters,
4882 int modifiers, MethodAttributes flags, IMethodData method)
4884 this.member = member;
4885 this.ParameterInfo = parameters;
4886 this.modifiers = modifiers;
4889 this.method = method;
4892 public MethodData (MemberBase member, InternalParameters parameters,
4893 int modifiers, MethodAttributes flags,
4894 IMethodData method, MethodBuilder builder,
4895 GenericMethod generic, MethodInfo parent_method)
4896 : this (member, parameters, modifiers, flags, method)
4898 this.builder = builder;
4899 this.GenericMethod = generic;
4900 this.parent_method = parent_method;
4903 public bool Define (TypeContainer container)
4905 MethodInfo implementing = null;
4908 if (member.IsExplicitImpl)
4909 prefix = member.InterfaceType.FullName + ".";
4913 string name = method.MethodName.Basename;
4914 string method_name = prefix + name;
4916 Type[] ParameterTypes = method.ParameterTypes;
4918 if (container.Pending != null){
4919 if (member is Indexer) // TODO: test it, but it should work without this IF
4920 implementing = container.Pending.IsInterfaceIndexer (
4921 member.InterfaceType, method.ReturnType, ParameterTypes);
4923 implementing = container.Pending.IsInterfaceMethod (
4924 member.InterfaceType, name, method.ReturnType, ParameterTypes);
4926 if (member.InterfaceType != null){
4927 if (implementing == null){
4928 if (member is PropertyBase) {
4929 Report.Error (550, method.Location, "'{0}' is an accessor not found in interface member '{1}'",
4930 method.GetSignatureForError (container), member.ExplicitInterfaceName);
4933 Report.Error (539, method.Location,
4934 "'{0}' in explicit interface declaration is not a member of interface", member.GetSignatureForError () );
4938 if (implementing.IsSpecialName && !((member is PropertyBase || member is EventProperty))) {
4939 Report.SymbolRelatedToPreviousError (implementing);
4940 Report.Error (683, method.Location, "'{0}' explicit method implementation cannot implement '{1}' because it is an accessor",
4941 member.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
4944 method_name = member.InterfaceType.FullName + "." + name;
4946 if (implementing != null && method is AbstractPropertyEventMethod && !implementing.IsSpecialName) {
4947 Report.SymbolRelatedToPreviousError (implementing);
4948 Report.Error (686, method.Location, "Accessor '{0}' cannot implement interface member '{1}' for type '{2}'. Use an explicit interface implementation",
4949 method.GetSignatureForError (container), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
4956 // For implicit implementations, make sure we are public, for
4957 // explicit implementations, make sure we are private.
4959 if (implementing != null){
4961 // Setting null inside this block will trigger a more
4962 // verbose error reporting for missing interface implementations
4964 // The "candidate" function has been flagged already
4965 // but it wont get cleared
4967 if (member.IsExplicitImpl){
4968 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
4969 Modifiers.Error_InvalidModifier (method.Location, "public, virtual or abstract");
4970 implementing = null;
4972 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
4973 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
4975 // If this is an interface method implementation,
4976 // check for public accessibility
4978 implementing = null;
4979 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
4980 // We may never be private.
4981 implementing = null;
4982 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
4984 // We may be protected if we're overriding something.
4986 implementing = null;
4991 // Static is not allowed
4993 if ((modifiers & Modifiers.STATIC) != 0){
4994 implementing = null;
4995 Modifiers.Error_InvalidModifier (method.Location, "static");
5000 // If implementing is still valid, set flags
5002 if (implementing != null){
5004 // When implementing interface methods, set NewSlot
5005 // unless, we are overwriting a method.
5007 if (implementing.DeclaringType.IsInterface){
5008 if ((modifiers & Modifiers.OVERRIDE) == 0)
5009 flags |= MethodAttributes.NewSlot;
5012 MethodAttributes.Virtual |
5013 MethodAttributes.HideBySig;
5015 // Set Final unless we're virtual, abstract or already overriding a method.
5016 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
5017 flags |= MethodAttributes.Final;
5019 IsImplementing = true;
5022 EmitContext ec = method.CreateEmitContext (container, null);
5024 DefineMethodBuilder (ec, container, method_name, ParameterTypes);
5026 if (builder == null)
5029 if (container.CurrentType != null)
5030 declaring_type = container.CurrentType;
5032 declaring_type = container.TypeBuilder;
5034 if ((modifiers & Modifiers.UNSAFE) != 0)
5035 builder.InitLocals = false;
5037 if (IsImplementing){
5039 // clear the pending implemntation flag
5041 if (member is Indexer) {
5042 container.Pending.ImplementIndexer (
5043 member.InterfaceType, builder, method.ReturnType,
5044 ParameterTypes, member.IsExplicitImpl);
5046 container.Pending.ImplementMethod (
5047 member.InterfaceType, name, method.ReturnType,
5048 ParameterTypes, member.IsExplicitImpl);
5050 if (member.IsExplicitImpl)
5051 container.TypeBuilder.DefineMethodOverride (
5052 builder, implementing);
5056 TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes);
5057 TypeManager.AddMethod (builder, method);
5059 if (GenericMethod != null) {
5060 bool is_override = member.IsExplicitImpl |
5061 ((modifiers & Modifiers.OVERRIDE) != 0);
5063 if (implementing != null)
5064 parent_method = implementing;
5066 if (!GenericMethod.DefineType (ec, builder, parent_method, is_override))
5074 /// Create the MethodBuilder for the method
5076 void DefineMethodBuilder (EmitContext ec, TypeContainer container, string method_name, Type[] ParameterTypes)
5078 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
5080 if ((modifiers & extern_static) == extern_static) {
5082 if (method.OptAttributes != null) {
5083 Attribute dllimport_attribute = method.OptAttributes.Search (TypeManager.dllimport_type, ec);
5084 if (dllimport_attribute != null) {
5085 flags |= MethodAttributes.PinvokeImpl;
5086 builder = dllimport_attribute.DefinePInvokeMethod (
5087 ec, container.TypeBuilder, method_name, flags,
5088 method.ReturnType, ParameterTypes);
5094 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
5095 // We are more strict than Microsoft and report CS0626 like error
5096 if (method.OptAttributes == null ||
5097 !method.OptAttributes.Contains (TypeManager.methodimpl_attr_type, ec)) {
5098 Report.Error (626, method.Location, "Method, operator, or accessor '{0}' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation", method.GetSignatureForError (container));
5103 if (builder == null)
5104 builder = container.TypeBuilder.DefineMethod (
5105 method_name, flags, method.CallingConventions,
5106 method.ReturnType, ParameterTypes);
5108 builder.SetGenericMethodSignature (
5109 flags, method.CallingConventions,
5110 method.ReturnType, ParameterTypes);
5116 public void Emit (TypeContainer container, Attributable kind)
5119 if ((flags & MethodAttributes.PinvokeImpl) == 0)
5120 ec = method.CreateEmitContext (container, builder.GetILGenerator ());
5122 ec = method.CreateEmitContext (container, null);
5124 if (method.GetObsoleteAttribute () != null || container.GetObsoleteAttribute (container) != null)
5125 ec.TestObsoleteMethodUsage = false;
5127 Location loc = method.Location;
5128 Attributes OptAttributes = method.OptAttributes;
5130 if (OptAttributes != null)
5131 OptAttributes.Emit (ec, kind);
5133 if (member is MethodCore)
5134 ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder, loc);
5136 ToplevelBlock block = method.Block;
5139 // abstract or extern methods have no bodies
5141 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
5146 // abstract or extern methods have no bodies.
5148 if ((modifiers & Modifiers.ABSTRACT) != 0)
5150 500, method.Location, "Abstract method `" +
5151 TypeManager.CSharpSignature (builder) +
5152 "' can not have a body");
5154 if ((modifiers & Modifiers.EXTERN) != 0)
5156 179, method.Location, "External method `" +
5157 TypeManager.CSharpSignature (builder) +
5158 "' can not have a body");
5164 // Methods must have a body unless they're extern or abstract
5166 if (block == null) {
5168 501, method.Location, "Method `" +
5169 TypeManager.CSharpSignature (builder) +
5170 "' must declare a body since it is not marked " +
5171 "abstract or extern");
5175 SourceMethod source = SourceMethod.Create (
5176 container, MethodBuilder, method.Block);
5179 // Handle destructors specially
5181 // FIXME: This code generates buggy code
5183 if (member is Destructor)
5184 EmitDestructor (ec, block);
5186 ec.EmitTopBlock (block, ParameterInfo, loc);
5189 source.CloseMethod ();
5192 void EmitDestructor (EmitContext ec, ToplevelBlock block)
5194 ILGenerator ig = ec.ig;
5196 Label finish = ig.DefineLabel ();
5198 block.SetDestructor ();
5200 ig.BeginExceptionBlock ();
5201 ec.ReturnLabel = finish;
5202 ec.HasReturnLabel = true;
5203 ec.EmitTopBlock (block, null, method.Location);
5205 // ig.MarkLabel (finish);
5206 ig.BeginFinallyBlock ();
5208 if (ec.ContainerType.BaseType != null) {
5209 Expression member_lookup = Expression.MemberLookup (
5210 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
5211 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, method.Location);
5213 if (member_lookup != null){
5214 MethodGroupExpr base_destructor = ((MethodGroupExpr) member_lookup);
5216 ig.Emit (OpCodes.Ldarg_0);
5217 ig.Emit (OpCodes.Call, (MethodInfo) base_destructor.Methods [0]);
5221 ig.EndExceptionBlock ();
5222 //ig.MarkLabel (ec.ReturnLabel);
5223 ig.Emit (OpCodes.Ret);
5227 // Should derive from MethodCore
5228 public class Destructor : Method {
5230 public Destructor (TypeContainer ds, Expression return_type, int mod, string name,
5231 Parameters parameters, Attributes attrs, Location l)
5232 : base (ds, null, return_type, mod, false, new MemberName (name),
5233 parameters, attrs, l)
5236 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5238 if (a.Type == TypeManager.conditional_attribute_type) {
5239 Report.Error (577, Location, "Conditional not valid on '{0}' because it is a destructor, operator, or explicit interface implementation", GetSignatureForError ());
5243 base.ApplyAttributeBuilder (a, cb);
5247 abstract public class MemberBase : MemberCore {
5248 public Expression Type;
5250 public MethodAttributes flags;
5252 protected readonly int explicit_mod_flags;
5255 // The "short" name of this property / indexer / event. This is the
5256 // name without the explicit interface.
5258 public string ShortName;
5261 // The type of this property / indexer / event
5263 public Type MemberType;
5266 // If true, this is an explicit interface implementation
5268 public bool IsExplicitImpl = false;
5271 // The name of the interface we are explicitly implementing
5273 public MemberName ExplicitInterfaceName = null;
5276 // Whether this is an interface member.
5278 public bool IsInterface;
5281 // If true, the interface type we are explicitly implementing
5283 public Type InterfaceType = null;
5286 // The constructor is only exposed to our children
5288 protected MemberBase (TypeContainer parent, Expression type, int mod,
5289 int allowed_mod, int def_mod, MemberName name,
5290 Attributes attrs, Location loc)
5291 : base (parent, name, attrs, loc)
5293 explicit_mod_flags = mod;
5295 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
5297 // Check for explicit interface implementation
5298 if (MemberName.Left != null) {
5299 ExplicitInterfaceName = MemberName.Left;
5300 ShortName = MemberName.Name;
5301 IsExplicitImpl = true;
5306 protected virtual bool CheckBase ()
5308 if ((ModFlags & Modifiers.PROTECTED) != 0 && Parent.Kind == Kind.Struct) {
5309 Report.Error (666, Location, "Protected member in struct declaration");
5313 if ((RootContext.WarningLevel >= 4) &&
5314 ((Parent.ModFlags & Modifiers.SEALED) != 0) &&
5315 ((ModFlags & Modifiers.PROTECTED) != 0) &&
5316 ((ModFlags & Modifiers.OVERRIDE) == 0) && (Name != "Finalize")) {
5317 Report.Warning (628, Location, "'{0}': new protected member declared in sealed class", GetSignatureForError (Parent));
5323 protected abstract bool CheckGenericOverride (MethodInfo method, string name);
5325 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
5329 foreach (Type partype in parameters){
5330 if (partype == TypeManager.void_type) {
5332 1547, Location, "Keyword 'void' cannot " +
5333 "be used in this context");
5337 if (partype.IsPointer){
5340 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
5344 if (ds.AsAccessible (partype, ModFlags))
5347 if (this is Indexer)
5348 Report.Error (55, Location,
5349 "Inconsistent accessibility: parameter type `" +
5350 TypeManager.CSharpName (partype) + "' is less " +
5351 "accessible than indexer `" + Name + "'");
5352 else if ((this is Method) && ((Method) this).IsOperator)
5353 Report.Error (57, Location,
5354 "Inconsistent accessibility: parameter type `" +
5355 TypeManager.CSharpName (partype) + "' is less " +
5356 "accessible than operator `" + Name + "'");
5358 Report.Error (51, Location,
5359 "Inconsistent accessibility: parameter type `" +
5360 TypeManager.CSharpName (partype) + "' is less " +
5361 "accessible than method `" + Name + "'");
5368 protected virtual bool DoDefineBase ()
5370 EmitContext ec = Parent.EmitContext;
5372 throw new InternalErrorException ("MemberBase.DoDefine called too early");
5375 throw new InternalErrorException ();
5378 ModFlags = Modifiers.PUBLIC |
5379 Modifiers.ABSTRACT |
5380 Modifiers.VIRTUAL | (ModFlags & Modifiers.UNSAFE) | (ModFlags & Modifiers.NEW);
5382 flags = MethodAttributes.Public |
5383 MethodAttributes.Abstract |
5384 MethodAttributes.HideBySig |
5385 MethodAttributes.NewSlot |
5386 MethodAttributes.Virtual;
5388 if (!Parent.MethodModifiersValid (this))
5391 flags = Modifiers.MethodAttr (ModFlags);
5397 protected virtual bool DoDefine (DeclSpace decl)
5399 EmitContext ec = decl.EmitContext;
5401 throw new InternalErrorException ("MemberBase.DoDefine called too early");
5403 ec.InUnsafe = InUnsafe;
5405 // Lookup Type, verify validity
5406 bool old_unsafe = ec.InUnsafe;
5407 ec.InUnsafe = InUnsafe;
5408 TypeExpr texpr = Type.ResolveAsTypeTerminal (ec);
5409 ec.InUnsafe = old_unsafe;
5414 MemberType = texpr.Type;
5416 if ((Parent.ModFlags & Modifiers.SEALED) != 0){
5417 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
5418 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
5423 // verify accessibility
5424 if (!Parent.AsAccessible (MemberType, ModFlags)) {
5425 Report.SymbolRelatedToPreviousError (MemberType);
5426 if (this is Property)
5427 Report.Error (53, Location,
5428 "Inconsistent accessibility: property type `" +
5429 TypeManager.CSharpName (MemberType) + "' is less " +
5430 "accessible than property `" + GetSignatureForError () + "'");
5431 else if (this is Indexer)
5432 Report.Error (54, Location,
5433 "Inconsistent accessibility: indexer return type `" +
5434 TypeManager.CSharpName (MemberType) + "' is less " +
5435 "accessible than indexer `" + Name + "'");
5436 else if (this is MethodCore) {
5437 if (this is Operator)
5438 Report.Error (56, Location,
5439 "Inconsistent accessibility: return type `" +
5440 TypeManager.CSharpName (MemberType) + "' is less " +
5441 "accessible than operator `" + Name + "'");
5443 Report.Error (50, Location,
5444 "Inconsistent accessibility: return type `" +
5445 TypeManager.CSharpName (MemberType) + "' is less " +
5446 "accessible than method `" + Name + "'");
5448 Report.Error (52, Location,
5449 "Inconsistent accessibility: field type `" +
5450 TypeManager.CSharpName (MemberType) + "' is less " +
5451 "accessible than field `" + Name + "'");
5456 if (MemberType.IsPointer && !UnsafeOK (Parent))
5459 if (IsExplicitImpl) {
5460 Expression expr = ExplicitInterfaceName.GetTypeExpression (Location);
5461 TypeExpr iface_texpr = expr.ResolveAsTypeTerminal (ec);
5462 if (iface_texpr == null)
5465 InterfaceType = iface_texpr.Type;
5467 if (!InterfaceType.IsInterface) {
5468 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", TypeManager.CSharpName (InterfaceType));
5472 if (!Parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
5475 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
5482 /// The name of the member can be changed during definition (see IndexerName attribute)
5484 protected virtual void UpdateMemberName ()
5486 MemberName.Name = ShortName;
5489 public override string GetSignatureForError (TypeContainer tc)
5491 return String.Concat (tc.Name, '.', base.GetSignatureForError (tc));
5494 protected bool IsTypePermitted ()
5496 if (MemberType == TypeManager.arg_iterator_type || MemberType == TypeManager.typed_reference_type) {
5497 Report.Error (610, Location, "Field or property cannot be of type '{0}'", TypeManager.CSharpName (MemberType));
5503 protected override bool VerifyClsCompliance(DeclSpace ds)
5505 if (base.VerifyClsCompliance (ds)) {
5509 if (IsInterface && HasClsCompliantAttribute && ds.IsClsCompliaceRequired (ds)) {
5510 Report.Error (3010, Location, "'{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
5515 protected override void VerifyObsoleteAttribute()
5517 CheckUsageOfObsoleteAttribute (MemberType);
5522 // Fields and Events both generate FieldBuilders, we use this to share
5523 // their common bits. This is also used to flag usage of the field
5525 abstract public class FieldBase : MemberBase {
5526 public FieldBuilder FieldBuilder;
5527 public Status status;
5530 public enum Status : byte {
5533 HAS_OFFSET = 4 // Used by FieldMember.
5536 static string[] attribute_targets = new string [] { "field" };
5539 /// Symbol with same name in base class/struct
5541 public MemberInfo conflict_symbol;
5544 // The constructor is only exposed to our children
5546 protected FieldBase (TypeContainer parent, Expression type, int mod,
5547 int allowed_mod, MemberName name, object init,
5548 Attributes attrs, Location loc)
5549 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE,
5555 public override AttributeTargets AttributeTargets {
5557 return AttributeTargets.Field;
5561 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5563 if (a.Type == TypeManager.marshal_as_attr_type) {
5564 UnmanagedMarshal marshal = a.GetMarshal (this);
5565 if (marshal != null) {
5566 FieldBuilder.SetMarshal (marshal);
5571 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
5572 a.Error_InvalidSecurityParent ();
5576 FieldBuilder.SetCustomAttribute (cb);
5580 // Whether this field has an initializer.
5582 public bool HasInitializer {
5584 return init != null;
5588 protected readonly Object init;
5590 Expression init_expr;
5591 bool init_expr_initialized = false;
5593 protected override bool CheckGenericOverride (MethodInfo method, string name)
5599 // Resolves and returns the field initializer.
5601 public Expression GetInitializerExpression (EmitContext ec)
5603 if (init_expr_initialized)
5607 if (init is Expression)
5608 e = (Expression) init;
5610 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
5612 EmitContext parent_ec = Parent.EmitContext;
5614 bool old_is_static = parent_ec.IsStatic;
5615 parent_ec.IsStatic = ec.IsStatic;
5616 parent_ec.IsFieldInitializer = true;
5617 e = e.DoResolve (parent_ec);
5618 parent_ec.IsFieldInitializer = false;
5619 parent_ec.IsStatic = old_is_static;
5622 init_expr_initialized = true;
5627 protected override bool CheckBase ()
5629 if (!base.CheckBase ())
5636 conflict_symbol = Parent.FindBaseMemberWithSameName (Name, false);
5637 if (conflict_symbol == null) {
5638 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
5639 Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError (Parent));
5644 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0) {
5645 Report.SymbolRelatedToPreviousError (conflict_symbol);
5646 Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
5652 protected override bool DoDefine (DeclSpace ds)
5654 if (!base.DoDefine (ds))
5657 if (MemberType == TypeManager.void_type) {
5658 Report.Error (1547, Location,
5659 "Keyword 'void' cannot be used in this context");
5665 public override string GetSignatureForError ()
5667 if (FieldBuilder == null) {
5668 return base.GetSignatureForError (Parent);
5670 return TypeManager.GetFullNameSignature (FieldBuilder);
5673 protected virtual bool IsFieldClsCompliant {
5675 if (FieldBuilder == null)
5678 return AttributeTester.IsClsCompliant (FieldBuilder.FieldType);
5682 public override string[] ValidAttributeTargets {
5684 return attribute_targets;
5688 protected override bool VerifyClsCompliance (DeclSpace ds)
5690 if (!base.VerifyClsCompliance (ds))
5693 if (!IsFieldClsCompliant) {
5694 Report.Error (3003, Location, "Type of '{0}' is not CLS-compliant", GetSignatureForError ());
5700 public void SetAssigned ()
5702 status |= Status.ASSIGNED;
5706 public abstract class FieldMember: FieldBase
5708 protected FieldMember (TypeContainer parent, Expression type, int mod,
5709 int allowed_mod, MemberName name, object init, Attributes attrs, Location loc)
5710 : base (parent, type, mod, allowed_mod | Modifiers.ABSTRACT, name, init, attrs, loc)
5712 if ((mod & Modifiers.ABSTRACT) != 0)
5713 Report.Error (681, loc, "The modifier 'abstract' is not valid on fields. Try using a property instead");
5716 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5718 if (a.Type == TypeManager.field_offset_attribute_type)
5720 status |= Status.HAS_OFFSET;
5722 if (!Parent.HasExplicitLayout) {
5723 Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)");
5727 if ((ModFlags & Modifiers.STATIC) != 0 || this is Const) {
5728 Report.Error (637, Location, "The FieldOffset attribute is not allowed on static or const fields");
5732 base.ApplyAttributeBuilder (a, cb);
5736 public override bool Define()
5738 EmitContext ec = Parent.EmitContext;
5740 throw new InternalErrorException ("FieldMember.Define called too early");
5742 bool old_unsafe = ec.InUnsafe;
5743 ec.InUnsafe = InUnsafe;
5744 TypeExpr texpr = Type.ResolveAsTypeTerminal (ec);
5745 ec.InUnsafe = old_unsafe;
5749 MemberType = texpr.Type;
5751 ec.InUnsafe = old_unsafe;
5753 if (MemberType == TypeManager.void_type) {
5754 Report.Error (1547, Location, "Keyword 'void' cannot be used in this context");
5761 if (!Parent.AsAccessible (MemberType, ModFlags)) {
5762 Report.Error (52, Location,
5763 "Inconsistent accessibility: field type `" +
5764 TypeManager.CSharpName (MemberType) + "' is less " +
5765 "accessible than field `" + Name + "'");
5769 if (!IsTypePermitted ())
5772 if (MemberType.IsPointer && !UnsafeOK (Parent))
5778 public override void Emit ()
5780 if (OptAttributes != null) {
5781 EmitContext ec = new EmitContext (Parent, Location, null, FieldBuilder.FieldType, ModFlags);
5782 OptAttributes.Emit (ec, this);
5785 if (Parent.HasExplicitLayout && ((status & Status.HAS_OFFSET) == 0) && (ModFlags & Modifiers.STATIC) == 0) {
5786 Report.Error (625, Location, "'{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute.", GetSignatureForError ());
5793 // Represents header string for documentation comment.
5795 public override string DocCommentHeader {
5796 get { return "F:"; }
5800 interface IFixedBuffer
5802 FieldInfo Element { get; }
5803 Type ElementType { get; }
5806 public class FixedFieldExternal: IFixedBuffer
5808 FieldInfo element_field;
5810 public FixedFieldExternal (FieldInfo fi)
5812 element_field = fi.FieldType.GetField (FixedField.FixedElementName);
5815 #region IFixedField Members
5817 public FieldInfo Element {
5819 return element_field;
5823 public Type ElementType {
5825 return element_field.FieldType;
5833 /// Fixed buffer implementation
5835 public class FixedField: FieldMember, IFixedBuffer
5837 public const string FixedElementName = "FixedElementField";
5838 static int GlobalCounter = 0;
5839 static object[] ctor_args = new object[] { (short)LayoutKind.Sequential };
5840 static FieldInfo[] fi;
5842 TypeBuilder fixed_buffer_type;
5843 FieldBuilder element;
5844 Expression size_expr;
5847 const int AllowedModifiers =
5850 Modifiers.PROTECTED |
5851 Modifiers.INTERNAL |
5854 public FixedField (TypeContainer parent, Expression type, int mod, string name,
5855 Expression size_expr, Attributes attrs, Location loc):
5856 base (parent, type, mod, AllowedModifiers, new MemberName (name), null, attrs, loc)
5858 if (RootContext.Version == LanguageVersion.ISO_1)
5859 Report.FeatureIsNotStandardized (loc, "fixed sized buffers");
5861 this.size_expr = size_expr;
5864 public override bool Define()
5866 if (Parent.Kind != Kind.Struct) {
5867 Report.Error (1642, Location, "Fixed buffer fields may only be members of structs");
5871 if (!base.Define ())
5874 if (!MemberType.IsPrimitive) {
5875 Report.Error (1663, Location, "Fixed sized buffer type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double");
5879 Expression e = size_expr.Resolve (Parent.EmitContext);
5883 Constant c = e as Constant;
5885 Report.Error (133, Location, "The expression being assigned to '{0}' must be constant", GetSignatureForError ());
5889 buffer_size = (int)c.GetValue ();
5890 if (buffer_size <= 0) {
5891 Report.Error (1665, Location, "Fixed sized buffer '{0}' must have a length greater than zero", GetSignatureForError ());
5894 buffer_size *= Expression.GetTypeSize (MemberType);
5897 string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++);
5899 fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name,
5900 TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, TypeManager.value_type);
5901 element = fixed_buffer_type.DefineField (FixedElementName, MemberType, FieldAttributes.Public);
5902 RootContext.RegisterCompilerGeneratedType (fixed_buffer_type);
5904 FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, Modifiers.FieldAttr (ModFlags));
5905 TypeManager.RegisterFieldBase (FieldBuilder, this);
5910 public override void Emit()
5913 fi = new FieldInfo [] { TypeManager.struct_layout_attribute_type.GetField ("Size") };
5915 object[] fi_val = new object[1];
5916 fi_val [0] = buffer_size;
5918 CustomAttributeBuilder cab = new CustomAttributeBuilder (TypeManager.struct_layout_attribute_ctor,
5919 ctor_args, fi, fi_val);
5920 fixed_buffer_type.SetCustomAttribute (cab);
5922 cab = new CustomAttributeBuilder (TypeManager.fixed_buffer_attr_ctor, new object[] { MemberType, buffer_size } );
5923 FieldBuilder.SetCustomAttribute (cab);
5927 protected override bool IsFieldClsCompliant {
5933 #region IFixedField Members
5935 public FieldInfo Element {
5941 public Type ElementType {
5951 // The Field class is used to represents class/struct fields during parsing.
5953 public class Field : FieldMember {
5955 // Modifiers allowed in a class declaration
5957 const int AllowedModifiers =
5960 Modifiers.PROTECTED |
5961 Modifiers.INTERNAL |
5964 Modifiers.VOLATILE |
5968 public Field (TypeContainer parent, Expression type, int mod, string name,
5969 Object expr_or_array_init, Attributes attrs, Location loc)
5970 : base (parent, type, mod, AllowedModifiers, new MemberName (name),
5971 expr_or_array_init, attrs, loc)
5975 public override bool Define ()
5977 if (!base.Define ())
5980 if (RootContext.WarningLevel > 1){
5981 Type ptype = Parent.TypeBuilder.BaseType;
5983 // ptype is only null for System.Object while compiling corlib.
5985 TypeContainer.FindMembers (
5986 ptype, MemberTypes.Method,
5987 BindingFlags.Public |
5988 BindingFlags.Static | BindingFlags.Instance,
5989 System.Type.FilterName, Name);
5993 if ((ModFlags & Modifiers.VOLATILE) != 0){
5994 if (!MemberType.IsClass){
5995 Type vt = MemberType;
5997 if (TypeManager.IsEnumType (vt))
5998 vt = TypeManager.EnumToUnderlying (MemberType);
6000 if (!((vt == TypeManager.bool_type) ||
6001 (vt == TypeManager.sbyte_type) ||
6002 (vt == TypeManager.byte_type) ||
6003 (vt == TypeManager.short_type) ||
6004 (vt == TypeManager.ushort_type) ||
6005 (vt == TypeManager.int32_type) ||
6006 (vt == TypeManager.uint32_type) ||
6007 (vt == TypeManager.char_type) ||
6008 (vt == TypeManager.float_type) ||
6009 (!vt.IsValueType))){
6011 677, Location, Parent.MakeName (Name) +
6012 " A volatile field can not be of type `" +
6013 TypeManager.CSharpName (vt) + "'");
6018 if ((ModFlags & Modifiers.READONLY) != 0){
6021 "A field can not be both volatile and readonly");
6026 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
6028 if (Parent.Kind == Kind.Struct &&
6029 ((fa & FieldAttributes.Static) == 0) &&
6030 MemberType == Parent.TypeBuilder &&
6031 !TypeManager.IsBuiltinType (MemberType)){
6032 Report.Error (523, Location, "Struct member `" + Parent.Name + "." + Name +
6033 "' causes a cycle in the structure layout");
6038 FieldBuilder = Parent.TypeBuilder.DefineField (
6039 Name, MemberType, Modifiers.FieldAttr (ModFlags));
6041 TypeManager.RegisterFieldBase (FieldBuilder, this);
6043 catch (ArgumentException) {
6044 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
6053 // `set' and `get' accessors are represented with an Accessor.
6055 public class Accessor {
6057 // Null if the accessor is empty, or a Block if not
6059 public const int AllowedModifiers =
6061 Modifiers.PROTECTED |
6062 Modifiers.INTERNAL |
6065 public ToplevelBlock Block;
6066 public Attributes Attributes;
6067 public Location Location;
6068 public int ModFlags;
6070 public Accessor (ToplevelBlock b, int mod, Attributes attrs, Location loc)
6075 ModFlags = Modifiers.Check (AllowedModifiers, mod, 0, loc);
6080 // Ooouh Martin, templates are missing here.
6081 // When it will be possible move here a lot of child code and template method type.
6082 public abstract class AbstractPropertyEventMethod: MemberCore, IMethodData {
6083 protected MethodData method_data;
6084 protected ToplevelBlock block;
6085 protected ListDictionary declarative_security;
6087 // The accessor are created event if they are not wanted.
6088 // But we need them because their names are reserved.
6089 // Field says whether accessor will be emited or not
6090 public readonly bool IsDummy;
6092 protected readonly string prefix;
6094 ReturnParameter return_attributes;
6096 public AbstractPropertyEventMethod (MemberBase member, string prefix)
6097 : base (null, SetupName (prefix, member), null, member.Location)
6099 this.prefix = prefix;
6103 public AbstractPropertyEventMethod (MemberBase member, Accessor accessor,
6105 : base (null, SetupName (prefix, member),
6106 accessor.Attributes, accessor.Location)
6108 this.prefix = prefix;
6109 this.block = accessor.Block;
6112 static MemberName SetupName (string prefix, MemberBase member)
6114 MemberName name = member.MemberName.Clone ();
6115 name.Name = prefix + member.ShortName;
6119 public void UpdateName (MemberBase member)
6121 MemberName.Name = prefix + member.ShortName;
6124 #region IMethodData Members
6126 public ToplevelBlock Block {
6136 public CallingConventions CallingConventions {
6138 return CallingConventions.Standard;
6142 public bool IsExcluded (EmitContext ec)
6147 GenericMethod IMethodData.GenericMethod {
6153 public MemberName MethodName {
6159 public abstract ObsoleteAttribute GetObsoleteAttribute ();
6160 public abstract Type[] ParameterTypes { get; }
6161 public abstract Type ReturnType { get; }
6162 public abstract EmitContext CreateEmitContext(TypeContainer tc, ILGenerator ig);
6166 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
6168 if (a.Type == TypeManager.cls_compliant_attribute_type || a.Type == TypeManager.obsolete_attribute_type ||
6169 a.Type == TypeManager.conditional_attribute_type) {
6170 Report.Error (1667, a.Location, "'{0}' is not valid on property or event accessors. It is valid on {1} declarations only", TypeManager.CSharpName (a.Type), a.GetValidTargets ());
6174 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
6175 if (declarative_security == null)
6176 declarative_security = new ListDictionary ();
6177 a.ExtractSecurityPermissionSet (declarative_security);
6181 if (a.Target == AttributeTargets.Method) {
6182 method_data.MethodBuilder.SetCustomAttribute (cb);
6186 if (a.Target == AttributeTargets.ReturnValue) {
6187 if (return_attributes == null)
6188 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
6190 return_attributes.ApplyAttributeBuilder (a, cb);
6194 ApplyToExtraTarget (a, cb);
6197 virtual protected void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb)
6199 System.Diagnostics.Debug.Fail ("You forgot to define special attribute target handling");
6202 public override bool Define()
6204 throw new NotSupportedException ();
6207 public virtual void Emit (TypeContainer container)
6209 method_data.Emit (container, this);
6211 if (declarative_security != null) {
6212 foreach (DictionaryEntry de in declarative_security) {
6213 method_data.MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
6220 public override bool IsClsCompliaceRequired(DeclSpace ds)
6225 public bool IsDuplicateImplementation (MethodCore method)
6227 if (Name != method.Name)
6230 Type[] param_types = method.ParameterTypes;
6232 if (param_types.Length != ParameterTypes.Length)
6235 for (int i = 0; i < param_types.Length; i++)
6236 if (param_types [i] != ParameterTypes [i])
6239 Report.SymbolRelatedToPreviousError (method);
6240 Report.Error (111, Location, "Type '{0}' already defines a member called '{1}' with " +
6241 "the same parameter types", Parent.Name, Name);
6245 public new Location Location {
6247 return base.Location;
6252 // Represents header string for documentation comment.
6254 public override string DocCommentHeader {
6255 get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
6258 protected override void VerifyObsoleteAttribute()
6265 // Properties and Indexers both generate PropertyBuilders, we use this to share
6266 // their common bits.
6268 abstract public class PropertyBase : MethodCore {
6270 public class GetMethod: PropertyMethod
6272 static string[] attribute_targets = new string [] { "method", "return" };
6274 public GetMethod (MethodCore method):
6275 base (method, "get_")
6279 public GetMethod (MethodCore method, Accessor accessor):
6280 base (method, accessor, "get_")
6284 public override MethodBuilder Define(TypeContainer container)
6286 base.Define (container);
6288 method_data = new MethodData (method, method.ParameterInfo, ModFlags, flags, this);
6290 if (!method_data.Define (container))
6293 return method_data.MethodBuilder;
6296 public override string GetSignatureForError (TypeContainer tc)
6298 return String.Concat (base.GetSignatureForError (tc), ".get");
6301 public override Type ReturnType {
6303 return method.MemberType;
6307 public override string[] ValidAttributeTargets {
6309 return attribute_targets;
6314 public class SetMethod: PropertyMethod {
6316 static string[] attribute_targets = new string [] { "method", "param", "return" };
6317 ImplicitParameter param_attr;
6319 public SetMethod (MethodCore method):
6320 base (method, "set_")
6324 public SetMethod (MethodCore method, Accessor accessor):
6325 base (method, accessor, "set_")
6329 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
6331 if (a.Target == AttributeTargets.Parameter) {
6332 if (param_attr == null)
6333 param_attr = new ImplicitParameter (method_data.MethodBuilder);
6335 param_attr.ApplyAttributeBuilder (a, cb);
6339 base.ApplyAttributeBuilder (a, cb);
6342 protected virtual InternalParameters GetParameterInfo (EmitContext ec)
6344 Parameter [] parms = new Parameter [1];
6345 parms [0] = new Parameter (method.Type, "value", Parameter.Modifier.NONE, null);
6346 Parameters parameters = new Parameters (parms, null, method.Location);
6348 bool old_unsafe = ec.InUnsafe;
6349 ec.InUnsafe = InUnsafe;
6350 Type [] types = parameters.GetParameterInfo (ec);
6351 ec.InUnsafe = old_unsafe;
6353 return new InternalParameters (types, parameters);
6356 public override MethodBuilder Define (TypeContainer container)
6358 if (container.EmitContext == null)
6359 throw new InternalErrorException ("SetMethod.Define called too early");
6361 base.Define (container);
6363 method_data = new MethodData (method, GetParameterInfo (container.EmitContext), ModFlags, flags, this);
6365 if (!method_data.Define (container))
6368 return method_data.MethodBuilder;
6371 public override string GetSignatureForError (TypeContainer tc)
6373 return String.Concat (base.GetSignatureForError (tc), ".set");
6376 public override Type[] ParameterTypes {
6378 return new Type[] { method.MemberType };
6382 public override Type ReturnType {
6384 return TypeManager.void_type;
6388 public override string[] ValidAttributeTargets {
6390 return attribute_targets;
6395 static string[] attribute_targets = new string [] { "property" };
6397 public abstract class PropertyMethod: AbstractPropertyEventMethod {
6398 protected readonly MethodCore method;
6399 protected MethodAttributes flags;
6401 public PropertyMethod (MethodCore method, string prefix)
6402 : base (method, prefix)
6404 this.method = method;
6405 Parent = method.Parent;
6408 public PropertyMethod (MethodCore method, Accessor accessor, string prefix)
6409 : base (method, accessor, prefix)
6411 this.method = method;
6412 Parent = method.Parent;
6413 this.ModFlags = accessor.ModFlags;
6415 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
6416 Report.FeatureIsNotStandardized (Location, "accessor modifiers");
6420 public override AttributeTargets AttributeTargets {
6422 return AttributeTargets.Method;
6426 public override bool IsClsCompliaceRequired(DeclSpace ds)
6428 return method.IsClsCompliaceRequired (ds);
6431 public InternalParameters ParameterInfo
6434 return method_data.ParameterInfo;
6438 public virtual MethodBuilder Define (TypeContainer container)
6441 // Check for custom access modifier
6443 if (ModFlags == 0) {
6444 ModFlags = method.ModFlags;
6445 flags = method.flags;
6447 CheckModifiers (container, ModFlags);
6448 ModFlags |= (method.ModFlags & (~Modifiers.Accessibility));
6449 flags = Modifiers.MethodAttr (ModFlags);
6450 flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
6457 public override Type[] ParameterTypes {
6459 return TypeManager.NoTypes;
6463 public override EmitContext CreateEmitContext (TypeContainer tc,
6466 return new EmitContext (
6467 tc, method.ds, method.Location, ig, ReturnType,
6468 method.ModFlags, false);
6471 public override ObsoleteAttribute GetObsoleteAttribute ()
6473 return method.GetObsoleteAttribute (method.ds);
6476 public override string GetSignatureForError (TypeContainer tc)
6478 return String.Concat (tc.Name, '.', method.Name);
6481 void CheckModifiers (TypeContainer container, int modflags)
6484 int mflags = method.ModFlags & Modifiers.Accessibility;
6486 if ((mflags & Modifiers.PUBLIC) != 0) {
6487 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
6489 else if ((mflags & Modifiers.PROTECTED) != 0) {
6490 if ((mflags & Modifiers.INTERNAL) != 0)
6491 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL;
6493 flags |= Modifiers.PRIVATE;
6495 else if ((mflags & Modifiers.INTERNAL) != 0)
6496 flags |= Modifiers.PRIVATE;
6498 if ((mflags == modflags) || (modflags & (~flags)) != 0)
6499 Report.Error (273, Location, "{0}: accessibility modifier must be more restrictive than the property or indexer",
6500 GetSignatureForError (container));
6503 public override bool MarkForDuplicationCheck ()
6505 caching_flags |= Flags.TestMethodDuplication;
6510 public PropertyMethod Get, Set;
6511 public PropertyBuilder PropertyBuilder;
6512 public MethodBuilder GetBuilder, SetBuilder;
6514 protected EmitContext ec;
6516 public PropertyBase (TypeContainer parent, Expression type, int mod_flags,
6517 int allowed_mod, bool is_iface, MemberName name,
6518 Parameters parameters, Attributes attrs,
6520 : base (parent, null, type, mod_flags, allowed_mod, is_iface, name,
6521 attrs, parameters, loc)
6525 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6527 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
6528 a.Error_InvalidSecurityParent ();
6532 PropertyBuilder.SetCustomAttribute (cb);
6535 public override AttributeTargets AttributeTargets {
6537 return AttributeTargets.Property;
6541 public override bool Define ()
6543 if (!DoDefine (Parent))
6546 if (!IsTypePermitted ())
6552 protected override bool DoDefine (DeclSpace ds)
6554 if (!base.DoDefine (ds))
6558 // Accessors modifiers check
6560 if (Get.ModFlags != 0 && Set.ModFlags != 0) {
6561 Report.Error (274, Location, "'{0}': cannot specify accessibility modifiers for both accessors of the property or indexer.",
6562 GetSignatureForError ());
6566 if ((Get.IsDummy || Set.IsDummy)
6567 && (Get.ModFlags != 0 || Set.ModFlags != 0) && (ModFlags & Modifiers.OVERRIDE) == 0) {
6568 Report.Error (276, Location,
6569 "'{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor.",
6570 GetSignatureForError ());
6574 if (MemberType.IsAbstract && MemberType.IsSealed) {
6575 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
6579 ec = new EmitContext (Parent, Location, null, MemberType, ModFlags);
6583 public override string GetSignatureForError()
6585 if (PropertyBuilder == null)
6586 return GetSignatureForError (Parent);
6588 return TypeManager.CSharpSignature (PropertyBuilder, false);
6591 protected override bool CheckForDuplications ()
6593 ArrayList ar = Parent.Indexers;
6595 int arLen = ar.Count;
6597 for (int i = 0; i < arLen; i++) {
6598 Indexer m = (Indexer) ar [i];
6599 if (IsDuplicateImplementation (m))
6604 ar = Parent.Properties;
6606 int arLen = ar.Count;
6608 for (int i = 0; i < arLen; i++) {
6609 Property m = (Property) ar [i];
6610 if (IsDuplicateImplementation (m))
6618 // TODO: rename to Resolve......
6619 protected override MethodInfo FindOutBaseMethod (TypeContainer container, ref Type base_ret_type)
6621 PropertyInfo base_property = container.BaseCache.FindMemberToOverride (
6622 container.TypeBuilder, Name, ParameterTypes, true) as PropertyInfo;
6624 if (base_property == null)
6627 base_ret_type = base_property.PropertyType;
6628 MethodInfo get_accessor = base_property.GetGetMethod (true);
6629 MethodInfo set_accessor = base_property.GetSetMethod (true);
6630 MethodAttributes get_accessor_access, set_accessor_access;
6632 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
6633 if (Get != null && !Get.IsDummy && get_accessor == null) {
6634 Report.SymbolRelatedToPreviousError (base_property);
6635 Report.Error (545, Location, "'{0}': cannot override because '{1}' does not have an overridable get accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6638 if (Set != null && !Set.IsDummy && set_accessor == null) {
6639 Report.SymbolRelatedToPreviousError (base_property);
6640 Report.Error (546, Location, "'{0}': cannot override because '{1}' does not have an overridable set accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6645 // Check base class accessors access
6647 get_accessor_access = set_accessor_access = 0;
6648 if ((ModFlags & Modifiers.NEW) == 0) {
6649 if (get_accessor != null) {
6650 MethodAttributes get_flags = Modifiers.MethodAttr (Get.ModFlags != 0 ? Get.ModFlags : ModFlags);
6651 get_accessor_access = (get_accessor.Attributes & MethodAttributes.MemberAccessMask);
6653 if (!Get.IsDummy && !CheckAccessModifiers (get_flags & MethodAttributes.MemberAccessMask, get_accessor_access, get_accessor))
6654 Report.Error (507, Location, "'{0}' can't change the access modifiers when overriding inherited member '{1}'",
6655 GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6658 if (set_accessor != null) {
6659 MethodAttributes set_flags = Modifiers.MethodAttr (Set.ModFlags != 0 ? Set.ModFlags : ModFlags);
6660 set_accessor_access = (set_accessor.Attributes & MethodAttributes.MemberAccessMask);
6662 if (!Set.IsDummy && !CheckAccessModifiers (set_flags & MethodAttributes.MemberAccessMask, set_accessor_access, set_accessor))
6663 Report.Error (507, Location, "'{0}' can't change the access modifiers when overriding inherited member '{1}'",
6664 GetSignatureForError (container), TypeManager.GetFullNameSignature (base_property));
6669 // Get the less restrictive access
6671 return get_accessor_access > set_accessor_access ? get_accessor : set_accessor;
6674 public override void Emit ()
6677 // The PropertyBuilder can be null for explicit implementations, in that
6678 // case, we do not actually emit the ".property", so there is nowhere to
6679 // put the attribute
6681 if (PropertyBuilder != null && OptAttributes != null)
6682 OptAttributes.Emit (ec, this);
6694 /// Tests whether accessors are not in collision with some method (CS0111)
6696 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6698 return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
6701 protected override void UpdateMemberName ()
6703 base.UpdateMemberName ();
6705 Get.UpdateName (this);
6706 Set.UpdateName (this);
6709 protected override bool VerifyClsCompliance (DeclSpace ds)
6711 if (!base.VerifyClsCompliance (ds))
6714 if ((Get.ModFlags != ModFlags && !Get.IsDummy) || (Set.ModFlags != ModFlags && !Set.IsDummy)) {
6715 Report.Error (3025, Get.ModFlags != ModFlags ? Get.Location : Set.Location,
6716 "CLS-compliant accessors must have the same accessibility as their property");
6721 public override string[] ValidAttributeTargets {
6723 return attribute_targets;
6728 // Represents header string for documentation comment.
6730 public override string DocCommentHeader {
6731 get { return "P:"; }
6735 public class Property : PropertyBase, IIteratorContainer {
6736 const int AllowedModifiers =
6739 Modifiers.PROTECTED |
6740 Modifiers.INTERNAL |
6744 Modifiers.OVERRIDE |
6745 Modifiers.ABSTRACT |
6748 Modifiers.METHOD_YIELDS |
6751 const int AllowedInterfaceModifiers =
6754 public Property (TypeContainer parent, Expression type, int mod_flags,
6755 bool is_iface, MemberName name, Attributes attrs,
6756 Accessor get_block, Accessor set_block, Location loc)
6757 : base (parent, type, mod_flags,
6758 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6759 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
6762 if (get_block == null)
6763 Get = new GetMethod (this);
6765 Get = new GetMethod (this, get_block);
6767 if (set_block == null)
6768 Set = new SetMethod (this);
6770 Set = new SetMethod (this, set_block);
6773 public override bool Define ()
6775 if (!DoDefineBase ())
6778 if (!base.Define ())
6784 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6788 GetBuilder = Get.Define (Parent);
6789 if (GetBuilder == null)
6793 // Setup iterator if we are one
6795 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
6796 Iterator iterator = new Iterator (
6797 Parent, "get", MemberType,
6798 TypeManager.NoTypes, Get.ParameterInfo,
6799 ModFlags, Get.Block, Location);
6801 if (!iterator.DefineIterator ())
6803 Get.Block = iterator.Block;
6808 SetBuilder = Set.Define (Parent);
6809 if (SetBuilder == null)
6812 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
6815 // FIXME - PropertyAttributes.HasDefault ?
6817 PropertyAttributes prop_attr = PropertyAttributes.None;
6819 prop_attr |= PropertyAttributes.RTSpecialName |
6820 PropertyAttributes.SpecialName;
6822 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6823 Name, prop_attr, MemberType, null);
6826 PropertyBuilder.SetGetMethod (GetBuilder);
6829 PropertyBuilder.SetSetMethod (SetBuilder);
6831 TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
6835 public void SetYields ()
6837 ModFlags |= Modifiers.METHOD_YIELDS;
6842 /// Gigantic workaround for lameness in SRE follows :
6843 /// This class derives from EventInfo and attempts to basically
6844 /// wrap around the EventBuilder so that FindMembers can quickly
6845 /// return this in it search for members
6847 public class MyEventBuilder : EventInfo {
6850 // We use this to "point" to our Builder which is
6851 // not really a MemberInfo
6853 EventBuilder MyBuilder;
6856 // We "catch" and wrap these methods
6858 MethodInfo raise, remove, add;
6860 EventAttributes attributes;
6861 Type declaring_type, reflected_type, event_type;
6866 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
6868 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
6870 // And now store the values in our own fields.
6872 declaring_type = type_builder;
6874 reflected_type = type_builder;
6876 attributes = event_attr;
6879 this.event_type = event_type;
6883 // Methods that you have to override. Note that you only need
6884 // to "implement" the variants that take the argument (those are
6885 // the "abstract" methods, the others (GetAddMethod()) are
6888 public override MethodInfo GetAddMethod (bool nonPublic)
6893 public override MethodInfo GetRemoveMethod (bool nonPublic)
6898 public override MethodInfo GetRaiseMethod (bool nonPublic)
6904 // These methods make "MyEventInfo" look like a Builder
6906 public void SetRaiseMethod (MethodBuilder raiseMethod)
6908 raise = raiseMethod;
6909 MyBuilder.SetRaiseMethod (raiseMethod);
6912 public void SetRemoveOnMethod (MethodBuilder removeMethod)
6914 remove = removeMethod;
6915 MyBuilder.SetRemoveOnMethod (removeMethod);
6918 public void SetAddOnMethod (MethodBuilder addMethod)
6921 MyBuilder.SetAddOnMethod (addMethod);
6924 public void SetCustomAttribute (CustomAttributeBuilder cb)
6926 MyBuilder.SetCustomAttribute (cb);
6929 public override object [] GetCustomAttributes (bool inherit)
6931 // FIXME : There's nothing which can be seemingly done here because
6932 // we have no way of getting at the custom attribute objects of the
6937 public override object [] GetCustomAttributes (Type t, bool inherit)
6939 // FIXME : Same here !
6943 public override bool IsDefined (Type t, bool b)
6948 public override EventAttributes Attributes {
6954 public override string Name {
6960 public override Type DeclaringType {
6962 return declaring_type;
6966 public override Type ReflectedType {
6968 return reflected_type;
6972 public Type EventType {
6978 public void SetUsed ()
6980 if (my_event != null)
6981 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
6986 /// For case when event is declared like property (with add and remove accessors).
6988 public class EventProperty: Event {
6990 static string[] attribute_targets = new string [] { "event", "property" };
6992 public EventProperty (TypeContainer parent, Expression type, int mod_flags,
6993 bool is_iface, MemberName name, Object init,
6994 Attributes attrs, Accessor add, Accessor remove,
6996 : base (parent, type, mod_flags, is_iface, name, init, attrs, loc)
6998 Add = new AddDelegateMethod (this, add);
6999 Remove = new RemoveDelegateMethod (this, remove);
7001 // For this event syntax we don't report error CS0067
7002 // because it is hard to do it.
7006 public override string[] ValidAttributeTargets {
7008 return attribute_targets;
7014 /// Event is declared like field.
7016 public class EventField: Event {
7018 static string[] attribute_targets = new string [] { "event", "field", "method" };
7019 static string[] attribute_targets_interface = new string[] { "event", "method" };
7021 public EventField (TypeContainer parent, Expression type, int mod_flags,
7022 bool is_iface, MemberName name, Object init,
7023 Attributes attrs, Location loc)
7024 : base (parent, type, mod_flags, is_iface, name, init, attrs, loc)
7026 Add = new AddDelegateMethod (this);
7027 Remove = new RemoveDelegateMethod (this);
7030 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7032 if (a.Target == AttributeTargets.Field) {
7033 FieldBuilder.SetCustomAttribute (cb);
7037 if (a.Target == AttributeTargets.Method) {
7038 Add.ApplyAttributeBuilder (a, cb);
7039 Remove.ApplyAttributeBuilder (a, cb);
7043 base.ApplyAttributeBuilder (a, cb);
7046 public override string[] ValidAttributeTargets {
7048 return IsInterface ? attribute_targets_interface : attribute_targets;
7053 public abstract class Event : FieldBase {
7055 protected sealed class AddDelegateMethod: DelegateMethod
7058 public AddDelegateMethod (Event method):
7059 base (method, "add_")
7063 public AddDelegateMethod (Event method, Accessor accessor):
7064 base (method, accessor, "add_")
7068 protected override MethodInfo DelegateMethodInfo {
7070 return TypeManager.delegate_combine_delegate_delegate;
7076 protected sealed class RemoveDelegateMethod: DelegateMethod
7078 public RemoveDelegateMethod (Event method):
7079 base (method, "remove_")
7083 public RemoveDelegateMethod (Event method, Accessor accessor):
7084 base (method, accessor, "remove_")
7088 protected override MethodInfo DelegateMethodInfo {
7090 return TypeManager.delegate_remove_delegate_delegate;
7096 public abstract class DelegateMethod: AbstractPropertyEventMethod
7098 protected readonly Event method;
7099 ImplicitParameter param_attr;
7101 static string[] attribute_targets = new string [] { "method", "param", "return" };
7103 public DelegateMethod (Event method, string prefix)
7104 : base (method, prefix)
7106 this.method = method;
7109 public DelegateMethod (Event method, Accessor accessor, string prefix)
7110 : base (method, accessor, prefix)
7112 this.method = method;
7115 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
7117 if (a.Target == AttributeTargets.Parameter) {
7118 if (param_attr == null)
7119 param_attr = new ImplicitParameter (method_data.MethodBuilder);
7121 param_attr.ApplyAttributeBuilder (a, cb);
7125 base.ApplyAttributeBuilder (a, cb);
7128 public override AttributeTargets AttributeTargets {
7130 return AttributeTargets.Method;
7134 public override bool IsClsCompliaceRequired(DeclSpace ds)
7136 return method.IsClsCompliaceRequired (ds);
7139 public MethodBuilder Define (TypeContainer container, InternalParameters ip)
7141 method_data = new MethodData (method, ip, method.ModFlags,
7142 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
7144 if (!method_data.Define (container))
7147 MethodBuilder mb = method_data.MethodBuilder;
7148 mb.DefineParameter (1, ParameterAttributes.None, "value");
7153 public override void Emit (TypeContainer tc)
7155 if (block != null) {
7160 ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
7161 FieldInfo field_info = (FieldInfo)method.FieldBuilder;
7163 method_data.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Synchronized);
7164 if ((method.ModFlags & Modifiers.STATIC) != 0) {
7165 ig.Emit (OpCodes.Ldsfld, field_info);
7166 ig.Emit (OpCodes.Ldarg_0);
7167 ig.Emit (OpCodes.Call, DelegateMethodInfo);
7168 ig.Emit (OpCodes.Castclass, method.MemberType);
7169 ig.Emit (OpCodes.Stsfld, field_info);
7171 ig.Emit (OpCodes.Ldarg_0);
7172 ig.Emit (OpCodes.Ldarg_0);
7173 ig.Emit (OpCodes.Ldfld, field_info);
7174 ig.Emit (OpCodes.Ldarg_1);
7175 ig.Emit (OpCodes.Call, DelegateMethodInfo);
7176 ig.Emit (OpCodes.Castclass, method.MemberType);
7177 ig.Emit (OpCodes.Stfld, field_info);
7179 ig.Emit (OpCodes.Ret);
7182 protected abstract MethodInfo DelegateMethodInfo { get; }
7184 public override Type[] ParameterTypes {
7186 return new Type[] { method.MemberType };
7190 public override Type ReturnType {
7192 return TypeManager.void_type;
7196 public override EmitContext CreateEmitContext (TypeContainer tc,
7199 return new EmitContext (
7200 tc, method.Parent, Location, ig, ReturnType,
7201 method.ModFlags, false);
7204 public override string GetSignatureForError (TypeContainer tc)
7206 return String.Concat (tc.Name, '.', method.Name);
7209 public override ObsoleteAttribute GetObsoleteAttribute ()
7211 return method.GetObsoleteAttribute (method.Parent);
7214 public override string[] ValidAttributeTargets {
7216 return attribute_targets;
7222 const int AllowedModifiers =
7225 Modifiers.PROTECTED |
7226 Modifiers.INTERNAL |
7231 Modifiers.OVERRIDE |
7235 const int AllowedInterfaceModifiers =
7238 public DelegateMethod Add, Remove;
7239 public MyEventBuilder EventBuilder;
7240 public MethodBuilder AddBuilder, RemoveBuilder;
7242 MethodData AddData, RemoveData;
7244 public Event (TypeContainer parent, Expression type, int mod_flags,
7245 bool is_iface, MemberName name, Object init, Attributes attrs,
7247 : base (parent, type, mod_flags,
7248 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
7249 name, init, attrs, loc)
7251 IsInterface = is_iface;
7254 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7256 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
7257 a.Error_InvalidSecurityParent ();
7261 EventBuilder.SetCustomAttribute (cb);
7264 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
7266 return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
7269 public override AttributeTargets AttributeTargets {
7271 return AttributeTargets.Event;
7275 public override bool Define ()
7277 EventAttributes e_attr;
7278 e_attr = EventAttributes.None;
7280 if (!DoDefineBase ())
7283 if (!DoDefine (Parent))
7286 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
7287 Report.Error (74, Location, "'" + Parent.Name + "." + Name +
7288 "': abstract event can not have an initializer");
7292 if (!TypeManager.IsDelegateType (MemberType)) {
7293 Report.Error (66, Location, "'" + Parent.Name + "." + Name +
7294 "' : event must be of a delegate type");
7298 EmitContext ec = Parent.EmitContext;
7300 throw new InternalErrorException ("Event.Define called too early?");
7301 bool old_unsafe = ec.InUnsafe;
7302 ec.InUnsafe = InUnsafe;
7304 Parameter [] parms = new Parameter [1];
7305 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
7306 Parameters parameters = new Parameters (parms, null, Location);
7307 Type [] types = parameters.GetParameterInfo (ec);
7308 InternalParameters ip = new InternalParameters (types, parameters);
7310 ec.InUnsafe = old_unsafe;
7316 // Now define the accessors
7319 AddBuilder = Add.Define (Parent, ip);
7320 if (AddBuilder == null)
7323 RemoveBuilder = Remove.Define (Parent, ip);
7324 if (RemoveBuilder == null)
7327 EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, e_attr, MemberType);
7329 if (Add.Block == null && Remove.Block == null && !IsInterface) {
7330 FieldBuilder = Parent.TypeBuilder.DefineField (
7332 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
7333 TypeManager.RegisterPrivateFieldOfEvent (
7334 (EventInfo) EventBuilder, FieldBuilder);
7335 TypeManager.RegisterFieldBase (FieldBuilder, this);
7338 EventBuilder.SetAddOnMethod (AddBuilder);
7339 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
7341 TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder);
7345 protected override bool CheckBase ()
7347 if (!base.CheckBase ())
7350 if (conflict_symbol != null && (ModFlags & Modifiers.NEW) == 0) {
7351 if (!(conflict_symbol is EventInfo)) {
7352 Report.SymbolRelatedToPreviousError (conflict_symbol);
7353 Report.Error (72, Location, "Event '{0}' can override only event", GetSignatureForError (Parent));
7361 public override void Emit ()
7363 if (OptAttributes != null) {
7364 EmitContext ec = new EmitContext (
7365 Parent, Location, null, MemberType, ModFlags);
7366 OptAttributes.Emit (ec, this);
7371 Remove.Emit (Parent);
7377 public override string GetSignatureForError ()
7379 if (EventBuilder == null)
7380 return base.GetSignatureForError (Parent);
7382 return TypeManager.GetFullNameSignature (EventBuilder);
7386 // Represents header string for documentation comment.
7388 public override string DocCommentHeader {
7389 get { return "E:"; }
7394 public class Indexer : PropertyBase {
7396 class GetIndexerMethod: GetMethod
7398 public GetIndexerMethod (MethodCore method):
7403 public GetIndexerMethod (MethodCore method, Accessor accessor):
7404 base (method, accessor)
7408 // TODO: one GetSignatureForError is enough (reuse Parent member)
7409 public override string GetSignatureForError (TypeContainer tc)
7411 string core = base.GetSignatureForError (tc);
7412 return core.Replace (TypeContainer.DefaultIndexerName,
7413 String.Format ("this[{0}]", TypeManager.CSharpName (ParameterTypes)));
7416 public override Type[] ParameterTypes {
7418 return method.ParameterTypes;
7423 class SetIndexerMethod: SetMethod
7425 readonly Parameters parameters;
7427 public SetIndexerMethod (MethodCore method):
7432 public SetIndexerMethod (MethodCore method, Parameters parameters, Accessor accessor):
7433 base (method, accessor)
7435 this.parameters = parameters;
7438 public override Type[] ParameterTypes {
7440 int top = method.ParameterTypes.Length;
7441 Type [] set_pars = new Type [top + 1];
7442 method.ParameterTypes.CopyTo (set_pars, 0);
7443 set_pars [top] = method.MemberType;
7448 protected override InternalParameters GetParameterInfo (EmitContext ec)
7450 Parameter [] fixed_parms = parameters.FixedParameters;
7452 if (fixed_parms == null){
7453 throw new Exception ("We currently do not support only array arguments in an indexer at: " + method.Location);
7454 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
7455 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
7457 // Here is the problem: the `value' parameter has
7458 // to come *after* the array parameter in the declaration
7460 // X (object [] x, Type value)
7463 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
7464 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
7468 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
7470 fixed_parms.CopyTo (tmp, 0);
7471 tmp [fixed_parms.Length] = new Parameter (
7472 method.Type, "value", Parameter.Modifier.NONE, null);
7474 Parameters set_formal_params = new Parameters (tmp, null, method.Location);
7475 Type [] types = set_formal_params.GetParameterInfo (ec);
7477 return new InternalParameters (types, set_formal_params);
7481 const int AllowedModifiers =
7484 Modifiers.PROTECTED |
7485 Modifiers.INTERNAL |
7489 Modifiers.OVERRIDE |
7494 const int AllowedInterfaceModifiers =
7498 // Are we implementing an interface ?
7500 public Indexer (TypeContainer parent, Expression type, MemberName name, int mod,
7501 bool is_iface, Parameters parameters, Attributes attrs,
7502 Accessor get_block, Accessor set_block, Location loc)
7503 : base (parent, type, mod,
7504 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
7505 is_iface, name, parameters, attrs, loc)
7507 if (get_block == null)
7508 Get = new GetIndexerMethod (this);
7510 Get = new GetIndexerMethod (this, get_block);
7512 if (set_block == null)
7513 Set = new SetIndexerMethod (this);
7515 Set = new SetIndexerMethod (this, parameters, set_block);
7518 public override bool Define ()
7520 PropertyAttributes prop_attr =
7521 PropertyAttributes.RTSpecialName |
7522 PropertyAttributes.SpecialName;
7524 if (!DoDefineBase ())
7527 if (!base.Define ())
7530 if (MemberType == TypeManager.void_type) {
7531 Report.Error (620, Location, "Indexers cannot have void type");
7535 if (OptAttributes != null) {
7536 Attribute indexer_attr = OptAttributes.Search (TypeManager.indexer_name_type, ec);
7537 if (indexer_attr != null) {
7538 // Remove the attribute from the list because it is not emitted
7539 OptAttributes.Attrs.Remove (indexer_attr);
7541 ShortName = indexer_attr.GetIndexerAttributeValue (ec);
7543 if (IsExplicitImpl) {
7544 Report.Error (415, indexer_attr.Location,
7545 "The 'IndexerName' attribute is valid only on an " +
7546 "indexer that is not an explicit interface member declaration");
7550 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
7551 Report.Error (609, indexer_attr.Location,
7552 "Cannot set the 'IndexerName' attribute on an indexer marked override");
7556 if (!Tokenizer.IsValidIdentifier (ShortName)) {
7557 Report.Error (633, indexer_attr.Location,
7558 "The argument to the 'IndexerName' attribute must be a valid identifier");
7562 UpdateMemberName ();
7566 if (InterfaceType != null) {
7567 string base_IndexerName = TypeManager.IndexerPropertyName (InterfaceType);
7568 if (base_IndexerName != Name)
7569 ShortName = base_IndexerName;
7570 UpdateMemberName ();
7573 if (!Parent.AddToMemberContainer (this) ||
7574 !Parent.AddToMemberContainer (Get) || !Parent.AddToMemberContainer (Set))
7580 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
7582 GetBuilder = Get.Define (Parent);
7583 if (GetBuilder == null)
7588 SetBuilder = Set.Define (Parent);
7589 if (SetBuilder == null)
7594 // Now name the parameters
7596 Parameter [] p = Parameters.FixedParameters;
7598 if ((p [0].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
7599 Report.Error (631, Location, "ref and out are not valid in this context");
7605 for (i = 0; i < p.Length; ++i) {
7607 GetBuilder.DefineParameter (
7608 i + 1, p [i].Attributes, p [i].Name);
7611 SetBuilder.DefineParameter (
7612 i + 1, p [i].Attributes, p [i].Name);
7616 SetBuilder.DefineParameter (
7617 i + 1, ParameterAttributes.None, "value");
7619 if (i != ParameterTypes.Length) {
7620 Parameter array_param = Parameters.ArrayParameter;
7622 SetBuilder.DefineParameter (
7623 i + 1, array_param.Attributes, array_param.Name);
7627 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
7628 Name, prop_attr, MemberType, ParameterTypes);
7631 PropertyBuilder.SetGetMethod (GetBuilder);
7634 PropertyBuilder.SetSetMethod (SetBuilder);
7636 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder, ParameterTypes);
7641 public override string GetSignatureForError ()
7643 if (PropertyBuilder == null)
7644 return GetSignatureForError (Parent);
7646 return TypeManager.CSharpSignature (PropertyBuilder, true);
7649 public override string GetSignatureForError(TypeContainer tc)
7651 return String.Concat (tc.Name, ".this[", Parameters.FixedParameters [0].TypeName.ToString (), ']');
7654 public override bool MarkForDuplicationCheck ()
7656 caching_flags |= Flags.TestMethodDuplication;
7662 public class Operator : MethodCore, IIteratorContainer {
7664 const int AllowedModifiers =
7670 public enum OpType : byte {
7680 // Unary and Binary operators
7703 // Implicit and Explicit
7708 public readonly OpType OperatorType;
7709 public MethodBuilder OperatorMethodBuilder;
7711 public Method OperatorMethod;
7713 static string[] attribute_targets = new string [] { "method", "return" };
7715 public Operator (TypeContainer parent, OpType type, Expression ret_type,
7716 int mod_flags, Parameters parameters,
7717 ToplevelBlock block, Attributes attrs, Location loc)
7718 : base (parent, null, ret_type, mod_flags, AllowedModifiers, false,
7719 new MemberName ("op_" + type), attrs, parameters, loc)
7721 OperatorType = type;
7725 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7727 OperatorMethod.ApplyAttributeBuilder (a, cb);
7730 public override AttributeTargets AttributeTargets {
7732 return AttributeTargets.Method;
7736 protected override bool CheckGenericOverride (MethodInfo method, string name)
7741 protected override bool CheckForDuplications()
7743 ArrayList ar = Parent.Operators;
7745 int arLen = ar.Count;
7747 for (int i = 0; i < arLen; i++) {
7748 Operator o = (Operator) ar [i];
7749 if (IsDuplicateImplementation (o))
7754 ar = Parent.Methods;
7756 int arLen = ar.Count;
7758 for (int i = 0; i < arLen; i++) {
7759 Method m = (Method) ar [i];
7760 if (IsDuplicateImplementation (m))
7768 public override bool Define ()
7770 const int RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
7771 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
7772 Report.Error (558, Location, "User defined operators '{0}' must be declared static and public", GetSignatureForError (Parent));
7779 if (MemberType == TypeManager.void_type) {
7780 Report.Error (590, Location, "User-defined operators cannot return void");
7784 OperatorMethod = new Method (
7785 Parent, null, Type, ModFlags, false, MemberName,
7786 Parameters, OptAttributes, Location);
7788 OperatorMethod.Block = Block;
7789 OperatorMethod.IsOperator = true;
7790 OperatorMethod.flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
7791 OperatorMethod.Define ();
7793 if (OperatorMethod.MethodBuilder == null)
7796 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
7798 parameter_types = OperatorMethod.ParameterTypes;
7799 Type declaring_type = OperatorMethod.MethodData.DeclaringType;
7800 Type return_type = OperatorMethod.ReturnType;
7801 Type first_arg_type = parameter_types [0];
7806 // Rules for conversion operators
7808 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7809 if (first_arg_type == return_type && first_arg_type == declaring_type){
7812 "User-defined conversion cannot take an object of the " +
7813 "enclosing type and convert to an object of the enclosing" +
7818 if (first_arg_type != declaring_type && return_type != declaring_type){
7821 "User-defined conversion must convert to or from the " +
7826 if (first_arg_type == TypeManager.object_type ||
7827 return_type == TypeManager.object_type){
7830 "User-defined conversion cannot convert to or from " +
7835 if (first_arg_type.IsInterface || return_type.IsInterface){
7838 "User-defined conversion cannot convert to or from an " +
7843 if (first_arg_type.IsSubclassOf (return_type)
7844 || return_type.IsSubclassOf (first_arg_type)){
7845 if (declaring_type.IsSubclassOf (return_type)) {
7846 Report.Error (553, Location, "'{0}' : user defined conversion to/from base class", GetSignatureForError ());
7849 Report.Error (554, Location, "'{0}' : user defined conversion to/from derived class", GetSignatureForError ());
7852 } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
7853 if (first_arg_type != declaring_type || parameter_types [1] != TypeManager.int32_type) {
7854 Report.Error (564, Location, "Overloaded shift operator must have the type of the first operand be the containing type, and the type of the second operand must be int");
7857 } else if (Parameters.FixedParameters.Length == 1) {
7858 // Checks for Unary operators
7860 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
7861 if (return_type != declaring_type && !return_type.IsSubclassOf (declaring_type)) {
7862 Report.Error (448, Location,
7863 "The return type for ++ or -- operator must be the containing type or derived from the containing type");
7866 if (first_arg_type != declaring_type){
7868 559, Location, "The parameter type for ++ or -- operator must be the containing type");
7873 if (first_arg_type != declaring_type){
7876 "The parameter of a unary operator must be the " +
7881 if (OperatorType == OpType.True || OperatorType == OpType.False) {
7882 if (return_type != TypeManager.bool_type){
7885 "The return type of operator True or False " +
7892 if (OperatorType == OpType.BitwiseAnd &&
7893 (first_arg_type != return_type || first_arg_type != parameter_types [1])) {
7894 Report.Error (217, Location, "In order to be applicable as a short circuit operator a user-defined logical operator ('{0}') " +
7895 "must have the same return type as the type of its 2 parameters", GetSignatureForError ());
7899 // Checks for Binary operators
7901 if (first_arg_type != declaring_type &&
7902 parameter_types [1] != declaring_type){
7905 "One of the parameters of a binary operator must " +
7906 "be the containing type");
7914 public override void Emit ()
7917 // abstract or extern methods have no bodies
7919 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
7922 OperatorMethod.Emit ();
7926 // Operator cannot be override
7927 protected override MethodInfo FindOutBaseMethod (TypeContainer container, ref Type base_ret_type)
7932 public static string GetName (OpType ot)
7935 case OpType.LogicalNot:
7937 case OpType.OnesComplement:
7939 case OpType.Increment:
7941 case OpType.Decrement:
7947 case OpType.Addition:
7949 case OpType.Subtraction:
7951 case OpType.UnaryPlus:
7953 case OpType.UnaryNegation:
7955 case OpType.Multiply:
7957 case OpType.Division:
7959 case OpType.Modulus:
7961 case OpType.BitwiseAnd:
7963 case OpType.BitwiseOr:
7965 case OpType.ExclusiveOr:
7967 case OpType.LeftShift:
7969 case OpType.RightShift:
7971 case OpType.Equality:
7973 case OpType.Inequality:
7975 case OpType.GreaterThan:
7977 case OpType.LessThan:
7979 case OpType.GreaterThanOrEqual:
7981 case OpType.LessThanOrEqual:
7983 case OpType.Implicit:
7985 case OpType.Explicit:
7991 public override string GetSignatureForError (TypeContainer tc)
7993 StringBuilder sb = new StringBuilder ();
7994 sb.AppendFormat ("{0}.operator {1} {2}({3}", tc.Name, GetName (OperatorType), Type.Type == null ? Type.ToString () : TypeManager.CSharpName (Type.Type),
7995 Parameters.FixedParameters [0].GetSignatureForError ());
7997 if (Parameters.FixedParameters.Length > 1) {
7999 sb.Append (Parameters.FixedParameters [1].GetSignatureForError ());
8002 return sb.ToString ();
8005 public override string GetSignatureForError ()
8010 public override bool MarkForDuplicationCheck ()
8012 caching_flags |= Flags.TestMethodDuplication;
8016 public override string ToString ()
8018 if (OperatorMethod == null)
8021 Type return_type = OperatorMethod.ReturnType;
8022 Type [] param_types = OperatorMethod.ParameterTypes;
8024 if (Parameters.FixedParameters.Length == 1)
8025 return String.Format (
8026 "{0} operator {1}({2})",
8027 TypeManager.CSharpName (return_type),
8028 GetName (OperatorType),
8031 return String.Format (
8032 "{0} operator {1}({2}, {3})",
8033 TypeManager.CSharpName (return_type),
8034 GetName (OperatorType),
8035 param_types [0], param_types [1]);
8038 public override string[] ValidAttributeTargets {
8040 return attribute_targets;
8044 public void SetYields ()
8046 ModFlags |= Modifiers.METHOD_YIELDS;
8051 // This is used to compare method signatures
8053 struct MethodSignature {
8055 public Type RetType;
8056 public Type [] Parameters;
8059 /// This delegate is used to extract methods which have the
8060 /// same signature as the argument
8062 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
8064 public MethodSignature (string name, Type ret_type, Type [] parameters)
8069 if (parameters == null)
8070 Parameters = TypeManager.NoTypes;
8072 Parameters = parameters;
8075 public override string ToString ()
8078 if (Parameters.Length != 0){
8079 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
8080 for (int i = 0; i < Parameters.Length; i++){
8081 sb.Append (Parameters [i]);
8082 if (i+1 < Parameters.Length)
8085 pars = sb.ToString ();
8088 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
8091 public override int GetHashCode ()
8093 return Name.GetHashCode ();
8096 public override bool Equals (Object o)
8098 MethodSignature other = (MethodSignature) o;
8100 if (other.Name != Name)
8103 if (other.RetType != RetType)
8106 if (Parameters == null){
8107 if (other.Parameters == null)
8112 if (other.Parameters == null)
8115 int c = Parameters.Length;
8116 if (other.Parameters.Length != c)
8119 for (int i = 0; i < c; i++)
8120 if (other.Parameters [i] != Parameters [i])
8126 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
8128 MethodSignature sig = (MethodSignature) filter_criteria;
8130 if (m.Name != sig.Name)
8134 MethodInfo mi = m as MethodInfo;
8135 PropertyInfo pi = m as PropertyInfo;
8138 ReturnType = mi.ReturnType;
8139 else if (pi != null)
8140 ReturnType = pi.PropertyType;
8145 // we use sig.RetType == null to mean `do not check the
8146 // method return value.
8148 if (sig.RetType != null)
8149 if (ReturnType != sig.RetType)
8154 args = TypeManager.GetArgumentTypes (mi);
8156 args = TypeManager.GetArgumentTypes (pi);
8157 Type [] sigp = sig.Parameters;
8159 if (args.Length != sigp.Length)
8162 for (int i = args.Length; i > 0; ){
8164 if (args [i] != sigp [i])