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 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2008 Novell, Inc
15 using System.Collections.Generic;
16 using System.Reflection;
17 using System.Reflection.Emit;
18 using System.Runtime.CompilerServices;
19 using System.Runtime.InteropServices;
20 using System.Security;
21 using System.Security.Permissions;
25 using XmlElement = System.Object;
30 using Mono.CompilerServices.SymbolWriter;
32 namespace Mono.CSharp {
44 /// This is the base class for structs and classes.
46 public abstract class TypeContainer : DeclSpace, IMemberContainer
49 // Different context is needed when resolving type container base
50 // types. Type names come from the parent scope but type parameter
51 // names from the container scope.
53 struct BaseContext : IMemberContext
57 public BaseContext (TypeContainer tc)
62 #region IMemberContext Members
64 public CompilerContext Compiler {
65 get { return tc.Compiler; }
68 public Type CurrentType {
69 get { return tc.Parent.CurrentType; }
72 public TypeParameter[] CurrentTypeParameters {
73 get { return tc.PartialContainer.CurrentTypeParameters; }
76 public TypeContainer CurrentTypeDefinition {
77 get { return tc.Parent.CurrentTypeDefinition; }
80 public bool IsObsolete {
81 get { return tc.IsObsolete; }
84 public bool IsUnsafe {
85 get { return tc.IsUnsafe; }
88 public bool IsStatic {
89 get { return tc.IsStatic; }
92 public string GetSignatureForError ()
94 throw new NotImplementedException ();
97 public ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
102 public FullNamedExpression LookupNamespaceAlias (string name)
104 return tc.Parent.LookupNamespaceAlias (name);
107 public FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
109 TypeParameter[] tp = CurrentTypeParameters;
111 TypeParameter t = TypeParameter.FindTypeParameter (tp, name);
113 return new TypeParameterExpr (t, loc);
116 return tc.Parent.LookupNamespaceOrType (name, loc, ignore_cs0104);
126 GetHashCode = 1 << 1,
127 HasStaticFieldInitializer = 1 << 2
131 // Whether this is a struct, class or interface
132 public readonly Kind Kind;
134 // Holds a list of classes and structures
135 protected List<TypeContainer> types;
137 List<MemberCore> ordered_explicit_member_list;
138 List<MemberCore> ordered_member_list;
140 // Holds the list of properties
141 List<MemberCore> properties;
143 // Holds the list of delegates
144 List<TypeContainer> delegates;
146 // Holds the list of constructors
147 protected List<MemberCore> instance_constructors;
149 // Holds the list of fields
150 protected List<MemberCore> fields;
152 // Holds a list of fields that have initializers
153 protected List<FieldInitializer> initialized_fields;
155 // Holds a list of static fields that have initializers
156 protected List<FieldInitializer> initialized_static_fields;
158 // Holds the list of constants
159 protected List<MemberCore> constants;
161 // Holds the methods.
162 List<MemberCore> methods;
165 protected List<MemberCore> events;
167 // Holds the indexers
168 List<MemberCore> indexers;
170 // Holds the operators
171 List<MemberCore> operators;
173 // Holds the compiler generated classes
174 List<CompilerGeneratedClass> compiler_generated;
177 // Pointers to the default constructor and the default static constructor
179 protected Constructor default_constructor;
180 protected Constructor default_static_constructor;
183 // Points to the first non-static field added to the container.
185 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
186 // and the first one's as good as any.
188 FieldBase first_nonstatic_field = null;
191 // This one is computed after we can distinguish interfaces
192 // from classes from the arraylist `type_bases'
195 TypeExpr[] iface_exprs;
197 GenericTypeParameterBuilder[] nested_gen_params;
199 protected List<FullNamedExpression> type_bases;
201 protected bool members_defined;
202 bool members_defined_ok;
204 // The interfaces we implement.
205 protected Type[] ifaces;
207 // The base member cache and our member cache
208 MemberCache base_cache;
209 protected MemberCache member_cache;
211 public const string DefaultIndexerName = "Item";
213 private bool seen_normal_indexers = false;
214 private string indexer_name = DefaultIndexerName;
215 protected bool requires_delayed_unmanagedtype_check;
217 private CachedMethods cached_method;
219 List<TypeContainer> partial_parts;
222 /// The pending methods that need to be implemented
223 // (interfaces or abstract methods)
225 PendingImplementation pending;
227 public TypeContainer (NamespaceEntry ns, DeclSpace parent, MemberName name,
228 Attributes attrs, Kind kind)
229 : base (ns, parent, name, attrs)
231 if (parent != null && parent.NamespaceEntry != ns)
232 throw new InternalErrorException ("A nested type should be in the same NamespaceEntry as its enclosing class");
235 this.PartialContainer = this;
238 public bool AddMember (MemberCore symbol)
240 return AddToContainer (symbol, symbol.MemberName.Basename);
243 protected virtual bool AddMemberType (DeclSpace ds)
245 return AddToContainer (ds, ds.Basename);
248 protected virtual void RemoveMemberType (DeclSpace ds)
250 RemoveFromContainer (ds.Basename);
253 public void AddConstant (Const constant)
255 if (!AddMember (constant))
258 if (constants == null)
259 constants = new List<MemberCore> ();
261 constants.Add (constant);
264 public TypeContainer AddTypeContainer (TypeContainer tc)
266 if (!AddMemberType (tc))
270 types = new List<TypeContainer> ();
276 public virtual TypeContainer AddPartial (TypeContainer next_part)
278 return AddPartial (next_part, next_part.Basename);
281 protected TypeContainer AddPartial (TypeContainer next_part, string name)
283 next_part.ModFlags |= Modifiers.PARTIAL;
284 TypeContainer tc = GetDefinition (name) as TypeContainer;
286 return AddTypeContainer (next_part);
288 if ((tc.ModFlags & Modifiers.PARTIAL) == 0) {
289 Report.SymbolRelatedToPreviousError (next_part);
290 Error_MissingPartialModifier (tc);
293 if (tc.Kind != next_part.Kind) {
294 Report.SymbolRelatedToPreviousError (tc);
295 Report.Error (261, next_part.Location,
296 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
297 next_part.GetSignatureForError ());
300 if ((tc.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) &&
301 ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 &&
302 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
303 Report.SymbolRelatedToPreviousError (tc);
304 Report.Error (262, next_part.Location,
305 "Partial declarations of `{0}' have conflicting accessibility modifiers",
306 next_part.GetSignatureForError ());
309 if (tc.partial_parts == null)
310 tc.partial_parts = new List<TypeContainer> (1);
312 if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
313 tc.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
314 } else if ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
315 tc.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
316 tc.ModFlags |= next_part.ModFlags;
318 tc.ModFlags |= next_part.ModFlags;
321 if (next_part.attributes != null) {
322 if (tc.attributes == null)
323 tc.attributes = next_part.attributes;
325 tc.attributes.AddAttributes (next_part.attributes.Attrs);
328 next_part.PartialContainer = tc;
329 tc.partial_parts.Add (next_part);
333 public virtual void RemoveTypeContainer (TypeContainer next_part)
336 types.Remove (next_part);
337 RemoveMemberType (next_part);
340 public void AddDelegate (Delegate d)
342 if (!AddMemberType (d))
345 if (delegates == null)
346 delegates = new List<TypeContainer> ();
351 private void AddMemberToList (MemberCore mc, List<MemberCore> alist, bool isexplicit)
353 if (ordered_explicit_member_list == null) {
354 ordered_explicit_member_list = new List<MemberCore> ();
355 ordered_member_list = new List<MemberCore> ();
359 if (Kind == Kind.Interface) {
360 Report.Error (541, mc.Location,
361 "`{0}': explicit interface declaration can only be declared in a class or struct",
362 mc.GetSignatureForError ());
365 ordered_explicit_member_list.Add (mc);
366 alist.Insert (0, mc);
368 ordered_member_list.Add (mc);
374 public void AddMethod (MethodOrOperator method)
376 if (!AddToContainer (method, method.MemberName.Basename))
380 methods = new List<MemberCore> ();
382 if (method.MemberName.Left != null)
383 AddMemberToList (method, methods, true);
385 AddMemberToList (method, methods, false);
388 public void AddConstructor (Constructor c)
390 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
391 if (!AddToContainer (c, is_static ?
392 ConstructorBuilder.ConstructorName : ConstructorBuilder.TypeConstructorName))
395 if (is_static && c.Parameters.IsEmpty){
396 if (default_static_constructor != null) {
397 Report.SymbolRelatedToPreviousError (default_static_constructor);
398 Report.Error (111, c.Location,
399 "A member `{0}' is already defined. Rename this member or use different parameter types",
400 c.GetSignatureForError ());
404 default_static_constructor = c;
406 if (c.Parameters.IsEmpty)
407 default_constructor = c;
409 if (instance_constructors == null)
410 instance_constructors = new List<MemberCore> ();
412 instance_constructors.Add (c);
416 public bool AddField (FieldBase field)
418 if (!AddMember (field))
422 fields = new List<MemberCore> ();
426 if ((field.ModFlags & Modifiers.STATIC) != 0)
429 if (first_nonstatic_field == null) {
430 first_nonstatic_field = field;
434 if (Kind == Kind.Struct && first_nonstatic_field.Parent != field.Parent) {
435 Report.SymbolRelatedToPreviousError (first_nonstatic_field.Parent);
436 Report.Warning (282, 3, field.Location,
437 "struct instance field `{0}' found in different declaration from instance field `{1}'",
438 field.GetSignatureForError (), first_nonstatic_field.GetSignatureForError ());
443 public void AddProperty (Property prop)
445 if (!AddMember (prop) ||
446 !AddMember (prop.Get) || !AddMember (prop.Set))
449 if (properties == null)
450 properties = new List<MemberCore> ();
452 if (prop.MemberName.Left != null)
453 AddMemberToList (prop, properties, true);
455 AddMemberToList (prop, properties, false);
458 public void AddEvent (Event e)
463 if (e is EventProperty) {
464 if (!AddMember (e.Add))
467 if (!AddMember (e.Remove))
472 events = new List<MemberCore> ();
478 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
480 public void AddIndexer (Indexer i)
482 if (indexers == null)
483 indexers = new List<MemberCore> ();
485 if (i.IsExplicitImpl)
486 AddMemberToList (i, indexers, true);
488 AddMemberToList (i, indexers, false);
491 public void AddOperator (Operator op)
496 if (operators == null)
497 operators = new List<MemberCore> ();
502 public void AddCompilerGeneratedClass (CompilerGeneratedClass c)
504 Report.Debug (64, "ADD COMPILER GENERATED CLASS", this, c);
506 if (compiler_generated == null)
507 compiler_generated = new List<CompilerGeneratedClass> ();
509 compiler_generated.Add (c);
512 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
514 if (a.Type == pa.DefaultMember) {
515 if (Indexers != null) {
516 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
521 base.ApplyAttributeBuilder (a, cb, pa);
524 public override AttributeTargets AttributeTargets {
526 throw new NotSupportedException ();
530 public IList<TypeContainer> Types {
536 public IList<MemberCore> Methods {
542 public IList<MemberCore> Constants {
548 protected virtual Type BaseType {
550 return TypeBuilder.BaseType;
554 public IList<MemberCore> Fields {
560 public IList<MemberCore> InstanceConstructors {
562 return instance_constructors;
566 public IList<MemberCore> Properties {
572 public IList<MemberCore> Events {
578 public IList<MemberCore> Indexers {
584 public IList<MemberCore> Operators {
590 public IList<TypeContainer> Delegates {
596 protected override TypeAttributes TypeAttr {
598 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel) | base.TypeAttr;
602 public string IndexerName {
604 return indexers == null ? DefaultIndexerName : indexer_name;
608 public bool IsComImport {
610 if (OptAttributes == null)
613 return OptAttributes.Contains (PredefinedAttributes.Get.ComImport);
617 public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
619 if ((field.ModFlags & Modifiers.STATIC) != 0){
620 if (initialized_static_fields == null) {
621 PartialContainer.HasStaticFieldInitializer = true;
622 initialized_static_fields = new List<FieldInitializer> (4);
625 initialized_static_fields.Add (expression);
627 if (initialized_fields == null)
628 initialized_fields = new List<FieldInitializer> (4);
630 initialized_fields.Add (expression);
634 public void ResolveFieldInitializers (BlockContext ec)
636 if (partial_parts != null) {
637 foreach (TypeContainer part in partial_parts) {
638 part.DoResolveFieldInitializers (ec);
641 DoResolveFieldInitializers (ec);
644 void DoResolveFieldInitializers (BlockContext ec)
647 if (initialized_static_fields == null)
650 bool has_complex_initializer = !RootContext.Optimize;
652 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
653 for (i = 0; i < initialized_static_fields.Count; ++i) {
654 FieldInitializer fi = initialized_static_fields [i];
655 ExpressionStatement s = fi.ResolveStatement (ec);
657 s = EmptyExpressionStatement.Instance;
658 } else if (fi.IsComplexInitializer) {
659 has_complex_initializer |= true;
665 for (i = 0; i < initialized_static_fields.Count; ++i) {
666 FieldInitializer fi = initialized_static_fields [i];
668 // Need special check to not optimize code like this
669 // static int a = b = 5;
672 if (!has_complex_initializer && fi.IsDefaultInitializer)
675 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
681 if (initialized_fields == null)
684 for (int i = 0; i < initialized_fields.Count; ++i) {
685 FieldInitializer fi = (FieldInitializer) initialized_fields [i];
686 ExpressionStatement s = fi.ResolveStatement (ec);
691 // Field is re-initialized to its default value => removed
693 if (fi.IsDefaultInitializer && RootContext.Optimize)
696 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
700 public override string DocComment {
712 public PendingImplementation PendingImplementations {
713 get { return pending; }
716 public override bool GetClsCompliantAttributeValue ()
718 if (PartialContainer != this)
719 return PartialContainer.GetClsCompliantAttributeValue ();
721 return base.GetClsCompliantAttributeValue ();
724 public virtual void AddBasesForPart (DeclSpace part, List<FullNamedExpression> bases)
726 // FIXME: get rid of partial_parts and store lists of bases of each part here
727 // assumed, not verified: 'part' is in 'partial_parts'
728 ((TypeContainer) part).type_bases = bases;
732 /// This function computes the Base class and also the
733 /// list of interfaces that the class or struct @c implements.
735 /// The return value is an array (might be null) of
736 /// interfaces implemented (as Types).
738 /// The @base_class argument is set to the base object or null
739 /// if this is `System.Object'.
741 protected virtual TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
744 if (type_bases == null)
747 int count = type_bases.Count;
748 TypeExpr [] ifaces = null;
749 IMemberContext base_context = new BaseContext (this);
750 for (int i = 0, j = 0; i < count; i++){
751 FullNamedExpression fne = (FullNamedExpression) type_bases [i];
754 // Standard ResolveAsTypeTerminal cannot be used in this case because
755 // it does ObsoleteAttribute and constraint checks which require
756 // base type to be set
758 TypeExpr fne_resolved = fne.ResolveAsBaseTerminal (base_context, false);
759 if (fne_resolved == null)
762 if (i == 0 && Kind == Kind.Class && !fne_resolved.Type.IsInterface) {
763 if (fne_resolved is DynamicTypeExpr)
764 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
765 GetSignatureForError ());
767 base_class = fne_resolved;
772 ifaces = new TypeExpr [count - i];
774 if (fne_resolved.Type.IsInterface) {
775 for (int ii = 0; ii < j; ++ii) {
776 if (TypeManager.IsEqual (fne_resolved.Type, ifaces [ii].Type)) {
777 Report.Error (528, Location, "`{0}' is already listed in interface list",
778 fne_resolved.GetSignatureForError ());
783 if (Kind == Kind.Interface && !IsAccessibleAs (fne_resolved.Type)) {
784 Report.Error (61, fne.Location,
785 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
786 fne_resolved.GetSignatureForError (), GetSignatureForError ());
789 Report.SymbolRelatedToPreviousError (fne_resolved.Type);
790 if (Kind != Kind.Class) {
791 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
792 } else if (base_class != null)
793 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
794 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
796 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
797 GetSignatureForError (), fne_resolved.GetSignatureForError ());
801 ifaces [j++] = fne_resolved;
807 TypeExpr[] GetNormalPartialBases (ref TypeExpr base_class)
809 var ifaces = new List<TypeExpr> (0);
810 if (iface_exprs != null)
811 ifaces.AddRange (iface_exprs);
813 foreach (TypeContainer part in partial_parts) {
814 TypeExpr new_base_class;
815 TypeExpr[] new_ifaces = part.ResolveBaseTypes (out new_base_class);
816 if (new_base_class != TypeManager.system_object_expr) {
817 if (base_class == TypeManager.system_object_expr)
818 base_class = new_base_class;
820 if (new_base_class != null && !TypeManager.IsEqual (new_base_class.Type, base_class.Type)) {
821 Report.SymbolRelatedToPreviousError (base_class.Location, "");
822 Report.Error (263, part.Location,
823 "Partial declarations of `{0}' must not specify different base classes",
824 part.GetSignatureForError ());
831 if (new_ifaces == null)
834 foreach (TypeExpr iface in new_ifaces) {
835 if (ifaces.Contains (iface))
842 if (ifaces.Count == 0)
845 return ifaces.ToArray ();
849 // Checks that some operators come in pairs:
855 // They are matched based on the return type and the argument types
857 void CheckPairedOperators ()
859 bool has_equality_or_inequality = false;
860 var operators = this.operators.ToArray ();
861 bool[] has_pair = new bool[operators.Length];
863 for (int i = 0; i < operators.Length; ++i) {
864 if (operators[i] == null)
867 Operator o_a = (Operator) operators[i];
868 Operator.OpType o_type = o_a.OperatorType;
869 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
870 has_equality_or_inequality = true;
872 Operator.OpType matching_type = o_a.GetMatchingOperator ();
873 if (matching_type == Operator.OpType.TOP) {
878 for (int ii = 0; ii < operators.Length; ++ii) {
879 Operator o_b = (Operator) operators[ii];
880 if (o_b == null || o_b.OperatorType != matching_type)
883 if (!TypeManager.IsEqual (o_a.ReturnType, o_b.ReturnType))
886 if (!TypeManager.IsEqual (o_a.ParameterTypes, o_b.ParameterTypes))
892 // Used to ignore duplicate user conversions
898 for (int i = 0; i < operators.Length; ++i) {
899 if (operators[i] == null || has_pair[i])
902 Operator o = (Operator) operators [i];
903 Report.Error (216, o.Location,
904 "The operator `{0}' requires a matching operator `{1}' to also be defined",
905 o.GetSignatureForError (), Operator.GetName (o.GetMatchingOperator ()));
908 if (has_equality_or_inequality) {
909 if (Methods == null || !HasEquals)
910 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
911 GetSignatureForError ());
913 if (Methods == null || !HasGetHashCode)
914 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
915 GetSignatureForError ());
919 bool CheckGenericInterfaces (Type[] ifaces)
921 var already_checked = new List<Type> ();
923 for (int i = 0; i < ifaces.Length; i++) {
924 Type iface = ifaces [i];
925 foreach (Type t in already_checked) {
929 Type[] inferred = new Type [CountTypeParameters];
930 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t, inferred, null))
933 Report.Error (695, Location,
934 "`{0}' cannot implement both `{1}' and `{2}' " +
935 "because they may unify for some type parameter substitutions",
936 TypeManager.CSharpName (TypeBuilder), TypeManager.CSharpName (iface),
937 TypeManager.CSharpName (t));
941 already_checked.Add (iface);
949 bool CreateTypeBuilder ()
952 Type default_parent = null;
953 if (Kind == Kind.Struct)
954 default_parent = TypeManager.value_type;
955 else if (Kind == Kind.Enum)
956 default_parent = TypeManager.enum_type;
957 else if (Kind == Kind.Delegate)
958 default_parent = TypeManager.multicast_delegate_type;
961 // Sets .size to 1 for structs with no instance fields
963 int type_size = Kind == Kind.Struct && first_nonstatic_field == null ? 1 : 0;
966 if (GlobalRootNamespace.Instance.IsNamespace (Name)) {
967 Report.Error (519, Location, "`{0}' clashes with a predefined namespace", Name);
971 ModuleBuilder builder = Module.Compiled.Builder;
972 TypeBuilder = builder.DefineType (
973 Name, TypeAttr, default_parent, type_size);
975 TypeBuilder builder = Parent.TypeBuilder;
977 TypeBuilder = builder.DefineNestedType (
978 Basename, TypeAttr, default_parent, type_size);
980 } catch (ArgumentException) {
981 Report.RuntimeMissingSupport (Location, "static classes");
985 TypeManager.AddUserType (this);
988 string[] param_names = new string [TypeParameters.Length];
989 for (int i = 0; i < TypeParameters.Length; i++)
990 param_names [i] = TypeParameters [i].Name;
992 GenericTypeParameterBuilder[] gen_params = TypeBuilder.DefineGenericParameters (param_names);
994 int offset = CountTypeParameters;
995 if (CurrentTypeParameters != null)
996 offset -= CurrentTypeParameters.Length;
999 nested_gen_params = new GenericTypeParameterBuilder [offset];
1000 Array.Copy (gen_params, nested_gen_params, offset);
1003 for (int i = offset; i < gen_params.Length; i++)
1004 CurrentTypeParameters [i - offset].Define (gen_params [i]);
1010 bool DefineBaseTypes ()
1012 iface_exprs = ResolveBaseTypes (out base_type);
1013 if (partial_parts != null) {
1014 iface_exprs = GetNormalPartialBases (ref base_type);
1018 // GetClassBases calls ResolveBaseTypeExpr() on the various type expressions involved,
1019 // which in turn should have called DefineType()s on base types if necessary.
1021 // None of the code below should trigger DefineType()s on classes that we depend on.
1022 // Thus, we are eligible to be on the topological sort `type_container_resolve_order'.
1024 // Let's do it as soon as possible, since code below can call DefineType() on classes
1025 // that depend on us to be populated before they are.
1027 if (!(this is CompilerGeneratedClass) && !(this is Delegate))
1028 RootContext.RegisterOrder (this);
1030 if (!CheckRecursiveDefinition (this))
1033 if (base_type != null && base_type.Type != null) {
1034 TypeBuilder.SetParent (base_type.Type);
1037 // add interfaces that were not added at type creation
1038 if (iface_exprs != null) {
1039 ifaces = TypeManager.ExpandInterfaces (iface_exprs);
1043 foreach (Type itype in ifaces)
1044 TypeBuilder.AddInterfaceImplementation (itype);
1046 if (!CheckGenericInterfaces (ifaces))
1049 TypeManager.RegisterBuilder (TypeBuilder, ifaces);
1056 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1058 public TypeBuilder CreateType ()
1060 if (TypeBuilder != null)
1066 if (!CreateTypeBuilder ()) {
1071 if (partial_parts != null) {
1072 foreach (TypeContainer part in partial_parts)
1073 part.TypeBuilder = TypeBuilder;
1076 if (Types != null) {
1077 foreach (TypeContainer tc in Types) {
1078 if (tc.CreateType () == null) {
1090 public override TypeBuilder DefineType ()
1097 type_defined = true;
1099 if (CreateType () == null) {
1104 if (!DefineBaseTypes ()) {
1109 if (!DefineNestedTypes ()) {
1117 public override void SetParameterInfo (List<Constraints> constraints_list)
1119 base.SetParameterInfo (constraints_list);
1121 if (!is_generic || PartialContainer == this)
1124 TypeParameter[] tc_names = PartialContainer.TypeParameters;
1125 for (int i = 0; i < tc_names.Length; ++i) {
1126 if (tc_names [i].Name != type_params [i].Name) {
1127 Report.SymbolRelatedToPreviousError (PartialContainer.Location, "");
1128 Report.Error (264, Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
1129 GetSignatureForError ());
1133 if (tc_names [i].Variance != type_params [i].Variance) {
1134 Report.SymbolRelatedToPreviousError (PartialContainer.Location, "");
1135 Report.Error (1067, Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers",
1136 GetSignatureForError ());
1142 void UpdateTypeParameterConstraints (TypeContainer part)
1144 TypeParameter[] current_params = type_params;
1145 for (int i = 0; i < current_params.Length; i++) {
1146 Constraints c = part.type_params [i].Constraints;
1150 if (current_params [i].UpdateConstraints (part, c))
1153 Report.SymbolRelatedToPreviousError (Location, "");
1154 Report.Error (265, part.Location,
1155 "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'",
1156 GetSignatureForError (), current_params [i].GetSignatureForError ());
1160 public bool ResolveType ()
1162 if (!DoResolveType ())
1165 if (compiler_generated != null) {
1166 foreach (CompilerGeneratedClass c in compiler_generated)
1167 if (!c.ResolveType ())
1174 protected virtual bool DoResolveType ()
1179 if (PartialContainer != this)
1180 throw new InternalErrorException ();
1182 TypeExpr current_type = null;
1183 if (CurrentTypeParameters != null) {
1184 foreach (TypeParameter type_param in CurrentTypeParameters) {
1185 if (!type_param.Resolve (this)) {
1191 if (partial_parts != null) {
1192 foreach (TypeContainer part in partial_parts)
1193 UpdateTypeParameterConstraints (part);
1197 for (int i = 0; i < TypeParameters.Length; ++i) {
1199 // FIXME: Same should be done for delegates
1200 // TODO: Quite ugly way how to propagate constraints to
1203 if (nested_gen_params != null && i < nested_gen_params.Length) {
1204 TypeParameters [i].SetConstraints (nested_gen_params [i]);
1206 if (!TypeParameters [i].DefineType (this)) {
1213 // TODO: Very strange, why not simple make generic type from
1214 // current type parameters
1215 current_type = new GenericTypeExpr (this, Location);
1216 current_type = current_type.ResolveAsTypeTerminal (this, false);
1217 if (current_type == null) {
1222 currentType = current_type.Type;
1226 protected virtual bool DefineNestedTypes ()
1228 if (Types != null) {
1229 foreach (TypeContainer tc in Types)
1230 if (tc.DefineType () == null)
1234 if (Delegates != null) {
1235 foreach (Delegate d in Delegates)
1236 if (d.DefineType () == null)
1243 TypeContainer InTransit;
1245 protected bool CheckRecursiveDefinition (TypeContainer tc)
1247 if (InTransit != null) {
1248 Report.SymbolRelatedToPreviousError (this);
1249 if (this is Interface)
1251 529, tc.Location, "Inherited interface `{0}' causes a " +
1252 "cycle in the interface hierarchy of `{1}'",
1253 GetSignatureForError (), tc.GetSignatureForError ());
1256 146, tc.Location, "Circular base class dependency " +
1257 "involving `{0}' and `{1}'",
1258 tc.GetSignatureForError (), GetSignatureForError ());
1264 if (base_type != null && base_type.Type != null) {
1265 Type t = TypeManager.DropGenericTypeArguments (base_type.Type);
1266 TypeContainer ptc = TypeManager.LookupTypeContainer (t);
1267 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1271 if (iface_exprs != null) {
1272 foreach (TypeExpr iface in iface_exprs) {
1273 Type itype = TypeManager.DropGenericTypeArguments (iface.Type);
1274 TypeContainer ptc = TypeManager.LookupTypeContainer (itype);
1275 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1280 if (!IsTopLevel && !Parent.PartialContainer.CheckRecursiveDefinition (this))
1287 public override TypeParameter[] CurrentTypeParameters {
1289 return PartialContainer.type_params;
1294 /// Populates our TypeBuilder with fields and methods
1296 public sealed override bool Define ()
1298 if (members_defined)
1299 return members_defined_ok;
1301 members_defined_ok = DoDefineMembers ();
1302 members_defined = true;
1304 return members_defined_ok;
1307 protected virtual bool DoDefineMembers ()
1309 if (iface_exprs != null) {
1310 foreach (TypeExpr iface in iface_exprs) {
1311 ObsoleteAttribute oa = AttributeTester.GetObsoleteAttribute (iface.Type);
1312 if ((oa != null) && !IsObsolete)
1313 AttributeTester.Report_ObsoleteMessage (
1314 oa, iface.GetSignatureForError (), Location, Report);
1316 GenericTypeExpr ct = iface as GenericTypeExpr;
1318 // TODO: passing `this' is wrong, should be base type iface instead
1319 TypeManager.CheckTypeVariance (ct.Type, Variance.Covariant, this);
1321 if (!ct.CheckConstraints (this))
1324 if (ct.HasDynamicArguments ()) {
1325 Report.Error (1966, iface.Location,
1326 "`{0}': cannot implement a dynamic interface `{1}'",
1327 GetSignatureForError (), iface.GetSignatureForError ());
1334 if (base_type != null) {
1335 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (base_type.Type);
1336 if (obsolete_attr != null && !IsObsolete)
1337 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), Location, Report);
1339 GenericTypeExpr ct = base_type as GenericTypeExpr;
1340 if ((ct != null) && !ct.CheckConstraints (this))
1343 TypeContainer baseContainer = TypeManager.LookupTypeContainer(base_type.Type);
1344 if (baseContainer != null)
1345 baseContainer.Define();
1347 member_cache = new MemberCache (base_type.Type, this);
1348 } else if (Kind == Kind.Interface) {
1349 member_cache = new MemberCache (null, this);
1350 Type [] ifaces = TypeManager.GetInterfaces (TypeBuilder);
1351 for (int i = 0; i < ifaces.Length; ++i)
1352 member_cache.AddInterface (TypeManager.LookupMemberCache (ifaces [i]));
1354 member_cache = new MemberCache (null, this);
1358 foreach (TypeContainer tc in types)
1359 member_cache.AddNestedType (tc);
1361 if (delegates != null)
1362 foreach (Delegate d in delegates)
1363 member_cache.AddNestedType (d);
1365 if (partial_parts != null) {
1366 foreach (TypeContainer part in partial_parts)
1367 part.member_cache = member_cache;
1371 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Basename, false);
1372 if (conflict_symbol == null) {
1373 if ((ModFlags & Modifiers.NEW) != 0)
1374 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
1376 if ((ModFlags & Modifiers.NEW) == 0) {
1377 Report.SymbolRelatedToPreviousError (conflict_symbol);
1378 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
1379 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
1384 DefineContainerMembers (constants);
1385 DefineContainerMembers (fields);
1387 if (Kind == Kind.Struct || Kind == Kind.Class) {
1388 pending = PendingImplementation.GetPendingImplementations (this);
1390 if (requires_delayed_unmanagedtype_check) {
1391 requires_delayed_unmanagedtype_check = false;
1392 foreach (FieldBase f in fields) {
1393 if (f.MemberType != null && f.MemberType.IsPointer)
1394 TypeManager.VerifyUnmanaged (Compiler, f.MemberType, f.Location);
1400 // Constructors are not in the defined_names array
1402 DefineContainerMembers (instance_constructors);
1404 DefineContainerMembers (events);
1405 DefineContainerMembers (ordered_explicit_member_list);
1406 DefineContainerMembers (ordered_member_list);
1408 if (operators != null) {
1409 DefineContainerMembers (operators);
1410 CheckPairedOperators ();
1413 DefineContainerMembers (delegates);
1415 ComputeIndexerName();
1416 CheckEqualsAndGetHashCode();
1418 if (CurrentType != null) {
1419 GenericType = CurrentType;
1423 // FIXME: This hack is needed because member cache does not work
1424 // with generic types, we rely on runtime to inflate dynamic types.
1425 // TODO: This hack requires member cache refactoring to be removed
1427 if (TypeManager.IsGenericType (TypeBuilder))
1428 member_cache = new MemberCache (this);
1433 protected virtual void DefineContainerMembers (System.Collections.IList mcal) // IList<MemberCore>
1436 foreach (MemberCore mc in mcal) {
1439 } catch (Exception e) {
1440 throw new InternalErrorException (mc, e);
1446 protected virtual void ComputeIndexerName ()
1448 if (indexers == null)
1451 string class_indexer_name = null;
1454 // If there's both an explicit and an implicit interface implementation, the
1455 // explicit one actually implements the interface while the other one is just
1456 // a normal indexer. See bug #37714.
1459 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
1460 foreach (Indexer i in indexers) {
1461 if (i.InterfaceType != null) {
1462 if (seen_normal_indexers)
1463 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
1467 seen_normal_indexers = true;
1469 if (class_indexer_name == null) {
1470 class_indexer_name = i.ShortName;
1474 if (i.ShortName != class_indexer_name)
1475 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");
1478 if (class_indexer_name != null)
1479 indexer_name = class_indexer_name;
1482 protected virtual void EmitIndexerName ()
1484 if (!seen_normal_indexers)
1487 PredefinedAttribute pa = PredefinedAttributes.Get.DefaultMember;
1488 if (pa.Constructor == null &&
1489 !pa.ResolveConstructor (Location, TypeManager.string_type))
1492 CustomAttributeBuilder cb = new CustomAttributeBuilder (pa.Constructor, new string [] { IndexerName });
1493 TypeBuilder.SetCustomAttribute (cb);
1496 protected virtual void CheckEqualsAndGetHashCode ()
1498 if (methods == null)
1501 if (HasEquals && !HasGetHashCode) {
1502 Report.Warning (659, 3, this.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", this.GetSignatureForError ());
1506 public MemberInfo FindBaseMemberWithSameName (string name, bool ignore_methods)
1508 return BaseCache == null ? null : BaseCache.FindMemberWithSameName (name, ignore_methods, null);
1512 /// This function is based by a delegate to the FindMembers routine
1514 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1520 /// This filter is used by FindMembers, and we just keep
1521 /// a global for the filter to `AlwaysAccept'
1523 static MemberFilter accepting_filter;
1526 static TypeContainer ()
1528 accepting_filter = new MemberFilter (AlwaysAccept);
1531 public MethodInfo[] GetMethods ()
1533 var members = new List<MethodInfo> ();
1537 if (methods != null) {
1538 int len = methods.Count;
1539 for (int i = 0; i < len; i++) {
1540 Method m = (Method) methods [i];
1542 members.Add (m.MethodBuilder);
1546 if (operators != null) {
1547 int len = operators.Count;
1548 for (int i = 0; i < len; i++) {
1549 Operator o = (Operator) operators [i];
1551 members.Add (o.MethodBuilder);
1555 if (properties != null) {
1556 int len = properties.Count;
1557 for (int i = 0; i < len; i++) {
1558 Property p = (Property) properties [i];
1560 if (p.GetBuilder != null)
1561 members.Add (p.GetBuilder);
1562 if (p.SetBuilder != null)
1563 members.Add (p.SetBuilder);
1567 if (indexers != null) {
1568 int len = indexers.Count;
1569 for (int i = 0; i < len; i++) {
1570 Indexer ix = (Indexer) indexers [i];
1572 if (ix.GetBuilder != null)
1573 members.Add (ix.GetBuilder);
1574 if (ix.SetBuilder != null)
1575 members.Add (ix.SetBuilder);
1579 if (events != null) {
1580 int len = events.Count;
1581 for (int i = 0; i < len; i++) {
1582 Event e = (Event) events [i];
1584 if (e.AddBuilder != null)
1585 members.Add (e.AddBuilder);
1586 if (e.RemoveBuilder != null)
1587 members.Add (e.RemoveBuilder);
1591 return members.ToArray ();
1594 // Indicated whether container has StructLayout attribute set Explicit
1595 public bool HasExplicitLayout {
1596 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
1597 set { caching_flags |= Flags.HasExplicitLayout; }
1600 public bool HasStructLayout {
1601 get { return (caching_flags & Flags.HasStructLayout) != 0; }
1602 set { caching_flags |= Flags.HasStructLayout; }
1606 // Return the nested type with name @name. Ensures that the nested type
1607 // is defined if necessary. Do _not_ use this when you have a MemberCache handy.
1609 public Type FindNestedType (string name)
1611 if (PartialContainer != this)
1612 throw new InternalErrorException ("should not happen");
1614 var lists = new[] { types, delegates };
1616 for (int j = 0; j < lists.Length; ++j) {
1617 var list = lists [j];
1621 int len = list.Count;
1622 for (int i = 0; i < len; ++i) {
1624 if (ds.Basename == name) {
1625 return ds.DefineType ();
1633 private void FindMembers_NestedTypes (Modifiers modflags,
1634 BindingFlags bf, MemberFilter filter, object criteria,
1635 ref List<MemberInfo> members)
1637 var lists = new[] { types, delegates };
1639 for (int j = 0; j < lists.Length; ++j) {
1640 var list = lists [j];
1644 int len = list.Count;
1645 for (int i = 0; i < len; i++) {
1648 if ((ds.ModFlags & modflags) == 0)
1651 TypeBuilder tb = ds.TypeBuilder;
1653 if (!(criteria is string) || ds.Basename.Equals (criteria))
1654 tb = ds.DefineType ();
1657 if (tb != null && (filter (tb, criteria) == true)) {
1658 if (members == null)
1659 members = new List<MemberInfo> ();
1668 /// This method returns the members of this type just like Type.FindMembers would
1669 /// Only, we need to use this for types which are _being_ defined because MS'
1670 /// implementation can't take care of that.
1673 // FIXME: return an empty static array instead of null, that cleans up
1674 // some code and is consistent with some coding conventions I just found
1678 // Notice that in various cases we check if our field is non-null,
1679 // something that would normally mean that there was a bug elsewhere.
1681 // The problem happens while we are defining p-invoke methods, as those
1682 // will trigger a FindMembers, but this happens before things are defined
1684 // Since the whole process is a no-op, it is fine to check for null here.
1686 // TODO: This approach will be one day completely removed, it's already
1687 // used at few places only
1690 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1691 MemberFilter filter, object criteria)
1693 List<MemberInfo> members = null;
1695 Modifiers modflags = 0;
1696 if ((bf & BindingFlags.Public) != 0)
1697 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1699 if ((bf & BindingFlags.NonPublic) != 0)
1700 modflags |= Modifiers.PRIVATE;
1702 Modifiers static_mask = 0, static_flags = 0;
1703 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1704 case BindingFlags.Static:
1705 static_mask = static_flags = Modifiers.STATIC;
1708 case BindingFlags.Instance:
1709 static_mask = Modifiers.STATIC;
1714 static_mask = static_flags = 0;
1718 Timer.StartTimer (TimerType.TcFindMembers);
1721 filter = accepting_filter;
1723 if ((mt & MemberTypes.Field) != 0) {
1724 if (fields != null) {
1725 int len = fields.Count;
1726 for (int i = 0; i < len; i++) {
1727 FieldBase f = (FieldBase) fields [i];
1729 if ((f.ModFlags & modflags) == 0)
1731 if ((f.ModFlags & static_mask) != static_flags)
1734 FieldBuilder fb = f.FieldBuilder;
1735 if (fb != null && filter (fb, criteria) == true) {
1736 if (members == null)
1737 members = new List<MemberInfo> ();
1744 if (constants != null) {
1745 int len = constants.Count;
1746 for (int i = 0; i < len; i++) {
1747 Const con = (Const) constants [i];
1749 if ((con.ModFlags & modflags) == 0)
1751 if ((con.ModFlags & static_mask) != static_flags)
1754 FieldBuilder fb = con.FieldBuilder;
1756 // Define parent and not member, otherwise membercache can be null
1757 if (con.Parent.Define ())
1758 fb = con.FieldBuilder;
1760 if (fb != null && filter (fb, criteria) == true) {
1761 if (members == null)
1762 members = new List<MemberInfo> ();
1770 if ((mt & MemberTypes.Method) != 0) {
1771 if (methods != null) {
1772 int len = methods.Count;
1773 for (int i = 0; i < len; i++) {
1774 MethodOrOperator m = (MethodOrOperator) methods [i];
1776 if ((m.ModFlags & modflags) == 0)
1778 if ((m.ModFlags & static_mask) != static_flags)
1781 MethodBuilder mb = m.MethodBuilder;
1783 if (mb != null && filter (mb, criteria) == true) {
1784 if (members == null)
1785 members = new List<MemberInfo> ();
1792 if (operators != null) {
1793 int len = operators.Count;
1794 for (int i = 0; i < len; i++) {
1795 Operator o = (Operator) operators [i];
1797 if ((o.ModFlags & modflags) == 0)
1799 if ((o.ModFlags & static_mask) != static_flags)
1802 MethodBuilder ob = o.MethodBuilder;
1803 if (ob != null && filter (ob, criteria) == true) {
1804 if (members == null)
1805 members = new List<MemberInfo> ();
1812 if (events != null) {
1813 foreach (Event e in events) {
1814 if ((e.ModFlags & modflags) == 0)
1816 if ((e.ModFlags & static_mask) != static_flags)
1819 MethodBuilder b = e.AddBuilder;
1820 if (b != null && filter (b, criteria)) {
1821 if (members == null)
1822 members = new List<MemberInfo> ();
1827 b = e.RemoveBuilder;
1828 if (b != null && filter (b, criteria)) {
1829 if (members == null)
1830 members = new List<MemberInfo> ();
1837 if (properties != null) {
1838 int len = properties.Count;
1839 for (int i = 0; i < len; i++) {
1840 Property p = (Property) properties [i];
1842 if ((p.ModFlags & modflags) == 0)
1844 if ((p.ModFlags & static_mask) != static_flags)
1850 if (b != null && filter (b, criteria) == true) {
1851 if (members == null)
1852 members = new List<MemberInfo> ();
1858 if (b != null && filter (b, criteria) == true) {
1859 if (members == null)
1860 members = new List<MemberInfo> ();
1867 if (indexers != null) {
1868 int len = indexers.Count;
1869 for (int i = 0; i < len; i++) {
1870 Indexer ix = (Indexer) indexers [i];
1872 if ((ix.ModFlags & modflags) == 0)
1874 if ((ix.ModFlags & static_mask) != static_flags)
1880 if (b != null && filter (b, criteria) == true) {
1881 if (members == null)
1882 members = new List<MemberInfo> ();
1888 if (b != null && filter (b, criteria) == true) {
1889 if (members == null)
1890 members = new List<MemberInfo> ();
1898 if ((mt & MemberTypes.Event) != 0) {
1899 if (events != null) {
1900 int len = events.Count;
1901 for (int i = 0; i < len; i++) {
1902 Event e = (Event) events [i];
1904 if ((e.ModFlags & modflags) == 0)
1906 if ((e.ModFlags & static_mask) != static_flags)
1909 MemberInfo eb = e.EventBuilder;
1910 if (eb != null && filter (eb, criteria) == true) {
1911 if (members == null)
1912 members = new List<MemberInfo> ();
1914 members.Add (e.EventBuilder);
1920 if ((mt & MemberTypes.Property) != 0){
1921 if (properties != null) {
1922 int len = properties.Count;
1923 for (int i = 0; i < len; i++) {
1924 Property p = (Property) properties [i];
1926 if ((p.ModFlags & modflags) == 0)
1928 if ((p.ModFlags & static_mask) != static_flags)
1931 MemberInfo pb = p.PropertyBuilder;
1932 if (pb != null && filter (pb, criteria) == true) {
1933 if (members == null)
1934 members = new List<MemberInfo> ();
1936 members.Add (p.PropertyBuilder);
1941 if (indexers != null) {
1942 int len = indexers.Count;
1943 for (int i = 0; i < len; i++) {
1944 Indexer ix = (Indexer) indexers [i];
1946 if ((ix.ModFlags & modflags) == 0)
1948 if ((ix.ModFlags & static_mask) != static_flags)
1951 MemberInfo ib = ix.PropertyBuilder;
1952 if (ib != null && filter (ib, criteria) == true) {
1953 if (members == null)
1954 members = new List<MemberInfo> ();
1956 members.Add (ix.PropertyBuilder);
1962 if ((mt & MemberTypes.NestedType) != 0)
1963 FindMembers_NestedTypes (modflags, bf, filter, criteria, ref members);
1965 if ((mt & MemberTypes.Constructor) != 0){
1966 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1967 int len = instance_constructors.Count;
1968 for (int i = 0; i < len; i++) {
1969 Constructor c = (Constructor) instance_constructors [i];
1971 ConstructorBuilder cb = c.ConstructorBuilder;
1972 if (cb != null && filter (cb, criteria) == true) {
1973 if (members == null)
1974 members = new List<MemberInfo> ();
1981 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1982 ConstructorBuilder cb =
1983 default_static_constructor.ConstructorBuilder;
1985 if (cb != null && filter (cb, criteria) == true) {
1986 if (members == null)
1987 members = new List<MemberInfo> ();
1995 // Lookup members in base if requested.
1997 if ((bf & BindingFlags.DeclaredOnly) == 0) {
1998 if (TypeBuilder.BaseType != null) {
1999 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
2000 if (list.Count > 0) {
2001 if (members == null)
2002 members = new List<MemberInfo> ();
2004 members.AddRange (list);
2009 Timer.StopTimer (TimerType.TcFindMembers);
2011 if (members == null)
2012 return MemberList.Empty;
2014 return new MemberList (members);
2017 public override MemberCache MemberCache {
2019 return member_cache;
2023 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
2024 MemberFilter filter, object criteria)
2026 DeclSpace ds = TypeManager.LookupDeclSpace (t);
2029 return ds.FindMembers (mt, bf, filter, criteria);
2031 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
2035 /// Emits the values for the constants
2037 public void EmitConstants ()
2039 if (constants != null)
2040 foreach (Const con in constants)
2045 void CheckMemberUsage (List<MemberCore> al, string member_type)
2050 foreach (MemberCore mc in al) {
2051 if ((mc.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE)
2054 if (!mc.IsUsed && (mc.caching_flags & Flags.Excluded) == 0) {
2055 Report.Warning (169, 3, mc.Location, "The private {0} `{1}' is never used", member_type, mc.GetSignatureForError ());
2060 public virtual void VerifyMembers ()
2063 // Check for internal or private fields that were never assigned
2065 if (Report.WarningLevel >= 3) {
2066 CheckMemberUsage (properties, "property");
2067 CheckMemberUsage (methods, "method");
2068 CheckMemberUsage (constants, "constant");
2070 if (fields != null){
2071 bool is_type_exposed = Kind == Kind.Struct || IsExposedFromAssembly ();
2072 foreach (FieldBase f in fields) {
2073 if ((f.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
2074 if (is_type_exposed)
2077 f.SetMemberIsUsed ();
2081 if ((f.caching_flags & Flags.IsAssigned) == 0)
2082 Report.Warning (169, 3, f.Location, "The private field `{0}' is never used", f.GetSignatureForError ());
2084 Report.Warning (414, 3, f.Location, "The private field `{0}' is assigned but its value is never used",
2085 f.GetSignatureForError ());
2091 // Only report 649 on level 4
2093 if (Report.WarningLevel < 4)
2096 if ((f.caching_flags & Flags.IsAssigned) != 0)
2100 // Don't be pendatic over serializable attributes
2102 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2105 Constant c = New.Constantify (f.MemberType);
2106 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value `{1}'",
2107 f.GetSignatureForError (), c == null ? "null" : c.AsString ());
2113 // TODO: move to ClassOrStruct
2114 void EmitConstructors ()
2116 if (instance_constructors == null)
2119 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && RootContext.VerifyClsCompliance && IsClsComplianceRequired ()) {
2120 bool has_compliant_args = false;
2122 foreach (Constructor c in instance_constructors) {
2126 catch (Exception e) {
2127 throw new InternalErrorException (c, e);
2130 if (has_compliant_args)
2133 has_compliant_args = c.HasCompliantArgs;
2135 if (!has_compliant_args)
2136 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2138 foreach (Constructor c in instance_constructors) {
2142 catch (Exception e) {
2143 throw new InternalErrorException (c, e);
2150 /// Emits the code, this step is performed after all
2151 /// the types, enumerations, constructors
2153 public virtual void EmitType ()
2155 if (OptAttributes != null)
2156 OptAttributes.Emit ();
2160 EmitConstructors ();
2162 // Can not continue if constants are broken
2164 if (Report.Errors > 0)
2167 if (default_static_constructor != null)
2168 default_static_constructor.Emit ();
2170 if (operators != null)
2171 foreach (Operator o in operators)
2174 if (properties != null)
2175 foreach (Property p in properties)
2178 if (indexers != null) {
2179 foreach (Indexer indx in indexers)
2184 if (events != null){
2185 foreach (Event e in Events)
2189 if (methods != null) {
2190 for (int i = 0; i < methods.Count; ++i)
2191 ((MethodOrOperator) methods [i]).Emit ();
2195 foreach (FieldBase f in fields)
2198 if (delegates != null) {
2199 foreach (Delegate d in Delegates) {
2204 if (pending != null)
2205 pending.VerifyPendingMethods (Report);
2207 if (Report.Errors > 0)
2210 if (compiler_generated != null) {
2211 for (int i = 0; i < compiler_generated.Count; ++i)
2212 ((CompilerGeneratedClass) compiler_generated [i]).EmitType ();
2216 public override void CloseType ()
2218 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2222 caching_flags |= Flags.CloseTypeCreated;
2223 TypeBuilder.CreateType ();
2224 } catch (TypeLoadException){
2226 // This is fine, the code still created the type
2228 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
2229 // Console.WriteLine (e.Message);
2230 } catch (Exception e) {
2231 throw new InternalErrorException (this, e);
2235 foreach (TypeContainer tc in Types)
2236 if (tc.Kind == Kind.Struct)
2239 foreach (TypeContainer tc in Types)
2240 if (tc.Kind != Kind.Struct)
2244 if (Delegates != null)
2245 foreach (Delegate d in Delegates)
2248 if (compiler_generated != null)
2249 foreach (CompilerGeneratedClass c in compiler_generated)
2252 PartialContainer = null;
2254 // properties = null;
2257 initialized_fields = null;
2258 initialized_static_fields = null;
2260 ordered_explicit_member_list = null;
2261 ordered_member_list = null;
2266 compiler_generated = null;
2267 default_constructor = null;
2268 default_static_constructor = null;
2270 OptAttributes = null;
2273 member_cache = null;
2277 // Performs the validation on a Method's modifiers (properties have
2278 // the same properties).
2280 public bool MethodModifiersValid (MemberCore mc)
2282 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2283 const Modifiers va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2284 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2286 var flags = mc.ModFlags;
2289 // At most one of static, virtual or override
2291 if ((flags & Modifiers.STATIC) != 0){
2292 if ((flags & vao) != 0){
2293 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2294 mc.GetSignatureForError ());
2299 if (Kind == Kind.Struct){
2300 if ((flags & va) != 0){
2301 ModifiersExtensions.Error_InvalidModifier (mc.Location, "virtual or abstract", Report);
2306 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2307 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2308 mc.GetSignatureForError ());
2313 // If the declaration includes the abstract modifier, then the
2314 // declaration does not include static, virtual or extern
2316 if ((flags & Modifiers.ABSTRACT) != 0){
2317 if ((flags & Modifiers.EXTERN) != 0){
2319 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2323 if ((flags & Modifiers.SEALED) != 0) {
2324 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2328 if ((flags & Modifiers.VIRTUAL) != 0){
2329 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2333 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2334 Report.SymbolRelatedToPreviousError (this);
2335 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2336 mc.GetSignatureForError (), GetSignatureForError ());
2341 if ((flags & Modifiers.PRIVATE) != 0){
2342 if ((flags & vao) != 0){
2343 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2348 if ((flags & Modifiers.SEALED) != 0){
2349 if ((flags & Modifiers.OVERRIDE) == 0){
2350 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2358 public Constructor DefaultStaticConstructor {
2359 get { return default_static_constructor; }
2362 protected override bool VerifyClsCompliance ()
2364 if (!base.VerifyClsCompliance ())
2369 Type base_type = TypeBuilder.BaseType;
2370 if (base_type != null && !AttributeTester.IsClsCompliant (base_type)) {
2371 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (base_type));
2378 /// Checks whether container name is CLS Compliant
2380 void VerifyClsName ()
2382 Dictionary<string, object> base_members = base_cache == null ?
2383 new Dictionary<string, object> () :
2384 base_cache.GetPublicMembers ();
2385 var this_members = new Dictionary<string, object> ();
2387 foreach (var entry in defined_names) {
2388 MemberCore mc = entry.Value;
2389 if (!mc.IsClsComplianceRequired ())
2392 string name = entry.Key;
2393 string basename = name.Substring (name.LastIndexOf ('.') + 1);
2395 string lcase = basename.ToLower (System.Globalization.CultureInfo.InvariantCulture);
2397 if (!base_members.TryGetValue (lcase, out found)) {
2398 if (!this_members.TryGetValue (lcase, out found)) {
2399 this_members.Add (lcase, mc);
2404 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
2407 if (found is MemberInfo) {
2408 if (basename == ((MemberInfo) found).Name)
2410 Report.SymbolRelatedToPreviousError ((MemberInfo) found);
2412 Report.SymbolRelatedToPreviousError ((MemberCore) found);
2415 Report.Warning (3005, 1, mc.Location, "Identifier `{0}' differing only in case is not CLS-compliant", mc.GetSignatureForError ());
2421 /// Performs checks for an explicit interface implementation. First it
2422 /// checks whether the `interface_type' is a base inteface implementation.
2423 /// Then it checks whether `name' exists in the interface type.
2425 public bool VerifyImplements (InterfaceMemberBase mb)
2427 if (ifaces != null) {
2428 foreach (Type t in ifaces){
2429 if (TypeManager.IsEqual (t, mb.InterfaceType))
2434 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2435 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2436 mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType));
2440 public override Type LookupAnyGeneric (string typeName)
2442 if (types != null) {
2443 foreach (TypeContainer tc in types) {
2447 int pos = tc.Basename.LastIndexOf ('`');
2448 if (pos == typeName.Length && String.Compare (typeName, 0, tc.Basename, 0, pos) == 0)
2449 return tc.TypeBuilder;
2453 return base.LookupAnyGeneric (typeName);
2456 public void Mark_HasEquals ()
2458 cached_method |= CachedMethods.Equals;
2461 public void Mark_HasGetHashCode ()
2463 cached_method |= CachedMethods.GetHashCode;
2467 /// Method container contains Equals method
2469 public bool HasEquals {
2471 return (cached_method & CachedMethods.Equals) != 0;
2476 /// Method container contains GetHashCode method
2478 public bool HasGetHashCode {
2480 return (cached_method & CachedMethods.GetHashCode) != 0;
2484 public bool HasStaticFieldInitializer {
2486 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2490 cached_method |= CachedMethods.HasStaticFieldInitializer;
2492 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2500 string IMemberContainer.Name {
2506 Type IMemberContainer.Type {
2512 bool IMemberContainer.IsInterface {
2514 return Kind == Kind.Interface;
2518 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2520 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2522 if (GenericType != null)
2523 return TypeManager.FindMembers (GenericType, mt, new_bf,
2526 return FindMembers (mt, new_bf, null, null);
2530 // Generates xml doc comments (if any), and if required,
2531 // handle warning report.
2533 internal override void GenerateDocComment (DeclSpace ds)
2535 DocUtil.GenerateTypeDocComment (this, ds, Report);
2538 public override string DocCommentHeader {
2539 get { return "T:"; }
2542 public MemberCache BaseCache {
2544 if (base_cache != null)
2546 if (TypeBuilder.BaseType != null)
2547 base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
2548 if (TypeBuilder.IsInterface)
2549 base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
2555 public abstract class ClassOrStruct : TypeContainer
2557 Dictionary<SecurityAction, PermissionSet> declarative_security;
2559 public ClassOrStruct (NamespaceEntry ns, DeclSpace parent,
2560 MemberName name, Attributes attrs, Kind kind)
2561 : base (ns, parent, name, attrs, kind)
2565 protected override bool AddToContainer (MemberCore symbol, string name)
2567 if (name == MemberName.Name) {
2568 if (symbol is TypeParameter) {
2569 Report.Error (694, symbol.Location,
2570 "Type parameter `{0}' has same name as containing type, or method",
2571 symbol.GetSignatureForError ());
2575 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2576 if (imb == null || !imb.IsExplicitImpl) {
2577 Report.SymbolRelatedToPreviousError (this);
2578 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2579 symbol.GetSignatureForError ());
2584 return base.AddToContainer (symbol, name);
2587 public override void VerifyMembers ()
2589 base.VerifyMembers ();
2591 if ((events != null) && Report.WarningLevel >= 3) {
2592 foreach (Event e in events){
2593 // Note: The event can be assigned from same class only, so we can report
2594 // this warning for all accessibility modes
2595 if ((e.caching_flags & Flags.IsUsed) == 0)
2596 Report.Warning (67, 3, e.Location, "The event `{0}' is never used", e.GetSignatureForError ());
2601 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2603 if (a.IsValidSecurityAttribute ()) {
2604 if (declarative_security == null)
2605 declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
2607 a.ExtractSecurityPermissionSet (declarative_security);
2611 if (a.Type == pa.StructLayout) {
2612 PartialContainer.HasStructLayout = true;
2614 if (a.GetLayoutKindValue () == LayoutKind.Explicit)
2615 PartialContainer.HasExplicitLayout = true;
2618 if (a.Type == pa.Dynamic) {
2619 a.Error_MisusedDynamicAttribute ();
2623 base.ApplyAttributeBuilder (a, cb, pa);
2627 /// Defines the default constructors
2629 protected void DefineDefaultConstructor (bool is_static)
2631 // The default instance constructor is public
2632 // If the class is abstract, the default constructor is protected
2633 // The default static constructor is private
2637 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2639 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2642 Constructor c = new Constructor (this, MemberName.Name, mods,
2643 null, ParametersCompiled.EmptyReadOnlyParameters,
2644 new GeneratedBaseInitializer (Location),
2648 c.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
2651 protected override bool DoDefineMembers ()
2653 CheckProtectedModifier ();
2655 base.DoDefineMembers ();
2657 if (default_static_constructor != null)
2658 default_static_constructor.Define ();
2663 public override void Emit ()
2665 if (default_static_constructor == null && PartialContainer.HasStaticFieldInitializer) {
2666 DefineDefaultConstructor (true);
2667 default_static_constructor.Define ();
2672 if (declarative_security != null) {
2673 foreach (var de in declarative_security) {
2674 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2679 public override ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
2681 DeclSpace top_level = Parent;
2682 if (top_level != null) {
2683 while (top_level.Parent != null)
2684 top_level = top_level.Parent;
2686 var candidates = NamespaceEntry.NS.LookupExtensionMethod (extensionType, this, name);
2687 if (candidates != null)
2688 return new ExtensionMethodGroupExpr (candidates, NamespaceEntry, extensionType, loc);
2691 return NamespaceEntry.LookupExtensionMethod (extensionType, name, loc);
2694 protected override TypeAttributes TypeAttr {
2696 if (default_static_constructor == null)
2697 return base.TypeAttr | TypeAttributes.BeforeFieldInit;
2699 return base.TypeAttr;
2705 // TODO: should be sealed
2706 public class Class : ClassOrStruct {
2707 const Modifiers AllowedModifiers =
2710 Modifiers.PROTECTED |
2711 Modifiers.INTERNAL |
2713 Modifiers.ABSTRACT |
2718 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2720 public Class (NamespaceEntry ns, DeclSpace parent, MemberName name, Modifiers mod,
2722 : base (ns, parent, name, attrs, Kind.Class)
2724 var accmods = Parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2725 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2727 if (IsStatic && RootContext.Version == LanguageVersion.ISO_1) {
2728 Report.FeatureIsNotAvailable (Location, "static classes");
2732 public override void AddBasesForPart (DeclSpace part, List<FullNamedExpression> bases)
2734 if (part.Name == "System.Object")
2735 Report.Error (537, part.Location,
2736 "The class System.Object cannot have a base class or implement an interface.");
2737 base.AddBasesForPart (part, bases);
2740 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2742 if (a.Type == pa.AttributeUsage) {
2743 if (!TypeManager.IsAttributeType (BaseType) &&
2744 TypeBuilder.FullName != "System.Attribute") {
2745 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2749 if (a.Type == pa.Conditional && !TypeManager.IsAttributeType (BaseType)) {
2750 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2754 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2755 a.Error_MissingGuidAttribute ();
2759 if (a.Type == pa.Extension) {
2760 a.Error_MisusedExtensionAttribute ();
2764 if (AttributeTester.IsAttributeExcluded (a.Type, Location))
2767 base.ApplyAttributeBuilder (a, cb, pa);
2770 public override AttributeTargets AttributeTargets {
2772 return AttributeTargets.Class;
2776 protected override void DefineContainerMembers (System.Collections.IList list)
2782 base.DefineContainerMembers (list);
2786 foreach (MemberCore m in list) {
2787 if (m is Operator) {
2788 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2792 if (m is Destructor) {
2793 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2798 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2802 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is Enum || m is Delegate)
2805 if (m is Constructor) {
2806 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2810 Method method = m as Method;
2811 if (method != null && method.Parameters.HasExtensionMethodType) {
2812 Report.Error (1105, m.Location, "`{0}': Extension methods must be declared static", m.GetSignatureForError ());
2816 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2819 base.DefineContainerMembers (list);
2822 protected override bool DoDefineMembers ()
2824 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2825 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2828 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2829 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2832 if (InstanceConstructors == null && !IsStatic)
2833 DefineDefaultConstructor (false);
2835 return base.DoDefineMembers ();
2838 public override void Emit ()
2842 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2843 PredefinedAttributes.Get.Extension.EmitAttribute (TypeBuilder);
2846 protected override TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
2848 TypeExpr[] ifaces = base.ResolveBaseTypes (out base_class);
2850 if (base_class == null) {
2851 if (RootContext.StdLib)
2852 base_class = TypeManager.system_object_expr;
2853 else if (Name != "System.Object")
2854 base_class = TypeManager.system_object_expr;
2856 if (Kind == Kind.Class && TypeManager.IsGenericParameter (base_class.Type)){
2858 689, base_class.Location,
2859 "Cannot derive from `{0}' because it is a type parameter",
2860 base_class.GetSignatureForError ());
2864 if (IsGeneric && TypeManager.IsAttributeType (base_class.Type)) {
2865 Report.Error (698, base_class.Location,
2866 "A generic type cannot derive from `{0}' because it is an attribute class",
2867 base_class.GetSignatureForError ());
2870 if (base_class.IsSealed){
2871 Report.SymbolRelatedToPreviousError (base_class.Type);
2872 if (base_class.Type.IsAbstract) {
2873 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2874 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
2876 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2877 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
2882 if (!base_class.CanInheritFrom ()){
2883 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2884 GetSignatureForError (), base_class.GetSignatureForError ());
2888 if (!IsAccessibleAs (base_class.Type)) {
2889 Report.SymbolRelatedToPreviousError (base_class.Type);
2890 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2891 TypeManager.CSharpName (base_class.Type), GetSignatureForError ());
2895 if (PartialContainer.IsStaticClass) {
2896 if (base_class.Type != TypeManager.object_type) {
2897 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2898 GetSignatureForError (), base_class.GetSignatureForError ());
2902 if (ifaces != null) {
2903 foreach (TypeExpr t in ifaces)
2904 Report.SymbolRelatedToPreviousError (t.Type);
2905 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2912 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2913 /// Valid only for attribute classes.
2914 public bool IsExcluded ()
2916 if ((caching_flags & Flags.Excluded_Undetected) == 0)
2917 return (caching_flags & Flags.Excluded) != 0;
2919 caching_flags &= ~Flags.Excluded_Undetected;
2921 if (OptAttributes == null)
2924 Attribute[] attrs = OptAttributes.SearchMulti (PredefinedAttributes.Get.Conditional);
2928 foreach (Attribute a in attrs) {
2929 string condition = a.GetConditionalAttributeValue ();
2930 if (Location.CompilationUnit.IsConditionalDefined (condition))
2934 caching_flags |= Flags.Excluded;
2939 // FIXME: How do we deal with the user specifying a different
2942 protected override TypeAttributes TypeAttr {
2944 TypeAttributes ta = base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2946 ta |= StaticClassAttribute;
2952 public sealed class Struct : ClassOrStruct {
2954 bool is_unmanaged, has_unmanaged_check_done;
2957 // Modifiers allowed in a struct declaration
2959 const Modifiers AllowedModifiers =
2962 Modifiers.PROTECTED |
2963 Modifiers.INTERNAL |
2967 public Struct (NamespaceEntry ns, DeclSpace parent, MemberName name,
2968 Modifiers mod, Attributes attrs)
2969 : base (ns, parent, name, attrs, Kind.Struct)
2971 var accmods = parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2973 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2975 this.ModFlags |= Modifiers.SEALED;
2978 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2980 base.ApplyAttributeBuilder (a, cb, pa);
2983 // When struct constains fixed fixed and struct layout has explicitly
2984 // set CharSet, its value has to be propagated to compiler generated
2985 // fixed field types
2987 if (a.Type == pa.StructLayout && Fields != null && a.HasField ("CharSet")) {
2988 for (int i = 0; i < Fields.Count; ++i) {
2989 FixedField ff = Fields [i] as FixedField;
2991 ff.SetCharSet (TypeBuilder.Attributes);
2996 public override AttributeTargets AttributeTargets {
2998 return AttributeTargets.Struct;
3002 public override bool IsUnmanagedType ()
3007 if (requires_delayed_unmanagedtype_check)
3010 if (has_unmanaged_check_done)
3011 return is_unmanaged;
3013 has_unmanaged_check_done = true;
3015 foreach (FieldBase f in fields) {
3016 if ((f.ModFlags & Modifiers.STATIC) != 0)
3019 // It can happen when recursive unmanaged types are defined
3020 // struct S { S* s; }
3021 Type mt = f.MemberType;
3023 has_unmanaged_check_done = false;
3024 requires_delayed_unmanagedtype_check = true;
3028 // TODO: Remove when pointer types are under mcs control
3029 while (mt.IsPointer)
3030 mt = TypeManager.GetElementType (mt);
3031 if (TypeManager.IsEqual (mt, TypeBuilder))
3034 if (TypeManager.IsUnmanagedType (mt))
3040 is_unmanaged = true;
3044 protected override TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
3046 TypeExpr[] ifaces = base.ResolveBaseTypes (out base_class);
3048 // If we are compiling our runtime,
3049 // and we are defining ValueType, then our
3050 // base is `System.Object'.
3052 if (base_class == null) {
3053 if (!RootContext.StdLib && Name == "System.ValueType")
3054 base_class = TypeManager.system_object_expr;
3056 base_class = TypeManager.system_valuetype_expr;
3063 // FIXME: Allow the user to specify a different set of attributes
3064 // in some cases (Sealed for example is mandatory for a class,
3065 // but what SequentialLayout can be changed
3067 protected override TypeAttributes TypeAttr {
3069 const TypeAttributes DefaultTypeAttributes =
3070 TypeAttributes.SequentialLayout |
3071 TypeAttributes.Sealed;
3073 return base.TypeAttr | DefaultTypeAttributes;
3077 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
3079 if ((field.ModFlags & Modifiers.STATIC) == 0) {
3080 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
3081 field.GetSignatureForError ());
3084 base.RegisterFieldForInitialization (field, expression);
3092 public sealed class Interface : TypeContainer, IMemberContainer {
3095 /// Modifiers allowed in a class declaration
3097 public const Modifiers AllowedModifiers =
3100 Modifiers.PROTECTED |
3101 Modifiers.INTERNAL |
3105 public Interface (NamespaceEntry ns, DeclSpace parent, MemberName name, Modifiers mod,
3107 : base (ns, parent, name, attrs, Kind.Interface)
3109 var accmods = parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3111 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
3114 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
3116 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3117 a.Error_MissingGuidAttribute ();
3121 base.ApplyAttributeBuilder (a, cb, pa);
3125 public override AttributeTargets AttributeTargets {
3127 return AttributeTargets.Interface;
3131 protected override TypeAttributes TypeAttr {
3133 const TypeAttributes DefaultTypeAttributes =
3134 TypeAttributes.AutoLayout |
3135 TypeAttributes.Abstract |
3136 TypeAttributes.Interface;
3138 return base.TypeAttr | DefaultTypeAttributes;
3142 protected override bool VerifyClsCompliance ()
3144 if (!base.VerifyClsCompliance ())
3147 if (ifaces != null) {
3148 foreach (Type t in ifaces) {
3149 if (AttributeTester.IsClsCompliant (t))
3152 Report.SymbolRelatedToPreviousError (t);
3153 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3154 GetSignatureForError (), TypeManager.CSharpName (t));
3162 // It is used as a base class for all property based members
3163 // This includes properties, indexers, and events
3164 public abstract class PropertyBasedMember : InterfaceMemberBase
3166 public PropertyBasedMember (DeclSpace parent, GenericMethod generic,
3167 FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
3168 MemberName name, Attributes attrs)
3169 : base (parent, generic, type, mod, allowed_mod, name, attrs)
3173 protected override bool VerifyClsCompliance ()
3175 if (!base.VerifyClsCompliance ())
3178 if (!AttributeTester.IsClsCompliant (MemberType)) {
3179 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
3180 GetSignatureForError ());
3188 public abstract class MethodCore : InterfaceMemberBase
3190 public readonly ParametersCompiled Parameters;
3191 protected ToplevelBlock block;
3193 public MethodCore (DeclSpace parent, GenericMethod generic,
3194 FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
3195 MemberName name, Attributes attrs, ParametersCompiled parameters)
3196 : base (parent, generic, type, mod, allowed_mod, name, attrs)
3198 Parameters = parameters;
3202 // Returns the System.Type array for the parameters of this method
3204 public Type [] ParameterTypes {
3206 return Parameters.Types;
3210 public ParametersCompiled ParameterInfo {
3216 public ToplevelBlock Block {
3226 public CallingConventions CallingConventions {
3228 CallingConventions cc = Parameters.CallingConvention;
3230 if ((ModFlags & Modifiers.STATIC) == 0)
3231 cc |= CallingConventions.HasThis;
3233 // FIXME: How is `ExplicitThis' used in C#?
3239 protected override bool CheckBase ()
3241 // Check whether arguments were correct.
3242 if (!DefineParameters (Parameters))
3245 return base.CheckBase ();
3249 // Returns a string that represents the signature for this
3250 // member which should be used in XML documentation.
3252 public override string GetDocCommentName (DeclSpace ds)
3254 return DocUtil.GetMethodDocCommentName (this, Parameters, ds);
3258 // Raised (and passed an XmlElement that contains the comment)
3259 // when GenerateDocComment is writing documentation expectedly.
3261 // FIXME: with a few effort, it could be done with XmlReader,
3262 // that means removal of DOM use.
3264 internal override void OnGenerateDocComment (XmlElement el)
3266 DocUtil.OnMethodGenerateDocComment (this, el, Report);
3270 // Represents header string for documentation comment.
3272 public override string DocCommentHeader
3274 get { return "M:"; }
3277 public override bool EnableOverloadChecks (MemberCore overload)
3279 if (overload is MethodCore || overload is AbstractPropertyEventMethod) {
3280 caching_flags |= Flags.MethodOverloadsExist;
3284 return base.EnableOverloadChecks (overload);
3287 protected override bool VerifyClsCompliance ()
3289 if (!base.VerifyClsCompliance ())
3292 if (Parameters.HasArglist) {
3293 Report.Warning (3000, 1, Location, "Methods with variable arguments are not CLS-compliant");
3296 if (!AttributeTester.IsClsCompliant (MemberType)) {
3297 Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant",
3298 GetSignatureForError ());
3301 Parameters.VerifyClsCompliance (this);
3307 public abstract class InterfaceMemberBase : MemberBase {
3309 // Whether this is an interface member.
3311 public bool IsInterface;
3314 // If true, this is an explicit interface implementation
3316 public bool IsExplicitImpl;
3318 protected bool is_external_implementation;
3321 // The interface type we are explicitly implementing
3323 public Type InterfaceType;
3326 // The method we're overriding if this is an override method.
3328 protected MethodInfo base_method;
3330 readonly Modifiers explicit_mod_flags;
3331 public MethodAttributes flags;
3333 public InterfaceMemberBase (DeclSpace parent, GenericMethod generic,
3334 FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
3335 MemberName name, Attributes attrs)
3336 : base (parent, generic, type, mod, allowed_mod, Modifiers.PRIVATE,
3339 IsInterface = parent.PartialContainer.Kind == Kind.Interface;
3340 IsExplicitImpl = (MemberName.Left != null);
3341 explicit_mod_flags = mod;
3344 protected override bool CheckBase ()
3346 if (!base.CheckBase ())
3349 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3350 CheckForDuplications ();
3355 // Is null for System.Object while compiling corlib and base interfaces
3356 if (Parent.PartialContainer.BaseCache == null) {
3357 if ((ModFlags & Modifiers.NEW) != 0) {
3358 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3363 Type base_ret_type = null;
3364 base_method = FindOutBaseMethod (ref base_ret_type);
3366 // method is override
3367 if (base_method != null) {
3368 if (!CheckMethodAgainstBase (base_ret_type))
3371 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3372 ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (base_method);
3374 if (OptAttributes == null || !OptAttributes.Contains (PredefinedAttributes.Get.Obsolete)) {
3375 Report.SymbolRelatedToPreviousError (base_method);
3376 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3377 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3380 if (OptAttributes != null && OptAttributes.Contains (PredefinedAttributes.Get.Obsolete)) {
3381 Report.SymbolRelatedToPreviousError (base_method);
3382 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3383 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3390 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Name, !((this is Event) || (this is Property)));
3391 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3392 if (conflict_symbol != null) {
3393 Report.SymbolRelatedToPreviousError (conflict_symbol);
3395 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3396 else if (this is PropertyBase)
3397 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3399 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3401 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3402 GetSignatureForError (), SimpleName.GetMemberType (this));
3407 if (conflict_symbol == null) {
3408 if ((ModFlags & Modifiers.NEW) != 0) {
3409 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3414 if ((ModFlags & Modifiers.NEW) == 0) {
3415 if (this is MethodOrOperator && conflict_symbol.MemberType == MemberTypes.Method)
3418 Report.SymbolRelatedToPreviousError (conflict_symbol);
3419 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3420 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3426 protected virtual bool CheckForDuplications ()
3428 return Parent.MemberCache.CheckExistingMembersOverloads (
3429 this, GetFullName (MemberName), ParametersCompiled.EmptyReadOnlyParameters, Report);
3433 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3434 // that have been defined.
3436 // `name' is the user visible name for reporting errors (this is used to
3437 // provide the right name regarding method names and properties)
3439 bool CheckMethodAgainstBase (Type base_method_type)
3443 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3444 if (!(base_method.IsAbstract || base_method.IsVirtual)){
3445 Report.SymbolRelatedToPreviousError (base_method);
3446 Report.Error (506, Location,
3447 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3448 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3452 // Now we check that the overriden method is not final
3454 if (base_method.IsFinal) {
3455 Report.SymbolRelatedToPreviousError (base_method);
3456 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3457 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3461 // Check that the permissions are not being changed
3463 MethodAttributes thisp = flags & MethodAttributes.MemberAccessMask;
3464 MethodAttributes base_classp = base_method.Attributes & MethodAttributes.MemberAccessMask;
3466 if (!CheckAccessModifiers (thisp, base_classp, base_method)) {
3467 Error_CannotChangeAccessModifiers (Location, base_method, base_classp, null);
3471 if (!TypeManager.IsEqual (MemberType, TypeManager.TypeToCoreType (base_method_type))) {
3472 Report.SymbolRelatedToPreviousError (base_method);
3473 if (this is PropertyBasedMember) {
3474 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3475 GetSignatureForError (), TypeManager.CSharpName (base_method_type), TypeManager.CSharpSignature (base_method));
3478 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3479 GetSignatureForError (), TypeManager.CSharpName (base_method_type), TypeManager.CSharpSignature (base_method));
3485 if ((ModFlags & Modifiers.NEW) == 0) {
3486 if ((ModFlags & Modifiers.OVERRIDE) == 0) {
3487 ModFlags |= Modifiers.NEW;
3488 Report.SymbolRelatedToPreviousError (base_method);
3489 if (!IsInterface && (base_method.IsVirtual || base_method.IsAbstract)) {
3490 Report.Warning (114, 2, Location, "`{0}' hides inherited member `{1}'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword",
3491 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3492 if (base_method.IsAbstract){
3493 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3494 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3498 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3499 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3503 if (base_method.IsAbstract && !IsInterface) {
3504 Report.SymbolRelatedToPreviousError (base_method);
3505 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3506 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3514 protected bool CheckAccessModifiers (MethodAttributes thisp, MethodAttributes base_classp, MethodInfo base_method)
3516 if ((base_classp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3518 // when overriding protected internal, the method can be declared
3519 // protected internal only within the same assembly or assembly
3520 // which has InternalsVisibleTo
3522 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3523 return TypeManager.IsThisOrFriendAssembly (Parent.Module.Assembly, base_method.DeclaringType.Assembly);
3524 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3526 // if it's not "protected internal", it must be "protected"
3530 } else if (Parent.TypeBuilder.Assembly == base_method.DeclaringType.Assembly) {
3532 // protected within the same assembly - an error
3535 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3536 (base_classp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3538 // protected ok, but other attributes differ - report an error
3544 return (thisp == base_classp);
3548 public override bool Define ()
3551 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3552 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3554 flags = MethodAttributes.Public |
3555 MethodAttributes.Abstract |
3556 MethodAttributes.HideBySig |
3557 MethodAttributes.NewSlot |
3558 MethodAttributes.Virtual;
3560 Parent.PartialContainer.MethodModifiersValid (this);
3562 flags = ModifiersExtensions.MethodAttr (ModFlags);
3565 if (IsExplicitImpl) {
3566 TypeExpr iface_texpr = MemberName.Left.GetTypeExpression ().ResolveAsTypeTerminal (this, false);
3567 if (iface_texpr == null)
3570 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3571 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3572 GetSignatureForError ());
3575 InterfaceType = iface_texpr.Type;
3577 if (!InterfaceType.IsInterface) {
3578 Report.SymbolRelatedToPreviousError (InterfaceType);
3579 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3580 TypeManager.CSharpName (InterfaceType));
3582 Parent.PartialContainer.VerifyImplements (this);
3585 ModifiersExtensions.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location, Report);
3588 return base.Define ();
3591 protected bool DefineParameters (ParametersCompiled parameters)
3593 if (!parameters.Resolve (this))
3597 for (int i = 0; i < parameters.Count; ++i) {
3598 Parameter p = parameters [i];
3600 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3601 p.Warning_UselessOptionalParameter (Report);
3603 if (p.CheckAccessibility (this))
3606 Type t = parameters.Types [i];
3607 Report.SymbolRelatedToPreviousError (t);
3608 if (this is Indexer)
3609 Report.Error (55, Location,
3610 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3611 TypeManager.CSharpName (t), GetSignatureForError ());
3612 else if (this is Operator)
3613 Report.Error (57, Location,
3614 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3615 TypeManager.CSharpName (t), GetSignatureForError ());
3617 Report.Error (51, Location,
3618 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3619 TypeManager.CSharpName (t), GetSignatureForError ());
3625 public override void Emit()
3627 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3628 // We are more strict than csc and report this as an error because SRE does not allow emit that
3629 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation) {
3630 if (this is Constructor) {
3631 Report.Error (824, Location,
3632 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3634 Report.Error (626, Location,
3635 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3636 GetSignatureForError ());
3643 public override bool EnableOverloadChecks (MemberCore overload)
3646 // Two members can differ in their explicit interface
3647 // type parameter only
3649 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3650 if (imb != null && imb.IsExplicitImpl) {
3651 if (IsExplicitImpl) {
3652 caching_flags |= Flags.MethodOverloadsExist;
3657 return IsExplicitImpl;
3660 protected void Error_CannotChangeAccessModifiers (Location loc, MemberInfo base_method, MethodAttributes ma, string suffix)
3662 Report.SymbolRelatedToPreviousError (base_method);
3663 string base_name = TypeManager.GetFullNameSignature (base_method);
3664 string this_name = GetSignatureForError ();
3665 if (suffix != null) {
3666 base_name += suffix;
3667 this_name += suffix;
3670 Report.Error (507, loc, "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3671 this_name, ModifiersExtensions.GetDescription (ma), base_name);
3674 protected static string Error722 {
3676 return "`{0}': static types cannot be used as return types";
3681 /// Gets base method and its return type
3683 protected abstract MethodInfo FindOutBaseMethod (ref Type base_ret_type);
3686 // The "short" name of this property / indexer / event. This is the
3687 // name without the explicit interface.
3689 public string ShortName
3691 get { return MemberName.Name; }
3692 set { SetMemberName (new MemberName (MemberName.Left, value, Location)); }
3696 // Returns full metadata method name
3698 public string GetFullName (MemberName name)
3700 if (!IsExplicitImpl)
3704 // When dealing with explicit members a full interface type
3705 // name is added to member name to avoid possible name conflicts
3707 // We use CSharpName which gets us full name with benefit of
3708 // replacing predefined names which saves some space and name
3711 return TypeManager.CSharpName (InterfaceType) + "." + name.Name;
3714 protected override bool VerifyClsCompliance ()
3716 if (!base.VerifyClsCompliance ()) {
3717 if (IsInterface && HasClsCompliantAttribute && Parent.IsClsComplianceRequired ()) {
3718 Report.Warning (3010, 1, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
3721 if ((ModFlags & Modifiers.ABSTRACT) != 0 && Parent.TypeBuilder.IsClass && IsExposedFromAssembly () && Parent.IsClsComplianceRequired ()) {
3722 Report.Warning (3011, 1, Location, "`{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
3727 if (GenericMethod != null)
3728 GenericMethod.VerifyClsCompliance ();
3733 public override bool IsUsed
3735 get { return IsExplicitImpl || base.IsUsed; }
3740 public abstract class MethodOrOperator : MethodCore, IMethodData
3742 public MethodBuilder MethodBuilder;
3743 ReturnParameter return_attributes;
3744 Dictionary<SecurityAction, PermissionSet> declarative_security;
3745 protected MethodData MethodData;
3747 static string[] attribute_targets = new string [] { "method", "return" };
3749 protected MethodOrOperator (DeclSpace parent, GenericMethod generic, FullNamedExpression type, Modifiers mod,
3750 Modifiers allowed_mod, MemberName name,
3751 Attributes attrs, ParametersCompiled parameters)
3752 : base (parent, generic, type, mod, allowed_mod, name,
3757 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
3759 if (a.Target == AttributeTargets.ReturnValue) {
3760 if (return_attributes == null)
3761 return_attributes = new ReturnParameter (this, MethodBuilder, Location);
3763 return_attributes.ApplyAttributeBuilder (a, cb, pa);
3767 if (a.IsInternalMethodImplAttribute) {
3768 is_external_implementation = true;
3771 if (a.Type == pa.DllImport) {
3772 const Modifiers extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3773 if ((ModFlags & extern_static) != extern_static) {
3774 Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
3776 is_external_implementation = true;
3779 if (a.IsValidSecurityAttribute ()) {
3780 if (declarative_security == null)
3781 declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
3782 a.ExtractSecurityPermissionSet (declarative_security);
3786 if (MethodBuilder != null)
3787 MethodBuilder.SetCustomAttribute (cb);
3790 public override AttributeTargets AttributeTargets {
3792 return AttributeTargets.Method;
3796 protected override bool CheckForDuplications ()
3798 string name = GetFullName (MemberName);
3799 if (MemberName.IsGeneric)
3800 name = MemberName.MakeName (name, MemberName.TypeArguments);
3802 return Parent.MemberCache.CheckExistingMembersOverloads (this, name, Parameters, Report);
3805 public virtual EmitContext CreateEmitContext (ILGenerator ig)
3807 return new EmitContext (
3808 this, ig, MemberType);
3811 protected override bool ResolveMemberType ()
3813 if (GenericMethod != null) {
3814 MethodBuilder = Parent.TypeBuilder.DefineMethod (GetFullName (MemberName), flags);
3815 if (!GenericMethod.Define (this))
3819 return base.ResolveMemberType ();
3822 public override bool Define ()
3824 if (!base.Define ())
3830 if (block != null && block.IsIterator && !(Parent is IteratorStorey)) {
3832 // Current method is turned into automatically generated
3833 // wrapper which creates an instance of iterator
3835 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
3836 ModFlags |= Modifiers.DEBUGGER_HIDDEN;
3839 if (IsPartialDefinition) {
3840 caching_flags &= ~Flags.Excluded_Undetected;
3841 caching_flags |= Flags.Excluded;
3843 // Add to member cache only when a partial method implementation has not been found yet
3844 if ((caching_flags & Flags.PartialDefinitionExists) == 0) {
3845 MethodBase mb = new PartialMethodDefinitionInfo (this);
3846 Parent.MemberCache.AddMember (mb, this);
3847 TypeManager.AddMethod (mb, this);
3853 MethodData = new MethodData (
3854 this, ModFlags, flags, this, MethodBuilder, GenericMethod, base_method);
3856 if (!MethodData.Define (Parent.PartialContainer, GetFullName (MemberName), Report))
3859 MethodBuilder = MethodData.MethodBuilder;
3861 if (TypeManager.IsGenericMethod (MethodBuilder))
3862 Parent.MemberCache.AddGenericMember (MethodBuilder, this);
3864 Parent.MemberCache.AddMember (MethodBuilder, this);
3869 protected override void DoMemberTypeIndependentChecks ()
3871 base.DoMemberTypeIndependentChecks ();
3873 CheckAbstractAndExtern (block != null);
3875 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3876 for (int i = 0; i < Parameters.Count; ++i) {
3877 IParameterData p = Parameters.FixedParameters [i];
3878 if (p.ModFlags == Parameter.Modifier.OUT) {
3879 Report.Error (752, Location, "`{0}': A partial method parameters cannot use `out' modifier",
3880 GetSignatureForError ());
3883 if (p.HasDefaultValue && IsPartialImplementation)
3884 ((Parameter) p).Warning_UselessOptionalParameter (Report);
3889 protected override void DoMemberTypeDependentChecks ()
3891 base.DoMemberTypeDependentChecks ();
3893 if (!TypeManager.IsGenericParameter (MemberType)) {
3894 if (MemberType.IsAbstract && MemberType.IsSealed) {
3895 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
3900 public override void Emit ()
3902 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
3903 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (MethodBuilder);
3904 if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
3905 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (MethodBuilder);
3907 if (TypeManager.IsDynamicType (ReturnType)) {
3908 return_attributes = new ReturnParameter (this, MethodBuilder, Location);
3909 PredefinedAttributes.Get.Dynamic.EmitAttribute (return_attributes.Builder);
3911 var trans_flags = TypeManager.HasDynamicTypeUsed (ReturnType);
3912 if (trans_flags != null) {
3913 var pa = PredefinedAttributes.Get.DynamicTransform;
3914 if (pa.Constructor != null || pa.ResolveConstructor (Location, TypeManager.bool_type.MakeArrayType ())) {
3915 return_attributes = new ReturnParameter (this, MethodBuilder, Location);
3916 return_attributes.Builder.SetCustomAttribute (
3917 new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
3922 if (OptAttributes != null)
3923 OptAttributes.Emit ();
3925 if (declarative_security != null) {
3926 foreach (var de in declarative_security) {
3927 MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value);
3931 if (MethodData != null)
3932 MethodData.Emit (Parent);
3940 protected void Error_ConditionalAttributeIsNotValid ()
3942 Report.Error (577, Location,
3943 "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
3944 GetSignatureForError ());
3947 public bool IsPartialDefinition {
3949 return (ModFlags & Modifiers.PARTIAL) != 0 && Block == null;
3953 public bool IsPartialImplementation {
3955 return (ModFlags & Modifiers.PARTIAL) != 0 && Block != null;
3959 public override string[] ValidAttributeTargets {
3961 return attribute_targets;
3965 #region IMethodData Members
3967 public Type ReturnType {
3973 public MemberName MethodName {
3980 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
3982 public bool IsExcluded () {
3983 if ((caching_flags & Flags.Excluded_Undetected) == 0)
3984 return (caching_flags & Flags.Excluded) != 0;
3986 caching_flags &= ~Flags.Excluded_Undetected;
3988 if (base_method == null) {
3989 if (OptAttributes == null)
3992 Attribute[] attrs = OptAttributes.SearchMulti (PredefinedAttributes.Get.Conditional);
3997 foreach (Attribute a in attrs) {
3998 string condition = a.GetConditionalAttributeValue ();
3999 if (condition == null)
4002 if (Location.CompilationUnit.IsConditionalDefined (condition))
4006 caching_flags |= Flags.Excluded;
4010 IMethodData md = TypeManager.GetMethod (TypeManager.DropGenericMethodArguments (base_method));
4012 if (AttributeTester.IsConditionalMethodExcluded (base_method, Location)) {
4013 caching_flags |= Flags.Excluded;
4019 if (md.IsExcluded ()) {
4020 caching_flags |= Flags.Excluded;
4026 GenericMethod IMethodData.GenericMethod {
4028 return GenericMethod;
4032 public virtual void EmitExtraSymbolInfo (SourceMethod source)
4039 public class SourceMethod : IMethodDef
4042 SourceMethodBuilder builder;
4044 protected SourceMethod (DeclSpace parent, MethodBase method, ICompileUnit file)
4046 this.method = method;
4048 builder = SymbolWriter.OpenMethod (file, parent.NamespaceEntry.SymbolFileID, this);
4051 public string Name {
4052 get { return method.Name; }
4057 if (method is MethodBuilder)
4058 return ((MethodBuilder) method).GetToken ().Token;
4059 else if (method is ConstructorBuilder)
4060 return ((ConstructorBuilder) method).GetToken ().Token;
4062 throw new NotSupportedException ();
4066 public void CloseMethod ()
4068 SymbolWriter.CloseMethod ();
4071 public void SetRealMethodName (string name)
4073 if (builder != null)
4074 builder.SetRealMethodName (name);
4077 public static SourceMethod Create (DeclSpace parent, MethodBase method, Block block)
4079 if (!SymbolWriter.HasSymbolWriter)
4084 Location start_loc = block.StartLocation;
4085 if (start_loc.IsNull)
4088 ICompileUnit compile_unit = start_loc.CompilationUnit;
4089 if (compile_unit == null)
4092 return new SourceMethod (parent, method, compile_unit);
4096 public class Method : MethodOrOperator {
4099 /// Modifiers allowed in a class declaration
4101 const Modifiers AllowedModifiers =
4104 Modifiers.PROTECTED |
4105 Modifiers.INTERNAL |
4110 Modifiers.OVERRIDE |
4111 Modifiers.ABSTRACT |
4115 const Modifiers AllowedInterfaceModifiers =
4116 Modifiers.NEW | Modifiers.UNSAFE;
4118 Method partialMethodImplementation;
4120 public Method (DeclSpace parent, GenericMethod generic,
4121 FullNamedExpression return_type, Modifiers mod,
4122 MemberName name, ParametersCompiled parameters, Attributes attrs)
4123 : base (parent, generic, return_type, mod,
4124 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
4125 name, attrs, parameters)
4129 protected Method (DeclSpace parent, FullNamedExpression return_type, Modifiers mod, Modifiers amod,
4130 MemberName name, ParametersCompiled parameters, Attributes attrs)
4131 : base (parent, null, return_type, mod, amod, name, attrs, parameters)
4135 public override string GetSignatureForError()
4137 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
4140 void Error_DuplicateEntryPoint (Method b)
4142 Report.Error (17, b.Location,
4143 "Program `{0}' has more than one entry point defined: `{1}'",
4144 CodeGen.FileName, b.GetSignatureForError ());
4147 bool IsEntryPoint ()
4149 if (ReturnType != TypeManager.void_type &&
4150 ReturnType != TypeManager.int32_type)
4153 if (Parameters.Count == 0)
4156 if (Parameters.Count > 1)
4159 Type t = Parameters.Types [0];
4160 return t.IsArray && t.GetArrayRank () == 1 &&
4161 TypeManager.GetElementType (t) == TypeManager.string_type &&
4162 (Parameters[0].ModFlags & ~Parameter.Modifier.PARAMS) == Parameter.Modifier.NONE;
4165 public override FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
4167 TypeParameter[] tp = CurrentTypeParameters;
4169 TypeParameter t = TypeParameter.FindTypeParameter (tp, name);
4171 return new TypeParameterExpr (t, loc);
4174 return base.LookupNamespaceOrType (name, loc, ignore_cs0104);
4177 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
4179 if (a.Type == pa.Conditional) {
4180 if (IsExplicitImpl) {
4181 Error_ConditionalAttributeIsNotValid ();
4185 if (ReturnType != TypeManager.void_type) {
4186 Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ());
4190 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
4191 Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ());
4196 Report.Error (582, Location, "Conditional not valid on interface members");
4200 if (MethodData.implementing != null) {
4201 Report.SymbolRelatedToPreviousError (MethodData.implementing.DeclaringType);
4202 Report.Error (629, Location, "Conditional member `{0}' cannot implement interface member `{1}'",
4203 GetSignatureForError (), TypeManager.CSharpSignature (MethodData.implementing));
4207 for (int i = 0; i < Parameters.Count; ++i) {
4208 if (Parameters.FixedParameters [i].ModFlags == Parameter.Modifier.OUT) {
4209 Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
4215 if (a.Type == pa.Extension) {
4216 a.Error_MisusedExtensionAttribute ();
4220 base.ApplyAttributeBuilder (a, cb, pa);
4223 protected override bool CheckForDuplications ()
4225 if (!base.CheckForDuplications ())
4228 var ar = Parent.PartialContainer.Properties;
4230 for (int i = 0; i < ar.Count; ++i) {
4231 PropertyBase pb = (PropertyBase) ar [i];
4232 if (pb.AreAccessorsDuplicateImplementation (this))
4237 ar = Parent.PartialContainer.Indexers;
4239 for (int i = 0; i < ar.Count; ++i) {
4240 PropertyBase pb = (PropertyBase) ar [i];
4241 if (pb.AreAccessorsDuplicateImplementation (this))
4249 protected override bool CheckBase ()
4251 if (!base.CheckBase ())
4254 if (base_method != null && (ModFlags & Modifiers.OVERRIDE) != 0 && Name == Destructor.MetadataName) {
4255 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
4256 TypeManager.CSharpSignature (base_method));
4262 public override TypeParameter[] CurrentTypeParameters {
4264 if (GenericMethod != null)
4265 return GenericMethod.CurrentTypeParameters;
4274 public override bool Define ()
4276 if (type_name == TypeManager.system_void_expr && Parameters.IsEmpty && Name == Destructor.MetadataName) {
4277 Report.Warning (465, 1, Location, "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
4280 if (!base.Define ())
4283 if (partialMethodImplementation != null && IsPartialDefinition)
4284 MethodBuilder = partialMethodImplementation.MethodBuilder;
4286 if (RootContext.StdLib && TypeManager.IsSpecialType (ReturnType)) {
4287 Error1599 (Location, ReturnType, Report);
4291 if (base_method != null && (ModFlags & Modifiers.NEW) == 0) {
4292 if (Parameters.Count == 1 && ParameterTypes [0] == TypeManager.object_type && Name == "Equals")
4293 Parent.PartialContainer.Mark_HasEquals ();
4294 else if (Parameters.IsEmpty && Name == "GetHashCode")
4295 Parent.PartialContainer.Mark_HasGetHashCode ();
4298 if ((ModFlags & Modifiers.STATIC) == 0)
4301 if (Parameters.HasExtensionMethodType) {
4302 if (Parent.PartialContainer.IsStaticClass && !Parent.IsGeneric) {
4303 if (!Parent.IsTopLevel)
4304 Report.Error (1109, Location, "`{0}': Extension methods cannot be defined in a nested class",
4305 GetSignatureForError ());
4307 PredefinedAttribute pa = PredefinedAttributes.Get.Extension;
4308 if (!pa.IsDefined) {
4309 Report.Error (1110, Location,
4310 "`{0}': Extension methods cannot be declared without a reference to System.Core.dll assembly. Add the assembly reference or remove `this' modifer from the first parameter",
4311 GetSignatureForError ());
4314 ModFlags |= Modifiers.METHOD_EXTENSION;
4315 Parent.PartialContainer.ModFlags |= Modifiers.METHOD_EXTENSION;
4316 CodeGen.Assembly.HasExtensionMethods = true;
4318 Report.Error (1106, Location, "`{0}': Extension methods must be defined in a non-generic static class",
4319 GetSignatureForError ());
4324 // This is used to track the Entry Point,
4326 if (RootContext.NeedsEntryPoint &&
4328 (RootContext.MainClass == null ||
4329 RootContext.MainClass == Parent.TypeBuilder.FullName)){
4330 if (IsEntryPoint ()) {
4332 if (RootContext.EntryPoint == null) {
4333 if (Parent.IsGeneric || MemberName.IsGeneric) {
4334 Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type",
4335 GetSignatureForError ());
4338 RootContext.EntryPoint = this;
4341 Error_DuplicateEntryPoint (RootContext.EntryPoint);
4342 Error_DuplicateEntryPoint (this);
4345 Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point",
4346 GetSignatureForError ());
4356 public override void Emit ()
4359 Report.Debug (64, "METHOD EMIT", this, MethodBuilder, Location, Block, MethodData);
4360 if (IsPartialDefinition) {
4362 // Use partial method implementation builder for partial method declaration attributes
4364 if (partialMethodImplementation != null) {
4365 MethodBuilder = partialMethodImplementation.MethodBuilder;
4368 } else if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.PartialDefinitionExists) == 0) {
4369 Report.Error (759, Location, "A partial method `{0}' implementation is missing a partial method declaration",
4370 GetSignatureForError ());
4375 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
4376 PredefinedAttributes.Get.Extension.EmitAttribute (MethodBuilder);
4378 Console.WriteLine ("Internal compiler error at {0}: exception caught while emitting {1}",
4379 Location, MethodBuilder);
4384 public override bool EnableOverloadChecks (MemberCore overload)
4386 // TODO: It can be deleted when members will be defined in correct order
4387 if (overload is Operator)
4388 return overload.EnableOverloadChecks (this);
4390 if (overload is Indexer)
4393 return base.EnableOverloadChecks (overload);
4396 public static void Error1599 (Location loc, Type t, Report Report)
4398 Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t));
4401 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
4403 MethodInfo mi = (MethodInfo) Parent.PartialContainer.BaseCache.FindMemberToOverride (
4404 Parent.TypeBuilder, Name, Parameters, GenericMethod, false);
4409 if (mi.IsSpecialName)
4412 base_ret_type = TypeManager.TypeToCoreType (mi.ReturnType);
4416 public void SetPartialDefinition (Method methodDefinition)
4418 caching_flags |= Flags.PartialDefinitionExists;
4419 methodDefinition.partialMethodImplementation = this;
4421 // Ensure we are always using method declaration parameters
4422 for (int i = 0; i < methodDefinition.Parameters.Count; ++i ) {
4423 Parameters [i].Name = methodDefinition.Parameters [i].Name;
4424 Parameters [i].DefaultValue = methodDefinition.Parameters [i].DefaultValue;
4427 if (methodDefinition.attributes == null)
4430 if (attributes == null) {
4431 attributes = methodDefinition.attributes;
4433 attributes.Attrs.AddRange (methodDefinition.attributes.Attrs);
4437 protected override bool VerifyClsCompliance ()
4439 if (!base.VerifyClsCompliance ())
4442 if (!Parameters.IsEmpty) {
4443 var al = Parent.PartialContainer.MemberCache.Members [Name];
4445 MemberCache.VerifyClsParameterConflict (al, this, MethodBuilder, Report);
4452 public abstract class ConstructorInitializer : ExpressionStatement
4454 Arguments argument_list;
4455 MethodGroupExpr base_constructor_group;
4457 public ConstructorInitializer (Arguments argument_list, Location loc)
4459 this.argument_list = argument_list;
4463 public Arguments Arguments {
4465 return argument_list;
4469 public override Expression CreateExpressionTree (ResolveContext ec)
4471 throw new NotSupportedException ("ET");
4474 protected override Expression DoResolve (ResolveContext ec)
4476 eclass = ExprClass.Value;
4478 // TODO: ec.GetSignatureForError ()
4479 ConstructorBuilder caller_builder = ((Constructor) ec.MemberContext).ConstructorBuilder;
4481 if (argument_list != null) {
4485 // Spec mandates that constructor initializer will not have `this' access
4487 using (ec.Set (ResolveContext.Options.BaseInitializer)) {
4488 argument_list.Resolve (ec, out dynamic);
4492 ec.Report.Error (1975, loc,
4493 "The constructor call cannot be dynamically dispatched within constructor initializer");
4499 type = ec.CurrentType;
4500 if (this is ConstructorBaseInitializer) {
4501 if (ec.CurrentType.BaseType == null)
4504 type = ec.CurrentType.BaseType;
4505 if (TypeManager.IsStruct (ec.CurrentType)) {
4506 ec.Report.Error (522, loc,
4507 "`{0}': Struct constructors cannot call base constructors", TypeManager.CSharpSignature (caller_builder));
4512 // It is legal to have "this" initializers that take no arguments
4513 // in structs, they are just no-ops.
4515 // struct D { public D (int a) : this () {}
4517 if (TypeManager.IsStruct (ec.CurrentType) && argument_list == null)
4521 base_constructor_group = MemberLookupFinal (
4522 ec, null, type, ConstructorBuilder.ConstructorName, MemberTypes.Constructor,
4523 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
4524 loc) as MethodGroupExpr;
4526 if (base_constructor_group == null)
4529 base_constructor_group = base_constructor_group.OverloadResolve (
4530 ec, ref argument_list, false, loc);
4532 if (base_constructor_group == null)
4536 base_constructor_group.InstanceExpression = ec.GetThis (loc);
4538 ConstructorInfo base_ctor = (ConstructorInfo)base_constructor_group;
4540 if (base_ctor == caller_builder){
4541 ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself", TypeManager.CSharpSignature (caller_builder));
4547 public override void Emit (EmitContext ec)
4549 // It can be null for static initializers
4550 if (base_constructor_group == null)
4555 base_constructor_group.EmitCall (ec, argument_list);
4558 public override void EmitStatement (EmitContext ec)
4564 public class ConstructorBaseInitializer : ConstructorInitializer {
4565 public ConstructorBaseInitializer (Arguments argument_list, Location l) :
4566 base (argument_list, l)
4571 class GeneratedBaseInitializer: ConstructorBaseInitializer {
4572 public GeneratedBaseInitializer (Location loc):
4578 public class ConstructorThisInitializer : ConstructorInitializer {
4579 public ConstructorThisInitializer (Arguments argument_list, Location l) :
4580 base (argument_list, l)
4585 public class Constructor : MethodCore, IMethodData {
4586 public ConstructorBuilder ConstructorBuilder;
4587 public ConstructorInitializer Initializer;
4588 Dictionary<SecurityAction, PermissionSet> declarative_security;
4589 bool has_compliant_args;
4592 // Modifiers allowed for a constructor.
4594 public const Modifiers AllowedModifiers =
4596 Modifiers.PROTECTED |
4597 Modifiers.INTERNAL |
4603 static readonly string[] attribute_targets = new string [] { "method" };
4606 // The spec claims that static is not permitted, but
4607 // my very own code has static constructors.
4609 public Constructor (DeclSpace parent, string name, Modifiers mod, Attributes attrs, ParametersCompiled args,
4610 ConstructorInitializer init, Location loc)
4611 : base (parent, null, null, mod, AllowedModifiers,
4612 new MemberName (name, loc), attrs, args)
4617 public bool HasCompliantArgs {
4618 get { return has_compliant_args; }
4621 public override AttributeTargets AttributeTargets {
4622 get { return AttributeTargets.Constructor; }
4626 // Returns true if this is a default constructor
4628 public bool IsDefault ()
4630 if ((ModFlags & Modifiers.STATIC) != 0)
4631 return Parameters.IsEmpty;
4633 return Parameters.IsEmpty &&
4634 (Initializer is ConstructorBaseInitializer) &&
4635 (Initializer.Arguments == null);
4638 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
4640 if (a.IsValidSecurityAttribute ()) {
4641 if (declarative_security == null) {
4642 declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
4644 a.ExtractSecurityPermissionSet (declarative_security);
4648 if (a.IsInternalMethodImplAttribute) {
4649 is_external_implementation = true;
4652 ConstructorBuilder.SetCustomAttribute (cb);
4655 protected override bool CheckBase ()
4657 if ((ModFlags & Modifiers.STATIC) != 0) {
4658 if (!Parameters.IsEmpty) {
4659 Report.Error (132, Location, "`{0}': The static constructor must be parameterless",
4660 GetSignatureForError ());
4664 // the rest can be ignored
4668 // Check whether arguments were correct.
4669 if (!DefineParameters (Parameters))
4672 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
4673 Parent.MemberCache.CheckExistingMembersOverloads (this, ConstructorInfo.ConstructorName,
4674 Parameters, Report);
4676 if (Parent.PartialContainer.Kind == Kind.Struct) {
4677 if (Parameters.Count == 0) {
4678 Report.Error (568, Location,
4679 "Structs cannot contain explicit parameterless constructors");
4684 CheckProtectedModifier ();
4690 // Creates the ConstructorBuilder
4692 public override bool Define ()
4694 if (ConstructorBuilder != null)
4697 MethodAttributes ca = (MethodAttributes.RTSpecialName |
4698 MethodAttributes.SpecialName);
4700 if ((ModFlags & Modifiers.STATIC) != 0) {
4701 ca |= MethodAttributes.Static | MethodAttributes.Private;
4703 ca |= MethodAttributes.HideBySig;
4705 if ((ModFlags & Modifiers.PUBLIC) != 0)
4706 ca |= MethodAttributes.Public;
4707 else if ((ModFlags & Modifiers.PROTECTED) != 0){
4708 if ((ModFlags & Modifiers.INTERNAL) != 0)
4709 ca |= MethodAttributes.FamORAssem;
4711 ca |= MethodAttributes.Family;
4712 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
4713 ca |= MethodAttributes.Assembly;
4715 ca |= MethodAttributes.Private;
4718 if (!CheckAbstractAndExtern (block != null))
4721 // Check if arguments were correct.
4725 ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
4726 ca, CallingConventions,
4727 Parameters.GetEmitTypes ());
4729 if (Parent.PartialContainer.IsComImport) {
4730 if (!IsDefault ()) {
4731 Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
4732 Parent.GetSignatureForError ());
4734 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
4737 Parent.MemberCache.AddMember (ConstructorBuilder, this);
4738 TypeManager.AddMethod (ConstructorBuilder, this);
4740 // It's here only to report an error
4741 if (block != null && block.IsIterator) {
4742 member_type = TypeManager.void_type;
4743 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
4752 public override void Emit ()
4754 if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
4755 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (ConstructorBuilder);
4757 if (OptAttributes != null)
4758 OptAttributes.Emit ();
4763 // If we use a "this (...)" constructor initializer, then
4764 // do not emit field initializers, they are initialized in the other constructor
4766 bool emit_field_initializers = ((ModFlags & Modifiers.STATIC) != 0) ||
4767 !(Initializer is ConstructorThisInitializer);
4769 BlockContext bc = new BlockContext (this, block, TypeManager.void_type);
4770 bc.Set (ResolveContext.Options.ConstructorScope);
4772 if (emit_field_initializers)
4773 Parent.PartialContainer.ResolveFieldInitializers (bc);
4775 if (block != null) {
4776 // If this is a non-static `struct' constructor and doesn't have any
4777 // initializer, it must initialize all of the struct's fields.
4778 if ((Parent.PartialContainer.Kind == Kind.Struct) &&
4779 ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
4780 block.AddThisVariable (Parent, Location);
4782 if (block != null && (ModFlags & Modifiers.STATIC) == 0){
4783 if (Parent.PartialContainer.Kind == Kind.Class && Initializer == null)
4784 Initializer = new GeneratedBaseInitializer (Location);
4786 if (Initializer != null) {
4787 block.AddScopeStatement (new StatementExpression (Initializer));
4792 Parameters.ApplyAttributes (ConstructorBuilder);
4794 SourceMethod source = SourceMethod.Create (Parent, ConstructorBuilder, block);
4796 if (block != null) {
4797 if (block.Resolve (null, bc, Parameters, this)) {
4798 EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType);
4799 ec.With (EmitContext.Options.ConstructorScope, true);
4801 if (!ec.HasReturnLabel && bc.HasReturnLabel) {
4802 ec.ReturnLabel = bc.ReturnLabel;
4803 ec.HasReturnLabel = true;
4811 source.CloseMethod ();
4813 if (declarative_security != null) {
4814 foreach (var de in declarative_security) {
4815 ConstructorBuilder.AddDeclarativeSecurity (de.Key, de.Value);
4822 // Is never override
4823 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
4828 public override string GetSignatureForError()
4830 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
4833 public override string[] ValidAttributeTargets {
4835 return attribute_targets;
4839 protected override bool VerifyClsCompliance ()
4841 if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
4845 if (!Parameters.IsEmpty) {
4846 var al = Parent.MemberCache.Members [ConstructorInfo.ConstructorName];
4848 MemberCache.VerifyClsParameterConflict (al, this, ConstructorBuilder, Report);
4850 if (TypeManager.IsSubclassOf (Parent.TypeBuilder, TypeManager.attribute_type)) {
4851 foreach (Type param in Parameters.Types) {
4852 if (param.IsArray) {
4858 has_compliant_args = true;
4862 #region IMethodData Members
4864 public MemberName MethodName {
4870 public Type ReturnType {
4876 public EmitContext CreateEmitContext (ILGenerator ig)
4878 throw new NotImplementedException ();
4881 public bool IsExcluded()
4886 GenericMethod IMethodData.GenericMethod {
4892 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
4899 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
4901 public interface IMethodData
4903 CallingConventions CallingConventions { get; }
4904 Location Location { get; }
4905 MemberName MethodName { get; }
4906 Type ReturnType { get; }
4907 GenericMethod GenericMethod { get; }
4908 ParametersCompiled ParameterInfo { get; }
4910 Attributes OptAttributes { get; }
4911 ToplevelBlock Block { get; set; }
4913 EmitContext CreateEmitContext (ILGenerator ig);
4914 ObsoleteAttribute GetObsoleteAttribute ();
4915 string GetSignatureForError ();
4917 bool IsClsComplianceRequired ();
4918 void SetMemberIsUsed ();
4919 void EmitExtraSymbolInfo (SourceMethod source);
4923 // Encapsulates most of the Method's state
4925 public class MethodData {
4926 static FieldInfo methodbuilder_attrs_field;
4927 public readonly IMethodData method;
4929 public readonly GenericMethod GenericMethod;
4932 // Are we implementing an interface ?
4934 public MethodInfo implementing;
4939 protected InterfaceMemberBase member;
4940 protected Modifiers modifiers;
4941 protected MethodAttributes flags;
4942 protected Type declaring_type;
4943 protected MethodInfo parent_method;
4945 MethodBuilder builder = null;
4946 public MethodBuilder MethodBuilder {
4952 public Type DeclaringType {
4954 return declaring_type;
4958 public MethodData (InterfaceMemberBase member,
4959 Modifiers modifiers, MethodAttributes flags, IMethodData method)
4961 this.member = member;
4962 this.modifiers = modifiers;
4965 this.method = method;
4968 public MethodData (InterfaceMemberBase member,
4969 Modifiers modifiers, MethodAttributes flags,
4970 IMethodData method, MethodBuilder builder,
4971 GenericMethod generic, MethodInfo parent_method)
4972 : this (member, modifiers, flags, method)
4974 this.builder = builder;
4975 this.GenericMethod = generic;
4976 this.parent_method = parent_method;
4979 public bool Define (DeclSpace parent, string method_full_name, Report Report)
4981 string name = method.MethodName.Basename;
4983 TypeContainer container = parent.PartialContainer;
4985 PendingImplementation pending = container.PendingImplementations;
4986 if (pending != null){
4987 implementing = pending.IsInterfaceMethod (name, member.InterfaceType, this);
4989 if (member.InterfaceType != null){
4990 if (implementing == null){
4991 if (member is PropertyBase) {
4992 Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'",
4993 method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType),
4994 member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
4997 Report.Error (539, method.Location,
4998 "`{0}.{1}' in explicit interface declaration is not a member of interface",
4999 TypeManager.CSharpName (member.InterfaceType), member.ShortName);
5003 if (implementing.IsSpecialName && !(method is AbstractPropertyEventMethod)) {
5004 Report.SymbolRelatedToPreviousError (implementing);
5005 Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
5006 member.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
5010 if (implementing != null) {
5011 AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod;
5012 if (prop_method == null) {
5013 if (TypeManager.IsSpecialMethod (implementing)) {
5014 Report.SymbolRelatedToPreviousError (implementing);
5015 Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}.{2}'",
5016 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing),
5017 implementing.Name.StartsWith ("get_") ? "get" : "set");
5019 } else if (implementing.DeclaringType.IsInterface) {
5020 if (!implementing.IsSpecialName) {
5021 Report.SymbolRelatedToPreviousError (implementing);
5022 Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
5023 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
5026 PropertyBase.PropertyMethod pm = prop_method as PropertyBase.PropertyMethod;
5027 if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
5028 Report.SymbolRelatedToPreviousError (implementing);
5029 Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'",
5030 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing, true));
5039 // For implicit implementations, make sure we are public, for
5040 // explicit implementations, make sure we are private.
5042 if (implementing != null){
5044 // Setting null inside this block will trigger a more
5045 // verbose error reporting for missing interface implementations
5047 // The "candidate" function has been flagged already
5048 // but it wont get cleared
5050 if (member.IsExplicitImpl){
5051 if (method.ParameterInfo.HasParams && !TypeManager.GetParameterData (implementing).HasParams) {
5052 Report.SymbolRelatedToPreviousError (implementing);
5053 Report.Error (466, method.Location, "`{0}': the explicit interface implementation cannot introduce the params modifier",
5054 method.GetSignatureForError ());
5058 if (implementing.DeclaringType.IsInterface) {
5060 // If this is an interface method implementation,
5061 // check for public accessibility
5063 if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
5065 implementing = null;
5067 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
5068 // We may never be private.
5069 implementing = null;
5071 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
5073 // We may be protected if we're overriding something.
5075 implementing = null;
5080 // Static is not allowed
5082 if ((modifiers & Modifiers.STATIC) != 0){
5083 implementing = null;
5088 // If implementing is still valid, set flags
5090 if (implementing != null){
5092 // When implementing interface methods, set NewSlot
5093 // unless, we are overwriting a method.
5095 if (implementing.DeclaringType.IsInterface){
5096 if ((modifiers & Modifiers.OVERRIDE) == 0)
5097 flags |= MethodAttributes.NewSlot;
5100 MethodAttributes.Virtual |
5101 MethodAttributes.HideBySig;
5103 // Set Final unless we're virtual, abstract or already overriding a method.
5104 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
5105 flags |= MethodAttributes.Final;
5108 DefineMethodBuilder (container, method_full_name, method.ParameterInfo);
5110 if (builder == null)
5113 if (container.CurrentType != null)
5114 declaring_type = container.CurrentType;
5116 declaring_type = container.TypeBuilder;
5118 if (implementing != null && member.IsExplicitImpl) {
5119 container.TypeBuilder.DefineMethodOverride (builder, implementing);
5122 TypeManager.AddMethod (builder, method);
5124 if (GenericMethod != null) {
5125 bool is_override = member.IsExplicitImpl |
5126 ((modifiers & Modifiers.OVERRIDE) != 0);
5128 if (implementing != null)
5129 parent_method = implementing;
5131 if (!GenericMethod.DefineType (GenericMethod, builder, parent_method, is_override))
5140 /// Create the MethodBuilder for the method
5142 void DefineMethodBuilder (TypeContainer container, string method_name, ParametersCompiled param)
5144 if (builder == null) {
5145 builder = container.TypeBuilder.DefineMethod (
5146 method_name, flags, method.CallingConventions,
5148 param.GetEmitTypes ());
5153 // Generic method has been already defined to resolve method parameters
5154 // correctly when they use type parameters
5156 builder.SetParameters (param.GetEmitTypes ());
5157 builder.SetReturnType (method.ReturnType);
5158 if (builder.Attributes != flags) {
5160 if (methodbuilder_attrs_field == null)
5161 methodbuilder_attrs_field = typeof (MethodBuilder).GetField ("attrs", BindingFlags.NonPublic | BindingFlags.Instance);
5162 methodbuilder_attrs_field.SetValue (builder, flags);
5164 container.Compiler.Report.RuntimeMissingSupport (method.Location, "Generic method MethodAttributes");
5172 public void Emit (DeclSpace parent)
5174 method.ParameterInfo.ApplyAttributes (MethodBuilder);
5176 if (GenericMethod != null)
5177 GenericMethod.EmitAttributes ();
5180 // clear the pending implementation flag
5182 if (implementing != null)
5183 parent.PartialContainer.PendingImplementations.ImplementMethod (method.MethodName.Basename,
5184 member.InterfaceType, this, member.IsExplicitImpl);
5186 SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
5188 ToplevelBlock block = method.Block;
5189 if (block != null) {
5190 BlockContext bc = new BlockContext ((IMemberContext) method, block, method.ReturnType);
5191 if (block.Resolve (null, bc, method.ParameterInfo, method)) {
5192 EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator ());
5193 if (!ec.HasReturnLabel && bc.HasReturnLabel) {
5194 ec.ReturnLabel = bc.ReturnLabel;
5195 ec.HasReturnLabel = true;
5202 if (source != null) {
5203 method.EmitExtraSymbolInfo (source);
5204 source.CloseMethod ();
5209 public class Destructor : MethodOrOperator
5211 const Modifiers AllowedModifiers =
5215 static readonly string[] attribute_targets = new string [] { "method" };
5217 public static readonly string MetadataName = "Finalize";
5219 public Destructor (DeclSpace parent, Modifiers mod, ParametersCompiled parameters, Attributes attrs, Location l)
5220 : base (parent, null, TypeManager.system_void_expr, mod, AllowedModifiers,
5221 new MemberName (MetadataName, l), attrs, parameters)
5223 ModFlags &= ~Modifiers.PRIVATE;
5224 ModFlags |= Modifiers.PROTECTED;
5227 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
5229 if (a.Type == pa.Conditional) {
5230 Error_ConditionalAttributeIsNotValid ();
5234 base.ApplyAttributeBuilder (a, cb, pa);
5237 protected override bool CheckBase ()
5239 flags |= MethodAttributes.Virtual;
5241 if (!base.CheckBase ())
5244 if (Parent.PartialContainer.BaseCache == null)
5247 Type base_type = Parent.PartialContainer.BaseCache.Container.Type;
5248 if (base_type != null && Block != null) {
5249 MethodGroupExpr method_expr = Expression.MethodLookup (Parent.Module.Compiler, Parent.TypeBuilder, base_type, MetadataName, Location);
5250 if (method_expr == null)
5251 throw new NotImplementedException ();
5253 method_expr.IsBase = true;
5254 method_expr.InstanceExpression = new CompilerGeneratedThis (Parent.TypeBuilder, Location);
5256 ToplevelBlock new_block = new ToplevelBlock (Compiler, Block.StartLocation);
5257 new_block.EndLocation = Block.EndLocation;
5259 Block finaly_block = new ExplicitBlock (new_block, Location, Location);
5260 Block try_block = new Block (new_block, block);
5263 // 0-size arguments to avoid CS0250 error
5264 // TODO: Should use AddScopeStatement or something else which emits correct
5267 finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0))));
5268 new_block.AddStatement (new TryFinally (try_block, finaly_block, Location));
5276 public override string GetSignatureForError ()
5278 return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
5281 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
5286 public override string[] ValidAttributeTargets {
5288 return attribute_targets;
5293 public abstract class MemberBase : MemberCore
5295 protected FullNamedExpression type_name;
5296 protected Type member_type;
5298 public readonly DeclSpace ds;
5299 public readonly GenericMethod GenericMethod;
5301 protected MemberBase (DeclSpace parent, GenericMethod generic,
5302 FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod,
5303 MemberName name, Attributes attrs)
5304 : base (parent, name, attrs)
5306 this.ds = generic != null ? generic : (DeclSpace) parent;
5307 this.type_name = type;
5308 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
5309 GenericMethod = generic;
5310 if (GenericMethod != null)
5311 GenericMethod.ModFlags = ModFlags;
5315 // Main member define entry
5317 public override bool Define ()
5319 DoMemberTypeIndependentChecks ();
5322 // Returns false only when type resolution failed
5324 if (!ResolveMemberType ())
5327 DoMemberTypeDependentChecks ();
5332 // Any type_name independent checks
5334 protected virtual void DoMemberTypeIndependentChecks ()
5336 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
5337 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
5338 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
5339 GetSignatureForError (), Parent.GetSignatureForError ());
5344 // Any type_name dependent checks
5346 protected virtual void DoMemberTypeDependentChecks ()
5348 // verify accessibility
5349 if (!IsAccessibleAs (MemberType)) {
5350 Report.SymbolRelatedToPreviousError (MemberType);
5351 if (this is Property)
5352 Report.Error (53, Location,
5353 "Inconsistent accessibility: property type `" +
5354 TypeManager.CSharpName (MemberType) + "' is less " +
5355 "accessible than property `" + GetSignatureForError () + "'");
5356 else if (this is Indexer)
5357 Report.Error (54, Location,
5358 "Inconsistent accessibility: indexer return type `" +
5359 TypeManager.CSharpName (MemberType) + "' is less " +
5360 "accessible than indexer `" + GetSignatureForError () + "'");
5361 else if (this is MethodCore) {
5362 if (this is Operator)
5363 Report.Error (56, Location,
5364 "Inconsistent accessibility: return type `" +
5365 TypeManager.CSharpName (MemberType) + "' is less " +
5366 "accessible than operator `" + GetSignatureForError () + "'");
5368 Report.Error (50, Location,
5369 "Inconsistent accessibility: return type `" +
5370 TypeManager.CSharpName (MemberType) + "' is less " +
5371 "accessible than method `" + GetSignatureForError () + "'");
5373 Report.Error (52, Location,
5374 "Inconsistent accessibility: field type `" +
5375 TypeManager.CSharpName (MemberType) + "' is less " +
5376 "accessible than field `" + GetSignatureForError () + "'");
5380 Variance variance = this is Event ? Variance.Contravariant : Variance.Covariant;
5381 TypeManager.CheckTypeVariance (MemberType, variance, this);
5384 protected bool IsTypePermitted ()
5386 if (TypeManager.IsSpecialType (MemberType)) {
5387 Report.Error (610, Location, "Field or property cannot be of type `{0}'", TypeManager.CSharpName (MemberType));
5393 protected virtual bool CheckBase ()
5395 CheckProtectedModifier ();
5400 public Type MemberType {
5401 get { return member_type; }
5404 protected virtual bool ResolveMemberType ()
5406 if (member_type != null)
5407 throw new InternalErrorException ("Multi-resolve");
5409 TypeExpr te = type_name.ResolveAsTypeTerminal (this, false);
5414 // Replace original type name, error reporting can use fully resolved name
5418 member_type = te.Type;
5424 // `set' and `get' accessors are represented with an Accessor.
5426 public class Accessor {
5428 // Null if the accessor is empty, or a Block if not
5430 public const Modifiers AllowedModifiers =
5432 Modifiers.PROTECTED |
5433 Modifiers.INTERNAL |
5436 public ToplevelBlock Block;
5437 public Attributes Attributes;
5438 public Location Location;
5439 public Modifiers ModFlags;
5440 public ParametersCompiled Parameters;
5442 public Accessor (ToplevelBlock b, Modifiers mod, Attributes attrs, ParametersCompiled p, Location loc)
5448 ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, 0, loc, RootContext.ToplevelTypes.Compiler.Report);
5452 // Ooouh Martin, templates are missing here.
5453 // When it will be possible move here a lot of child code and template method type.
5454 public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData {
5455 protected MethodData method_data;
5456 protected ToplevelBlock block;
5457 protected Dictionary<SecurityAction, PermissionSet> declarative_security;
5459 // The accessor are created even if they are not wanted.
5460 // But we need them because their names are reserved.
5461 // Field says whether accessor will be emited or not
5462 public readonly bool IsDummy;
5464 protected readonly string prefix;
5466 ReturnParameter return_attributes;
5468 public AbstractPropertyEventMethod (PropertyBasedMember member, string prefix)
5469 : base (member.Parent, SetupName (prefix, member, member.Location), null)
5471 this.prefix = prefix;
5475 public AbstractPropertyEventMethod (InterfaceMemberBase member, Accessor accessor,
5477 : base (member.Parent, SetupName (prefix, member, accessor.Location),
5478 accessor.Attributes)
5480 this.prefix = prefix;
5481 this.block = accessor.Block;
5484 static MemberName SetupName (string prefix, InterfaceMemberBase member, Location loc)
5486 return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc);
5489 public void UpdateName (InterfaceMemberBase member)
5491 SetMemberName (SetupName (prefix, member, Location));
5494 #region IMethodData Members
5496 public ToplevelBlock Block {
5506 public CallingConventions CallingConventions {
5508 return CallingConventions.Standard;
5512 public EmitContext CreateEmitContext (ILGenerator ig)
5514 return new EmitContext (this, ig, ReturnType);
5517 public bool IsExcluded ()
5522 GenericMethod IMethodData.GenericMethod {
5528 public MemberName MethodName {
5534 public Type[] ParameterTypes {
5536 return ParameterInfo.Types;
5540 public abstract ParametersCompiled ParameterInfo { get ; }
5541 public abstract Type ReturnType { get; }
5545 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
5547 if (a.Type == pa.CLSCompliant || a.Type == pa.Obsolete || a.Type == pa.Conditional) {
5548 Report.Error (1667, a.Location,
5549 "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
5550 TypeManager.CSharpName (a.Type), a.GetValidTargets ());
5554 if (a.IsValidSecurityAttribute ()) {
5555 if (declarative_security == null)
5556 declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
5557 a.ExtractSecurityPermissionSet (declarative_security);
5561 if (a.Target == AttributeTargets.Method) {
5562 method_data.MethodBuilder.SetCustomAttribute (cb);
5566 if (a.Target == AttributeTargets.ReturnValue) {
5567 if (return_attributes == null)
5568 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
5570 return_attributes.ApplyAttributeBuilder (a, cb, pa);
5574 ApplyToExtraTarget (a, cb, pa);
5577 protected virtual void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
5579 throw new NotSupportedException ("You forgot to define special attribute target handling");
5582 // It is not supported for the accessors
5583 public sealed override bool Define()
5585 throw new NotSupportedException ();
5588 public virtual void Emit (DeclSpace parent)
5590 method_data.Emit (parent);
5592 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
5593 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (method_data.MethodBuilder);
5594 if (((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0))
5595 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (method_data.MethodBuilder);
5597 if (TypeManager.IsDynamicType (ReturnType)) {
5598 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
5599 PredefinedAttributes.Get.Dynamic.EmitAttribute (return_attributes.Builder);
5601 var trans_flags = TypeManager.HasDynamicTypeUsed (ReturnType);
5602 if (trans_flags != null) {
5603 var pa = PredefinedAttributes.Get.DynamicTransform;
5604 if (pa.Constructor != null || pa.ResolveConstructor (Location, TypeManager.bool_type.MakeArrayType ())) {
5605 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
5606 return_attributes.Builder.SetCustomAttribute (
5607 new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
5612 if (OptAttributes != null)
5613 OptAttributes.Emit ();
5615 if (declarative_security != null) {
5616 foreach (var de in declarative_security) {
5617 method_data.MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value);
5624 public override bool EnableOverloadChecks (MemberCore overload)
5626 // This can only happen with indexers and it will
5627 // be catched as indexer difference
5628 if (overload is AbstractPropertyEventMethod)
5631 if (overload is MethodCore) {
5632 caching_flags |= Flags.MethodOverloadsExist;
5638 public override bool IsClsComplianceRequired()
5643 public bool IsDuplicateImplementation (MethodCore method)
5645 if (!MemberName.Equals (method.MemberName))
5648 Type[] param_types = method.ParameterTypes;
5650 if (param_types == null || param_types.Length != ParameterTypes.Length)
5653 for (int i = 0; i < param_types.Length; i++)
5654 if (param_types [i] != ParameterTypes [i])
5657 Report.SymbolRelatedToPreviousError (method);
5658 Report.Error (82, Location, "A member `{0}' is already reserved",
5659 method.GetSignatureForError ());
5663 public override bool IsUsed
5674 // Represents header string for documentation comment.
5676 public override string DocCommentHeader {
5677 get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
5680 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
5685 // Properties and Indexers both generate PropertyBuilders, we use this to share
5686 // their common bits.
5688 abstract public class PropertyBase : PropertyBasedMember {
5690 public class GetMethod : PropertyMethod
5692 static string[] attribute_targets = new string [] { "method", "return" };
5694 public GetMethod (PropertyBase method):
5695 base (method, "get_")
5699 public GetMethod (PropertyBase method, Accessor accessor):
5700 base (method, accessor, "get_")
5704 public override MethodBuilder Define (DeclSpace parent)
5706 base.Define (parent);
5711 method_data = new MethodData (method, ModFlags, flags, this);
5713 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
5716 return method_data.MethodBuilder;
5719 public override Type ReturnType {
5721 return method.MemberType;
5725 public override ParametersCompiled ParameterInfo {
5727 return ParametersCompiled.EmptyReadOnlyParameters;
5731 public override string[] ValidAttributeTargets {
5733 return attribute_targets;
5738 public class SetMethod : PropertyMethod {
5740 static string[] attribute_targets = new string [] { "method", "param", "return" };
5741 ImplicitParameter param_attr;
5742 protected ParametersCompiled parameters;
5744 public SetMethod (PropertyBase method) :
5745 base (method, "set_")
5747 parameters = new ParametersCompiled (Compiler,
5748 new Parameter (method.type_name, "value", Parameter.Modifier.NONE, null, Location));
5751 public SetMethod (PropertyBase method, Accessor accessor):
5752 base (method, accessor, "set_")
5754 this.parameters = accessor.Parameters;
5757 protected override void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
5759 if (a.Target == AttributeTargets.Parameter) {
5760 if (param_attr == null)
5761 param_attr = new ImplicitParameter (method_data.MethodBuilder);
5763 param_attr.ApplyAttributeBuilder (a, cb, pa);
5767 base.ApplyAttributeBuilder (a, cb, pa);
5770 public override ParametersCompiled ParameterInfo {
5776 public override MethodBuilder Define (DeclSpace parent)
5778 parameters.Resolve (this);
5780 base.Define (parent);
5785 method_data = new MethodData (method, ModFlags, flags, this);
5787 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
5790 return method_data.MethodBuilder;
5793 public override Type ReturnType {
5795 return TypeManager.void_type;
5799 public override string[] ValidAttributeTargets {
5801 return attribute_targets;
5806 static string[] attribute_targets = new string [] { "property" };
5808 public abstract class PropertyMethod : AbstractPropertyEventMethod
5810 protected readonly PropertyBase method;
5811 protected MethodAttributes flags;
5813 public PropertyMethod (PropertyBase method, string prefix)
5814 : base (method, prefix)
5816 this.method = method;
5817 this.ModFlags = method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE);
5820 public PropertyMethod (PropertyBase method, Accessor accessor,
5822 : base (method, accessor, prefix)
5824 this.method = method;
5825 this.ModFlags = accessor.ModFlags | (method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE));
5827 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
5828 Report.FeatureIsNotAvailable (Location, "access modifiers on properties");
5832 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
5834 if (a.IsInternalMethodImplAttribute) {
5835 method.is_external_implementation = true;
5838 base.ApplyAttributeBuilder (a, cb, pa);
5841 public override AttributeTargets AttributeTargets {
5843 return AttributeTargets.Method;
5847 public override bool IsClsComplianceRequired ()
5849 return method.IsClsComplianceRequired ();
5852 public virtual MethodBuilder Define (DeclSpace parent)
5854 CheckForDuplications ();
5857 if (method.InterfaceType != null && parent.PartialContainer.PendingImplementations != null) {
5858 MethodInfo mi = parent.PartialContainer.PendingImplementations.IsInterfaceMethod (
5859 MethodName.Name, method.InterfaceType, new MethodData (method, ModFlags, flags, this));
5861 Report.SymbolRelatedToPreviousError (mi);
5862 Report.Error (551, Location, "Explicit interface implementation `{0}' is missing accessor `{1}'",
5863 method.GetSignatureForError (), TypeManager.CSharpSignature (mi, true));
5869 TypeContainer container = parent.PartialContainer;
5872 // Check for custom access modifier
5874 if ((ModFlags & Modifiers.AccessibilityMask) == 0) {
5875 ModFlags |= method.ModFlags;
5876 flags = method.flags;
5878 if (container.Kind == Kind.Interface)
5879 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
5880 GetSignatureForError ());
5882 if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
5883 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
5886 CheckModifiers (ModFlags);
5887 ModFlags |= (method.ModFlags & (~Modifiers.AccessibilityMask));
5888 ModFlags |= Modifiers.PROPERTY_CUSTOM;
5889 flags = ModifiersExtensions.MethodAttr (ModFlags);
5890 flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
5893 CheckAbstractAndExtern (block != null);
5894 CheckProtectedModifier ();
5896 if (block != null && block.IsIterator)
5897 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
5902 public bool HasCustomAccessModifier {
5904 return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
5908 public PropertyBase Property {
5914 public override ObsoleteAttribute GetObsoleteAttribute ()
5916 return method.GetObsoleteAttribute ();
5919 public override string GetSignatureForError()
5921 return method.GetSignatureForError () + '.' + prefix.Substring (0, 3);
5924 void CheckModifiers (Modifiers modflags)
5926 modflags &= Modifiers.AccessibilityMask;
5927 Modifiers flags = 0;
5928 Modifiers mflags = method.ModFlags & Modifiers.AccessibilityMask;
5930 if ((mflags & Modifiers.PUBLIC) != 0) {
5931 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
5933 else if ((mflags & Modifiers.PROTECTED) != 0) {
5934 if ((mflags & Modifiers.INTERNAL) != 0)
5935 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL;
5937 flags |= Modifiers.PRIVATE;
5938 } else if ((mflags & Modifiers.INTERNAL) != 0)
5939 flags |= Modifiers.PRIVATE;
5941 if ((mflags == modflags) || (modflags & (~flags)) != 0) {
5942 Report.Error (273, Location,
5943 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
5944 GetSignatureForError (), method.GetSignatureForError ());
5948 protected bool CheckForDuplications ()
5950 if ((caching_flags & Flags.MethodOverloadsExist) == 0)
5953 return Parent.MemberCache.CheckExistingMembersOverloads (this, Name, ParameterInfo, Report);
5957 public PropertyMethod Get, Set;
5958 public PropertyBuilder PropertyBuilder;
5959 public MethodBuilder GetBuilder, SetBuilder;
5961 protected bool define_set_first = false;
5963 public PropertyBase (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags,
5964 Modifiers allowed_mod, MemberName name,
5965 Attributes attrs, bool define_set_first)
5966 : base (parent, null, type, mod_flags, allowed_mod, name, attrs)
5968 this.define_set_first = define_set_first;
5971 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
5973 if (a.HasSecurityAttribute) {
5974 a.Error_InvalidSecurityParent ();
5978 if (a.Type == pa.Dynamic) {
5979 a.Error_MisusedDynamicAttribute ();
5983 PropertyBuilder.SetCustomAttribute (cb);
5986 public override AttributeTargets AttributeTargets {
5988 return AttributeTargets.Property;
5992 protected override void DoMemberTypeDependentChecks ()
5994 base.DoMemberTypeDependentChecks ();
5998 if (MemberType.IsGenericParameter)
6002 if ((MemberType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
6003 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
6007 protected override void DoMemberTypeIndependentChecks ()
6009 base.DoMemberTypeIndependentChecks ();
6012 // Accessors modifiers check
6014 if ((Get.ModFlags & Modifiers.AccessibilityMask) != 0 &&
6015 (Set.ModFlags & Modifiers.AccessibilityMask) != 0) {
6016 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
6017 GetSignatureForError ());
6020 if ((ModFlags & Modifiers.OVERRIDE) == 0 &&
6021 (Get.IsDummy && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) ||
6022 (Set.IsDummy && (Get.ModFlags & Modifiers.AccessibilityMask) != 0)) {
6023 Report.Error (276, Location,
6024 "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
6025 GetSignatureForError ());
6031 GetBuilder = Get.Define (Parent);
6032 return (Get.IsDummy) ? true : GetBuilder != null;
6035 bool DefineSet (bool define)
6040 SetBuilder = Set.Define (Parent);
6041 return (Set.IsDummy) ? true : SetBuilder != null;
6044 protected bool DefineAccessors ()
6046 return DefineSet (define_set_first) &&
6048 DefineSet (!define_set_first);
6051 protected abstract PropertyInfo ResolveBaseProperty ();
6053 // TODO: rename to Resolve......
6054 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
6056 PropertyInfo base_property = ResolveBaseProperty ();
6057 if (base_property == null)
6060 base_ret_type = base_property.PropertyType;
6061 MethodInfo get_accessor = base_property.GetGetMethod (true);
6062 MethodInfo set_accessor = base_property.GetSetMethod (true);
6063 MethodAttributes get_accessor_access = 0, set_accessor_access = 0;
6066 // Check base property accessors conflict
6068 if ((ModFlags & (Modifiers.OVERRIDE | Modifiers.NEW)) == Modifiers.OVERRIDE) {
6069 if (get_accessor == null) {
6070 if (Get != null && !Get.IsDummy) {
6071 Report.SymbolRelatedToPreviousError (base_property);
6072 Report.Error (545, Location,
6073 "`{0}.get': cannot override because `{1}' does not have an overridable get accessor",
6074 GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6077 get_accessor_access = get_accessor.Attributes & MethodAttributes.MemberAccessMask;
6079 if (!Get.IsDummy && !CheckAccessModifiers (
6080 ModifiersExtensions.MethodAttr (Get.ModFlags) & MethodAttributes.MemberAccessMask, get_accessor_access, get_accessor))
6081 Error_CannotChangeAccessModifiers (Get.Location, get_accessor, get_accessor_access, ".get");
6084 if (set_accessor == null) {
6085 if (Set != null && !Set.IsDummy) {
6086 Report.SymbolRelatedToPreviousError (base_property);
6087 Report.Error (546, Location,
6088 "`{0}.set': cannot override because `{1}' does not have an overridable set accessor",
6089 GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6092 set_accessor_access = set_accessor.Attributes & MethodAttributes.MemberAccessMask;
6094 if (!Set.IsDummy && !CheckAccessModifiers (
6095 ModifiersExtensions.MethodAttr (Set.ModFlags) & MethodAttributes.MemberAccessMask, set_accessor_access, set_accessor))
6096 Error_CannotChangeAccessModifiers (Set.Location, set_accessor, set_accessor_access, ".set");
6100 // When one accessor does not exist and property hides base one
6101 // we need to propagate this upwards
6102 if (set_accessor == null)
6103 set_accessor = get_accessor;
6106 // Get the less restrictive access
6108 return get_accessor_access > set_accessor_access ? get_accessor : set_accessor;
6111 public override void Emit ()
6114 // The PropertyBuilder can be null for explicit implementations, in that
6115 // case, we do not actually emit the ".property", so there is nowhere to
6116 // put the attribute
6118 if (PropertyBuilder != null) {
6119 if (OptAttributes != null)
6120 OptAttributes.Emit ();
6122 if (TypeManager.IsDynamicType (member_type)) {
6123 PredefinedAttributes.Get.Dynamic.EmitAttribute (PropertyBuilder);
6125 var trans_flags = TypeManager.HasDynamicTypeUsed (member_type);
6126 if (trans_flags != null) {
6127 var pa = PredefinedAttributes.Get.DynamicTransform;
6128 if (pa.Constructor != null || pa.ResolveConstructor (Location, TypeManager.bool_type.MakeArrayType ())) {
6129 PropertyBuilder.SetCustomAttribute (
6130 new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
6146 /// Tests whether accessors are not in collision with some method (CS0111)
6148 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6150 return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
6153 public override bool IsUsed
6159 return Get.IsUsed | Set.IsUsed;
6163 protected override void SetMemberName (MemberName new_name)
6165 base.SetMemberName (new_name);
6167 Get.UpdateName (this);
6168 Set.UpdateName (this);
6171 public override string[] ValidAttributeTargets {
6173 return attribute_targets;
6178 // Represents header string for documentation comment.
6180 public override string DocCommentHeader {
6181 get { return "P:"; }
6185 public class Property : PropertyBase
6187 public sealed class BackingField : Field
6189 readonly Property property;
6191 public BackingField (Property p)
6192 : base (p.Parent, p.type_name,
6193 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
6194 new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
6199 public override string GetSignatureForError ()
6201 return property.GetSignatureForError ();
6205 const Modifiers AllowedModifiers =
6208 Modifiers.PROTECTED |
6209 Modifiers.INTERNAL |
6213 Modifiers.OVERRIDE |
6214 Modifiers.ABSTRACT |
6219 const Modifiers AllowedInterfaceModifiers =
6222 public Property (DeclSpace parent, FullNamedExpression type, Modifiers mod,
6223 MemberName name, Attributes attrs, Accessor get_block,
6224 Accessor set_block, bool define_set_first)
6225 : this (parent, type, mod, name, attrs, get_block, set_block,
6226 define_set_first, null)
6230 public Property (DeclSpace parent, FullNamedExpression type, Modifiers mod,
6231 MemberName name, Attributes attrs, Accessor get_block,
6232 Accessor set_block, bool define_set_first, Block current_block)
6233 : base (parent, type, mod,
6234 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
6235 name, attrs, define_set_first)
6237 if (get_block == null)
6238 Get = new GetMethod (this);
6240 Get = new GetMethod (this, get_block);
6242 if (set_block == null)
6243 Set = new SetMethod (this);
6245 Set = new SetMethod (this, set_block);
6247 if (!IsInterface && (mod & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
6248 get_block != null && get_block.Block == null &&
6249 set_block != null && set_block.Block == null) {
6250 if (RootContext.Version <= LanguageVersion.ISO_2)
6251 Report.FeatureIsNotAvailable (Location, "automatically implemented properties");
6253 Get.ModFlags |= Modifiers.COMPILER_GENERATED;
6254 Set.ModFlags |= Modifiers.COMPILER_GENERATED;
6258 void CreateAutomaticProperty ()
6260 // Create backing field
6261 Field field = new BackingField (this);
6262 if (!field.Define ())
6265 Parent.PartialContainer.AddField (field);
6267 FieldExpr fe = new FieldExpr (field, Location);
6268 if ((field.ModFlags & Modifiers.STATIC) == 0)
6269 fe.InstanceExpression = new CompilerGeneratedThis (fe.Type, Location);
6272 Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
6273 Return r = new Return (fe, Location);
6274 Get.Block.AddStatement (r);
6277 Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location);
6278 Assign a = new SimpleAssign (fe, new SimpleName ("value", Location));
6279 Set.Block.AddStatement (new StatementExpression (a));
6282 public override bool Define ()
6284 if (!base.Define ())
6287 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6289 if ((Get.ModFlags & Modifiers.COMPILER_GENERATED) != 0)
6290 CreateAutomaticProperty ();
6292 if (!DefineAccessors ())
6298 // FIXME - PropertyAttributes.HasDefault ?
6300 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6301 GetFullName (MemberName), PropertyAttributes.None, MemberType, null);
6304 PropertyBuilder.SetGetMethod (GetBuilder);
6305 Parent.MemberCache.AddMember (GetBuilder, Get);
6309 PropertyBuilder.SetSetMethod (SetBuilder);
6310 Parent.MemberCache.AddMember (SetBuilder, Set);
6313 TypeManager.RegisterProperty (PropertyBuilder, this);
6314 Parent.MemberCache.AddMember (PropertyBuilder, this);
6318 public override void Emit ()
6320 if (((Set.ModFlags | Get.ModFlags) & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) {
6321 Report.Error (842, Location,
6322 "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
6323 GetSignatureForError ());
6329 protected override PropertyInfo ResolveBaseProperty ()
6331 return Parent.PartialContainer.BaseCache.FindMemberToOverride (
6332 Parent.TypeBuilder, Name, ParametersCompiled.EmptyReadOnlyParameters, null, true) as PropertyInfo;
6337 /// Gigantic workaround for lameness in SRE follows :
6338 /// This class derives from EventInfo and attempts to basically
6339 /// wrap around the EventBuilder so that FindMembers can quickly
6340 /// return this in it search for members
6342 public class MyEventBuilder : EventInfo {
6345 // We use this to "point" to our Builder which is
6346 // not really a MemberInfo
6348 EventBuilder MyBuilder;
6351 // We "catch" and wrap these methods
6353 MethodInfo raise, remove, add;
6355 EventAttributes attributes;
6356 Type declaring_type, reflected_type, event_type;
6361 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
6363 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
6365 // And now store the values in our own fields.
6367 declaring_type = type_builder;
6369 reflected_type = type_builder;
6371 attributes = event_attr;
6374 this.event_type = event_type;
6378 // Methods that you have to override. Note that you only need
6379 // to "implement" the variants that take the argument (those are
6380 // the "abstract" methods, the others (GetAddMethod()) are
6383 public override MethodInfo GetAddMethod (bool nonPublic)
6388 public override MethodInfo GetRemoveMethod (bool nonPublic)
6393 public override MethodInfo GetRaiseMethod (bool nonPublic)
6399 // These methods make "MyEventInfo" look like a Builder
6401 public void SetRaiseMethod (MethodBuilder raiseMethod)
6403 raise = raiseMethod;
6404 MyBuilder.SetRaiseMethod (raiseMethod);
6407 public void SetRemoveOnMethod (MethodBuilder removeMethod)
6409 remove = removeMethod;
6410 MyBuilder.SetRemoveOnMethod (removeMethod);
6413 public void SetAddOnMethod (MethodBuilder addMethod)
6416 MyBuilder.SetAddOnMethod (addMethod);
6419 public void SetCustomAttribute (CustomAttributeBuilder cb)
6421 MyBuilder.SetCustomAttribute (cb);
6424 public override object [] GetCustomAttributes (bool inherit)
6426 // FIXME : There's nothing which can be seemingly done here because
6427 // we have no way of getting at the custom attribute objects of the
6432 public override object [] GetCustomAttributes (Type t, bool inherit)
6434 // FIXME : Same here !
6438 public override bool IsDefined (Type t, bool b)
6443 public override EventAttributes Attributes {
6449 public override string Name {
6455 public override Type DeclaringType {
6457 return declaring_type;
6461 public override Type ReflectedType {
6463 return reflected_type;
6467 public Type EventType {
6473 public void SetUsed ()
6475 if (my_event != null) {
6476 // my_event.SetAssigned ();
6477 my_event.SetMemberIsUsed ();
6483 /// For case when event is declared like property (with add and remove accessors).
6485 public class EventProperty: Event {
6486 abstract class AEventPropertyAccessor : AEventAccessor
6488 protected AEventPropertyAccessor (EventProperty method, Accessor accessor, string prefix)
6489 : base (method, accessor, prefix)
6493 public override MethodBuilder Define (DeclSpace ds)
6495 CheckAbstractAndExtern (block != null);
6496 return base.Define (ds);
6499 public override string GetSignatureForError ()
6501 return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1);
6505 sealed class AddDelegateMethod: AEventPropertyAccessor
6507 public AddDelegateMethod (EventProperty method, Accessor accessor):
6508 base (method, accessor, AddPrefix)
6513 sealed class RemoveDelegateMethod: AEventPropertyAccessor
6515 public RemoveDelegateMethod (EventProperty method, Accessor accessor):
6516 base (method, accessor, RemovePrefix)
6522 static readonly string[] attribute_targets = new string [] { "event" }; // "property" target was disabled for 2.0 version
6524 public EventProperty (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags,
6526 Attributes attrs, Accessor add, Accessor remove)
6527 : base (parent, type, mod_flags, name, attrs)
6529 Add = new AddDelegateMethod (this, add);
6530 Remove = new RemoveDelegateMethod (this, remove);
6533 public override bool Define()
6535 if (!base.Define ())
6542 public override string[] ValidAttributeTargets {
6544 return attribute_targets;
6550 /// Event is declared like field.
6552 public class EventField : Event {
6553 abstract class EventFieldAccessor : AEventAccessor
6555 protected EventFieldAccessor (EventField method, string prefix)
6556 : base (method, prefix)
6560 public override void Emit (DeclSpace parent)
6562 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
6563 if (parent is Class) {
6564 MethodBuilder mb = method_data.MethodBuilder;
6565 mb.SetImplementationFlags (mb.GetMethodImplementationFlags () | MethodImplAttributes.Synchronized);
6568 var field_info = ((EventField) method).BackingField;
6569 FieldExpr f_expr = new FieldExpr (field_info, Location);
6570 if ((method.ModFlags & Modifiers.STATIC) == 0)
6571 f_expr.InstanceExpression = new CompilerGeneratedThis (field_info.Spec.FieldType, Location);
6573 block = new ToplevelBlock (Compiler, ParameterInfo, Location);
6574 block.AddStatement (new StatementExpression (
6575 new CompoundAssign (Operation,
6577 block.GetParameterReference (ParameterInfo[0].Name, Location))));
6583 protected abstract Binary.Operator Operation { get; }
6586 sealed class AddDelegateMethod: EventFieldAccessor
6588 public AddDelegateMethod (EventField method):
6589 base (method, AddPrefix)
6593 protected override Binary.Operator Operation {
6594 get { return Binary.Operator.Addition; }
6598 sealed class RemoveDelegateMethod: EventFieldAccessor
6600 public RemoveDelegateMethod (EventField method):
6601 base (method, RemovePrefix)
6605 protected override Binary.Operator Operation {
6606 get { return Binary.Operator.Subtraction; }
6611 static readonly string[] attribute_targets = new string [] { "event", "field", "method" };
6612 static readonly string[] attribute_targets_interface = new string[] { "event", "method" };
6614 public Field BackingField;
6615 public Expression Initializer;
6617 public EventField (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
6618 : base (parent, type, mod_flags, name, attrs)
6620 Add = new AddDelegateMethod (this);
6621 Remove = new RemoveDelegateMethod (this);
6624 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6626 if (a.Target == AttributeTargets.Field) {
6627 BackingField.ApplyAttributeBuilder (a, cb, pa);
6631 if (a.Target == AttributeTargets.Method) {
6632 int errors = Report.Errors;
6633 Add.ApplyAttributeBuilder (a, cb, pa);
6634 if (errors == Report.Errors)
6635 Remove.ApplyAttributeBuilder (a, cb, pa);
6639 base.ApplyAttributeBuilder (a, cb, pa);
6642 public override bool Define()
6644 if (!base.Define ())
6647 if (Initializer != null && (ModFlags & Modifiers.ABSTRACT) != 0) {
6648 Report.Error (74, Location, "`{0}': abstract event cannot have an initializer",
6649 GetSignatureForError ());
6652 if (!HasBackingField) {
6657 // FIXME: We are unable to detect whether generic event is used because
6658 // we are using FieldExpr instead of EventExpr for event access in that
6659 // case. When this issue will be fixed this hack can be removed.
6660 if (TypeManager.IsGenericType (MemberType) || Parent.IsGeneric)
6663 if (Add.IsInterfaceImplementation)
6666 TypeManager.RegisterEventField (EventBuilder, this);
6668 BackingField = new Field (Parent,
6669 new TypeExpression (MemberType, Location),
6670 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
6673 Parent.PartialContainer.AddField (BackingField);
6674 BackingField.Initializer = Initializer;
6675 BackingField.ModFlags &= ~Modifiers.COMPILER_GENERATED;
6677 // Call define because we passed fields definition
6678 return BackingField.Define ();
6681 bool HasBackingField {
6683 return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0;
6687 public override string[] ValidAttributeTargets
6690 return HasBackingField ? attribute_targets : attribute_targets_interface;
6695 public abstract class Event : PropertyBasedMember {
6696 public abstract class AEventAccessor : AbstractPropertyEventMethod
6698 protected readonly Event method;
6699 ImplicitParameter param_attr;
6701 static readonly string[] attribute_targets = new string [] { "method", "param", "return" };
6703 public const string AddPrefix = "add_";
6704 public const string RemovePrefix = "remove_";
6706 protected AEventAccessor (Event method, string prefix)
6707 : base (method, prefix)
6709 this.method = method;
6710 this.ModFlags = method.ModFlags;
6713 protected AEventAccessor (Event method, Accessor accessor, string prefix)
6714 : base (method, accessor, prefix)
6716 this.method = method;
6717 this.ModFlags = method.ModFlags;
6720 public bool IsInterfaceImplementation {
6721 get { return method_data.implementing != null; }
6724 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6726 if (a.IsInternalMethodImplAttribute) {
6727 method.is_external_implementation = true;
6730 base.ApplyAttributeBuilder (a, cb, pa);
6733 protected override void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6735 if (a.Target == AttributeTargets.Parameter) {
6736 if (param_attr == null)
6737 param_attr = new ImplicitParameter (method_data.MethodBuilder);
6739 param_attr.ApplyAttributeBuilder (a, cb, pa);
6743 base.ApplyAttributeBuilder (a, cb, pa);
6746 public override AttributeTargets AttributeTargets {
6748 return AttributeTargets.Method;
6752 public override bool IsClsComplianceRequired ()
6754 return method.IsClsComplianceRequired ();
6757 public virtual MethodBuilder Define (DeclSpace parent)
6759 method_data = new MethodData (method, method.ModFlags,
6760 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
6762 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
6765 MethodBuilder mb = method_data.MethodBuilder;
6766 ParameterInfo.ApplyAttributes (mb);
6770 public override Type ReturnType {
6772 return TypeManager.void_type;
6776 public override ObsoleteAttribute GetObsoleteAttribute ()
6778 return method.GetObsoleteAttribute ();
6781 public override string[] ValidAttributeTargets {
6783 return attribute_targets;
6787 public override ParametersCompiled ParameterInfo {
6789 return method.parameters;
6795 const Modifiers AllowedModifiers =
6798 Modifiers.PROTECTED |
6799 Modifiers.INTERNAL |
6804 Modifiers.OVERRIDE |
6806 Modifiers.ABSTRACT |
6809 const Modifiers AllowedInterfaceModifiers =
6812 public AEventAccessor Add, Remove;
6813 public MyEventBuilder EventBuilder;
6814 public MethodBuilder AddBuilder, RemoveBuilder;
6816 ParametersCompiled parameters;
6818 protected Event (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
6819 : base (parent, null, type, mod_flags,
6820 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
6825 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
6827 if ((a.HasSecurityAttribute)) {
6828 a.Error_InvalidSecurityParent ();
6832 EventBuilder.SetCustomAttribute (cb);
6835 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6837 return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
6840 public override AttributeTargets AttributeTargets {
6842 return AttributeTargets.Event;
6846 public override bool Define ()
6848 if (!base.Define ())
6851 if (!TypeManager.IsDelegateType (MemberType)) {
6852 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
6855 parameters = ParametersCompiled.CreateFullyResolved (
6856 new Parameter (null, "value", Parameter.Modifier.NONE, null, Location), MemberType);
6861 if (TypeManager.delegate_combine_delegate_delegate == null) {
6862 TypeManager.delegate_combine_delegate_delegate = TypeManager.GetPredefinedMethod (
6863 TypeManager.delegate_type, "Combine", Location,
6864 TypeManager.delegate_type, TypeManager.delegate_type);
6866 if (TypeManager.delegate_remove_delegate_delegate == null) {
6867 TypeManager.delegate_remove_delegate_delegate = TypeManager.GetPredefinedMethod (
6868 TypeManager.delegate_type, "Remove", Location,
6869 TypeManager.delegate_type, TypeManager.delegate_type);
6873 // Now define the accessors
6876 AddBuilder = Add.Define (Parent);
6877 if (AddBuilder == null)
6880 RemoveBuilder = Remove.Define (Parent);
6881 if (RemoveBuilder == null)
6884 EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, EventAttributes.None, MemberType);
6885 EventBuilder.SetAddOnMethod (AddBuilder);
6886 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
6888 Parent.MemberCache.AddMember (EventBuilder, this);
6889 Parent.MemberCache.AddMember (AddBuilder, Add);
6890 Parent.MemberCache.AddMember (RemoveBuilder, Remove);
6895 public override void Emit ()
6897 if (OptAttributes != null) {
6898 OptAttributes.Emit ();
6902 Remove.Emit (Parent);
6907 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
6909 MethodInfo mi = (MethodInfo) Parent.PartialContainer.BaseCache.FindBaseEvent (
6910 Parent.TypeBuilder, Name);
6915 AParametersCollection pd = TypeManager.GetParameterData (mi);
6916 base_ret_type = pd.Types [0];
6921 // Represents header string for documentation comment.
6923 public override string DocCommentHeader {
6924 get { return "E:"; }
6929 public class Indexer : PropertyBase
6931 public class GetIndexerMethod : GetMethod
6933 ParametersCompiled parameters;
6935 public GetIndexerMethod (Indexer method):
6938 this.parameters = method.parameters;
6941 public GetIndexerMethod (PropertyBase method, Accessor accessor):
6942 base (method, accessor)
6944 parameters = accessor.Parameters;
6947 public override MethodBuilder Define (DeclSpace parent)
6949 parameters.Resolve (this);
6950 return base.Define (parent);
6953 public override bool EnableOverloadChecks (MemberCore overload)
6955 if (base.EnableOverloadChecks (overload)) {
6956 overload.caching_flags |= Flags.MethodOverloadsExist;
6963 public override ParametersCompiled ParameterInfo {
6970 public class SetIndexerMethod: SetMethod
6972 public SetIndexerMethod (Indexer method):
6975 parameters = ParametersCompiled.MergeGenerated (Compiler, method.parameters, false, parameters [0], null);
6978 public SetIndexerMethod (PropertyBase method, Accessor accessor):
6979 base (method, accessor)
6981 parameters = method.Get.IsDummy ? accessor.Parameters : accessor.Parameters.Clone ();
6984 public override bool EnableOverloadChecks (MemberCore overload)
6986 if (base.EnableOverloadChecks (overload)) {
6987 overload.caching_flags |= Flags.MethodOverloadsExist;
6995 const Modifiers AllowedModifiers =
6998 Modifiers.PROTECTED |
6999 Modifiers.INTERNAL |
7003 Modifiers.OVERRIDE |
7008 const Modifiers AllowedInterfaceModifiers =
7011 public readonly ParametersCompiled parameters;
7013 public Indexer (DeclSpace parent, FullNamedExpression type, MemberName name, Modifiers mod,
7014 ParametersCompiled parameters, Attributes attrs,
7015 Accessor get_block, Accessor set_block, bool define_set_first)
7016 : base (parent, type, mod,
7017 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
7018 name, attrs, define_set_first)
7020 this.parameters = parameters;
7022 if (get_block == null)
7023 Get = new GetIndexerMethod (this);
7025 Get = new GetIndexerMethod (this, get_block);
7027 if (set_block == null)
7028 Set = new SetIndexerMethod (this);
7030 Set = new SetIndexerMethod (this, set_block);
7033 protected override bool CheckForDuplications ()
7035 return Parent.MemberCache.CheckExistingMembersOverloads (this, GetFullName (MemberName), parameters, Report);
7038 public override bool Define ()
7040 if (!base.Define ())
7043 if (!DefineParameters (parameters))
7046 if (OptAttributes != null) {
7047 Attribute indexer_attr = OptAttributes.Search (PredefinedAttributes.Get.IndexerName);
7048 if (indexer_attr != null) {
7049 // Remove the attribute from the list because it is not emitted
7050 OptAttributes.Attrs.Remove (indexer_attr);
7052 string name = indexer_attr.GetIndexerAttributeValue ();
7058 if (IsExplicitImpl) {
7059 Report.Error (415, indexer_attr.Location,
7060 "The `IndexerName' attribute is valid only on an " +
7061 "indexer that is not an explicit interface member declaration");
7065 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
7066 Report.Error (609, indexer_attr.Location,
7067 "Cannot set the `IndexerName' attribute on an indexer marked override");
7073 if (InterfaceType != null) {
7074 string base_IndexerName = TypeManager.IndexerPropertyName (InterfaceType);
7075 if (base_IndexerName != Name)
7076 ShortName = base_IndexerName;
7079 if (!Parent.PartialContainer.AddMember (this) ||
7080 !Parent.PartialContainer.AddMember (Get) || !Parent.PartialContainer.AddMember (Set))
7083 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
7085 if (!DefineAccessors ())
7092 // Now name the parameters
7094 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
7095 GetFullName (MemberName), PropertyAttributes.None, MemberType, parameters.GetEmitTypes ());
7098 PropertyBuilder.SetGetMethod (GetBuilder);
7099 Parent.MemberCache.AddMember (GetBuilder, Get);
7103 PropertyBuilder.SetSetMethod (SetBuilder);
7104 Parent.MemberCache.AddMember (SetBuilder, Set);
7107 TypeManager.RegisterIndexer (PropertyBuilder, parameters);
7108 Parent.MemberCache.AddMember (PropertyBuilder, this);
7112 public override bool EnableOverloadChecks (MemberCore overload)
7114 if (overload is Indexer) {
7115 caching_flags |= Flags.MethodOverloadsExist;
7119 return base.EnableOverloadChecks (overload);
7122 public override string GetDocCommentName (DeclSpace ds)
7124 return DocUtil.GetMethodDocCommentName (this, parameters, ds);
7127 public override string GetSignatureForError ()
7129 StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
7130 if (MemberName.Left != null) {
7132 sb.Append (MemberName.Left.GetSignatureForError ());
7135 sb.Append (".this");
7136 sb.Append (parameters.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
7137 return sb.ToString ();
7140 protected override PropertyInfo ResolveBaseProperty ()
7142 return Parent.PartialContainer.BaseCache.FindMemberToOverride (
7143 Parent.TypeBuilder, Name, parameters, null, true) as PropertyInfo;
7146 protected override bool VerifyClsCompliance ()
7148 if (!base.VerifyClsCompliance ())
7151 parameters.VerifyClsCompliance (this);
7156 public class Operator : MethodOrOperator {
7158 const Modifiers AllowedModifiers =
7164 public enum OpType : byte {
7174 // Unary and Binary operators
7197 // Implicit and Explicit
7201 // Just because of enum
7205 public readonly OpType OperatorType;
7207 static readonly string [] [] names;
7211 names = new string[(int)OpType.TOP][];
7212 names [(int) OpType.LogicalNot] = new string [] { "!", "op_LogicalNot" };
7213 names [(int) OpType.OnesComplement] = new string [] { "~", "op_OnesComplement" };
7214 names [(int) OpType.Increment] = new string [] { "++", "op_Increment" };
7215 names [(int) OpType.Decrement] = new string [] { "--", "op_Decrement" };
7216 names [(int) OpType.True] = new string [] { "true", "op_True" };
7217 names [(int) OpType.False] = new string [] { "false", "op_False" };
7218 names [(int) OpType.Addition] = new string [] { "+", "op_Addition" };
7219 names [(int) OpType.Subtraction] = new string [] { "-", "op_Subtraction" };
7220 names [(int) OpType.UnaryPlus] = new string [] { "+", "op_UnaryPlus" };
7221 names [(int) OpType.UnaryNegation] = new string [] { "-", "op_UnaryNegation" };
7222 names [(int) OpType.Multiply] = new string [] { "*", "op_Multiply" };
7223 names [(int) OpType.Division] = new string [] { "/", "op_Division" };
7224 names [(int) OpType.Modulus] = new string [] { "%", "op_Modulus" };
7225 names [(int) OpType.BitwiseAnd] = new string [] { "&", "op_BitwiseAnd" };
7226 names [(int) OpType.BitwiseOr] = new string [] { "|", "op_BitwiseOr" };
7227 names [(int) OpType.ExclusiveOr] = new string [] { "^", "op_ExclusiveOr" };
7228 names [(int) OpType.LeftShift] = new string [] { "<<", "op_LeftShift" };
7229 names [(int) OpType.RightShift] = new string [] { ">>", "op_RightShift" };
7230 names [(int) OpType.Equality] = new string [] { "==", "op_Equality" };
7231 names [(int) OpType.Inequality] = new string [] { "!=", "op_Inequality" };
7232 names [(int) OpType.GreaterThan] = new string [] { ">", "op_GreaterThan" };
7233 names [(int) OpType.LessThan] = new string [] { "<", "op_LessThan" };
7234 names [(int) OpType.GreaterThanOrEqual] = new string [] { ">=", "op_GreaterThanOrEqual" };
7235 names [(int) OpType.LessThanOrEqual] = new string [] { "<=", "op_LessThanOrEqual" };
7236 names [(int) OpType.Implicit] = new string [] { "implicit", "op_Implicit" };
7237 names [(int) OpType.Explicit] = new string [] { "explicit", "op_Explicit" };
7240 public Operator (DeclSpace parent, OpType type, FullNamedExpression ret_type,
7241 Modifiers mod_flags, ParametersCompiled parameters,
7242 ToplevelBlock block, Attributes attrs, Location loc)
7243 : base (parent, null, ret_type, mod_flags, AllowedModifiers,
7244 new MemberName (GetMetadataName (type), loc), attrs, parameters)
7246 OperatorType = type;
7250 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
7252 if (a.Type == pa.Conditional) {
7253 Error_ConditionalAttributeIsNotValid ();
7257 base.ApplyAttributeBuilder (a, cb, pa);
7260 public override bool Define ()
7262 const Modifiers RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
7263 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
7264 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
7267 if (!base.Define ())
7270 // imlicit and explicit operator of same types are not allowed
7271 if (OperatorType == OpType.Explicit)
7272 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Implicit), Parameters, Report);
7273 else if (OperatorType == OpType.Implicit)
7274 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Explicit), Parameters, Report);
7276 Type declaring_type = MethodData.DeclaringType;
7277 Type return_type = MemberType;
7278 Type first_arg_type = ParameterTypes [0];
7280 Type first_arg_type_unwrap = first_arg_type;
7281 if (TypeManager.IsNullableType (first_arg_type))
7282 first_arg_type_unwrap = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (first_arg_type) [0]);
7284 Type return_type_unwrap = return_type;
7285 if (TypeManager.IsNullableType (return_type))
7286 return_type_unwrap = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (return_type) [0]);
7288 if (TypeManager.IsDynamicType (return_type) || TypeManager.IsDynamicType (first_arg_type)) {
7289 Report.Error (1964, Location,
7290 "User-defined operator `{0}' cannot convert to or from the dynamic type",
7291 GetSignatureForError ());
7297 // Rules for conversion operators
7299 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7300 if (first_arg_type_unwrap == return_type_unwrap && first_arg_type_unwrap == declaring_type){
7301 Report.Error (555, Location,
7302 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
7307 if (TypeManager.IsEqual (declaring_type, return_type) || declaring_type == return_type_unwrap) {
7308 conv_type = first_arg_type;
7309 } else if (TypeManager.IsEqual (declaring_type, first_arg_type) || declaring_type == first_arg_type_unwrap) {
7310 conv_type = return_type;
7312 Report.Error (556, Location,
7313 "User-defined conversion must convert to or from the enclosing type");
7318 // Because IsInterface and IsClass are not supported
7320 if (!TypeManager.IsGenericParameter (conv_type)) {
7321 if (conv_type.IsInterface) {
7322 Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
7323 GetSignatureForError ());
7327 if (conv_type.IsClass) {
7328 if (TypeManager.IsSubclassOf (declaring_type, conv_type)) {
7329 Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from a base class",
7330 GetSignatureForError ());
7334 if (TypeManager.IsSubclassOf (conv_type, declaring_type)) {
7335 Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from a derived class",
7336 GetSignatureForError ());
7341 } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
7342 if (first_arg_type != declaring_type || Parameters.Types [1] != TypeManager.int32_type) {
7343 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");
7346 } else if (Parameters.Count == 1) {
7347 // Checks for Unary operators
7349 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
7350 if (return_type != declaring_type && !TypeManager.IsSubclassOf (return_type, declaring_type)) {
7351 Report.Error (448, Location,
7352 "The return type for ++ or -- operator must be the containing type or derived from the containing type");
7355 if (first_arg_type != declaring_type) {
7357 559, Location, "The parameter type for ++ or -- operator must be the containing type");
7362 if (!TypeManager.IsEqual (first_arg_type_unwrap, declaring_type)){
7363 Report.Error (562, Location,
7364 "The parameter type of a unary operator must be the containing type");
7368 if (OperatorType == OpType.True || OperatorType == OpType.False) {
7369 if (return_type != TypeManager.bool_type){
7372 "The return type of operator True or False " +
7378 } else if (!TypeManager.IsEqual (first_arg_type_unwrap, declaring_type)) {
7379 // Checks for Binary operators
7381 var second_arg_type = ParameterTypes [1];
7382 if (TypeManager.IsNullableType (second_arg_type))
7383 second_arg_type = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (second_arg_type) [0]);
7385 if (!TypeManager.IsEqual (second_arg_type, declaring_type)) {
7386 Report.Error (563, Location,
7387 "One of the parameters of a binary operator must be the containing type");
7395 protected override bool ResolveMemberType ()
7397 if (!base.ResolveMemberType ())
7400 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
7404 // Operator cannot be override
7405 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
7410 public static string GetName (OpType ot)
7412 return names [(int) ot] [0];
7415 public static string GetName (string metadata_name)
7417 for (int i = 0; i < names.Length; ++i) {
7418 if (names [i] [1] == metadata_name)
7419 return names [i] [0];
7424 public static string GetMetadataName (OpType ot)
7426 return names [(int) ot] [1];
7429 public static string GetMetadataName (string name)
7431 for (int i = 0; i < names.Length; ++i) {
7432 if (names [i] [0] == name)
7433 return names [i] [1];
7438 public OpType GetMatchingOperator ()
7440 switch (OperatorType) {
7441 case OpType.Equality:
7442 return OpType.Inequality;
7443 case OpType.Inequality:
7444 return OpType.Equality;
7446 return OpType.False;
7449 case OpType.GreaterThan:
7450 return OpType.LessThan;
7451 case OpType.LessThan:
7452 return OpType.GreaterThan;
7453 case OpType.GreaterThanOrEqual:
7454 return OpType.LessThanOrEqual;
7455 case OpType.LessThanOrEqual:
7456 return OpType.GreaterThanOrEqual;
7462 public override string GetSignatureForError ()
7464 StringBuilder sb = new StringBuilder ();
7465 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7466 sb.AppendFormat ("{0}.{1} operator {2}",
7467 Parent.GetSignatureForError (), GetName (OperatorType), type_name.GetSignatureForError ());
7470 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
7473 sb.Append (Parameters.GetSignatureForError ());
7474 return sb.ToString ();
7479 // This is used to compare method signatures
7481 struct MethodSignature {
7483 public Type RetType;
7484 public Type [] Parameters;
7487 /// This delegate is used to extract methods which have the
7488 /// same signature as the argument
7490 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
7492 public MethodSignature (string name, Type ret_type, Type [] parameters)
7497 if (parameters == null)
7498 Parameters = Type.EmptyTypes;
7500 Parameters = parameters;
7503 public override string ToString ()
7506 if (Parameters.Length != 0){
7507 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
7508 for (int i = 0; i < Parameters.Length; i++){
7509 sb.Append (Parameters [i]);
7510 if (i+1 < Parameters.Length)
7513 pars = sb.ToString ();
7516 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
7519 public override int GetHashCode ()
7521 return Name.GetHashCode ();
7524 public override bool Equals (Object o)
7526 MethodSignature other = (MethodSignature) o;
7528 if (other.Name != Name)
7531 if (other.RetType != RetType)
7534 if (Parameters == null){
7535 if (other.Parameters == null)
7540 if (other.Parameters == null)
7543 int c = Parameters.Length;
7544 if (other.Parameters.Length != c)
7547 for (int i = 0; i < c; i++)
7548 if (other.Parameters [i] != Parameters [i])
7554 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
7556 MethodSignature sig = (MethodSignature) filter_criteria;
7558 if (m.Name != sig.Name)
7562 MethodInfo mi = m as MethodInfo;
7563 PropertyInfo pi = m as PropertyInfo;
7566 ReturnType = mi.ReturnType;
7567 else if (pi != null)
7568 ReturnType = pi.PropertyType;
7573 // we use sig.RetType == null to mean `do not check the
7574 // method return value.
7576 if (sig.RetType != null) {
7577 if (!TypeManager.IsEqual (ReturnType, sig.RetType))
7583 args = TypeManager.GetParameterData (mi).Types;
7585 args = TypeManager.GetParameterData (pi).Types;
7586 Type [] sigp = sig.Parameters;
7588 if (args.Length != sigp.Length)
7591 for (int i = args.Length - 1; i >= 0; i--)
7592 if (!TypeManager.IsEqual (args [i], sigp [i]))