2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / class.cs
blob9923f91607799cf0cb503fa0c206fc26db0d756d
1 //
2 // class.cs: Class and Struct handlers
3 //
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
7 //
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 //
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2008 Novell, Inc
14 using System;
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;
22 using System.Text;
24 #if NET_2_1
25 using XmlElement = System.Object;
26 #else
27 using System.Xml;
28 #endif
30 using Mono.CompilerServices.SymbolWriter;
32 namespace Mono.CSharp {
34 /// <summary>
35 /// This is the base class for structs and classes.
36 /// </summary>
37 public abstract class TypeContainer : DeclSpace, IMemberContainer
40 // Different context is needed when resolving type container base
41 // types. Type names come from the parent scope but type parameter
42 // names from the container scope.
44 struct BaseContext : IMemberContext
46 TypeContainer tc;
48 public BaseContext (TypeContainer tc)
50 this.tc = tc;
53 #region IMemberContext Members
55 public CompilerContext Compiler {
56 get { return tc.Compiler; }
59 public Type CurrentType {
60 get { return tc.Parent.CurrentType; }
63 public TypeParameter[] CurrentTypeParameters {
64 get { return tc.PartialContainer.CurrentTypeParameters; }
67 public TypeContainer CurrentTypeDefinition {
68 get { return tc.Parent.CurrentTypeDefinition; }
71 public bool IsObsolete {
72 get { return tc.IsObsolete; }
75 public bool IsUnsafe {
76 get { return tc.IsUnsafe; }
79 public bool IsStatic {
80 get { return tc.IsStatic; }
83 public string GetSignatureForError ()
85 throw new NotImplementedException ();
88 public ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
90 return null;
93 public FullNamedExpression LookupNamespaceAlias (string name)
95 return tc.Parent.LookupNamespaceAlias (name);
98 public FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
100 TypeParameter[] tp = CurrentTypeParameters;
101 if (tp != null) {
102 TypeParameter t = TypeParameter.FindTypeParameter (tp, name);
103 if (t != null)
104 return new TypeParameterExpr (t, loc);
107 return tc.Parent.LookupNamespaceOrType (name, loc, ignore_cs0104);
110 #endregion
113 [Flags]
114 enum CachedMethods
116 Equals = 1,
117 GetHashCode = 1 << 1,
118 HasStaticFieldInitializer = 1 << 2
122 // Whether this is a struct, class or interface
123 public readonly MemberKind Kind;
125 // Holds a list of classes and structures
126 protected List<TypeContainer> types;
128 List<MemberCore> ordered_explicit_member_list;
129 List<MemberCore> ordered_member_list;
131 // Holds the list of properties
132 List<MemberCore> properties;
134 // Holds the list of delegates
135 List<TypeContainer> delegates;
137 // Holds the list of constructors
138 protected List<MemberCore> instance_constructors;
140 // Holds the list of fields
141 protected List<MemberCore> fields;
143 // Holds a list of fields that have initializers
144 protected List<FieldInitializer> initialized_fields;
146 // Holds a list of static fields that have initializers
147 protected List<FieldInitializer> initialized_static_fields;
149 // Holds the list of constants
150 protected List<MemberCore> constants;
152 // Holds the methods.
153 List<MemberCore> methods;
155 // Holds the events
156 protected List<MemberCore> events;
158 // Holds the indexers
159 List<MemberCore> indexers;
161 // Holds the operators
162 List<MemberCore> operators;
164 // Holds the compiler generated classes
165 List<CompilerGeneratedClass> compiler_generated;
168 // Pointers to the default constructor and the default static constructor
170 protected Constructor default_constructor;
171 protected Constructor default_static_constructor;
174 // Points to the first non-static field added to the container.
176 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
177 // and the first one's as good as any.
179 FieldBase first_nonstatic_field = null;
182 // This one is computed after we can distinguish interfaces
183 // from classes from the arraylist `type_bases'
185 TypeExpr base_type;
186 TypeExpr[] iface_exprs;
187 Type GenericType;
188 GenericTypeParameterBuilder[] nested_gen_params;
190 protected List<FullNamedExpression> type_bases;
192 protected bool members_defined;
193 bool members_defined_ok;
195 // The interfaces we implement.
196 protected Type[] ifaces;
198 // The base member cache and our member cache
199 MemberCache base_cache;
200 protected MemberCache member_cache;
202 public const string DefaultIndexerName = "Item";
204 private bool seen_normal_indexers = false;
205 private string indexer_name = DefaultIndexerName;
206 protected bool requires_delayed_unmanagedtype_check;
208 private CachedMethods cached_method;
210 List<TypeContainer> partial_parts;
212 /// <remarks>
213 /// The pending methods that need to be implemented
214 // (interfaces or abstract methods)
215 /// </remarks>
216 PendingImplementation pending;
218 public TypeContainer (NamespaceEntry ns, DeclSpace parent, MemberName name,
219 Attributes attrs, MemberKind kind)
220 : base (ns, parent, name, attrs)
222 if (parent != null && parent.NamespaceEntry != ns)
223 throw new InternalErrorException ("A nested type should be in the same NamespaceEntry as its enclosing class");
225 this.Kind = kind;
226 this.PartialContainer = this;
229 public bool AddMember (MemberCore symbol)
231 return AddToContainer (symbol, symbol.MemberName.Basename);
234 protected virtual bool AddMemberType (DeclSpace ds)
236 return AddToContainer (ds, ds.Basename);
239 protected virtual void RemoveMemberType (DeclSpace ds)
241 RemoveFromContainer (ds.Basename);
244 public void AddConstant (Const constant)
246 if (!AddMember (constant))
247 return;
249 if (constants == null)
250 constants = new List<MemberCore> ();
252 constants.Add (constant);
255 public TypeContainer AddTypeContainer (TypeContainer tc)
257 if (!AddMemberType (tc))
258 return tc;
260 if (types == null)
261 types = new List<TypeContainer> ();
263 types.Add (tc);
264 return tc;
267 public virtual TypeContainer AddPartial (TypeContainer next_part)
269 return AddPartial (next_part, next_part.Basename);
272 protected TypeContainer AddPartial (TypeContainer next_part, string name)
274 next_part.ModFlags |= Modifiers.PARTIAL;
275 TypeContainer tc = GetDefinition (name) as TypeContainer;
276 if (tc == null)
277 return AddTypeContainer (next_part);
279 if ((tc.ModFlags & Modifiers.PARTIAL) == 0) {
280 Report.SymbolRelatedToPreviousError (next_part);
281 Error_MissingPartialModifier (tc);
284 if (tc.Kind != next_part.Kind) {
285 Report.SymbolRelatedToPreviousError (tc);
286 Report.Error (261, next_part.Location,
287 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
288 next_part.GetSignatureForError ());
291 if ((tc.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) &&
292 ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 &&
293 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
294 Report.SymbolRelatedToPreviousError (tc);
295 Report.Error (262, next_part.Location,
296 "Partial declarations of `{0}' have conflicting accessibility modifiers",
297 next_part.GetSignatureForError ());
300 if (tc.partial_parts == null)
301 tc.partial_parts = new List<TypeContainer> (1);
303 if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
304 tc.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
305 } else if ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
306 tc.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
307 tc.ModFlags |= next_part.ModFlags;
308 } else {
309 tc.ModFlags |= next_part.ModFlags;
312 if (next_part.attributes != null) {
313 if (tc.attributes == null)
314 tc.attributes = next_part.attributes;
315 else
316 tc.attributes.AddAttributes (next_part.attributes.Attrs);
319 next_part.PartialContainer = tc;
320 tc.partial_parts.Add (next_part);
321 return tc;
324 public virtual void RemoveTypeContainer (TypeContainer next_part)
326 if (types != null)
327 types.Remove (next_part);
328 RemoveMemberType (next_part);
331 public void AddDelegate (Delegate d)
333 if (!AddMemberType (d))
334 return;
336 if (delegates == null)
337 delegates = new List<TypeContainer> ();
339 delegates.Add (d);
342 private void AddMemberToList (MemberCore mc, List<MemberCore> alist, bool isexplicit)
344 if (ordered_explicit_member_list == null) {
345 ordered_explicit_member_list = new List<MemberCore> ();
346 ordered_member_list = new List<MemberCore> ();
349 if (isexplicit) {
350 if (Kind == MemberKind.Interface) {
351 Report.Error (541, mc.Location,
352 "`{0}': explicit interface declaration can only be declared in a class or struct",
353 mc.GetSignatureForError ());
356 ordered_explicit_member_list.Add (mc);
357 alist.Insert (0, mc);
358 } else {
359 ordered_member_list.Add (mc);
360 alist.Add (mc);
365 public void AddMethod (MethodOrOperator method)
367 if (!AddToContainer (method, method.MemberName.Basename))
368 return;
370 if (methods == null)
371 methods = new List<MemberCore> ();
373 if (method.MemberName.Left != null)
374 AddMemberToList (method, methods, true);
375 else
376 AddMemberToList (method, methods, false);
379 public void AddConstructor (Constructor c)
381 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
382 if (!AddToContainer (c, is_static ?
383 ConstructorBuilder.ConstructorName : ConstructorBuilder.TypeConstructorName))
384 return;
386 if (is_static && c.Parameters.IsEmpty){
387 if (default_static_constructor != null) {
388 Report.SymbolRelatedToPreviousError (default_static_constructor);
389 Report.Error (111, c.Location,
390 "A member `{0}' is already defined. Rename this member or use different parameter types",
391 c.GetSignatureForError ());
392 return;
395 default_static_constructor = c;
396 } else {
397 if (c.Parameters.IsEmpty)
398 default_constructor = c;
400 if (instance_constructors == null)
401 instance_constructors = new List<MemberCore> ();
403 instance_constructors.Add (c);
407 public bool AddField (FieldBase field)
409 if (!AddMember (field))
410 return false;
412 if (fields == null)
413 fields = new List<MemberCore> ();
415 fields.Add (field);
417 if ((field.ModFlags & Modifiers.STATIC) != 0)
418 return true;
420 if (first_nonstatic_field == null) {
421 first_nonstatic_field = field;
422 return true;
425 if (Kind == MemberKind.Struct && first_nonstatic_field.Parent != field.Parent) {
426 Report.SymbolRelatedToPreviousError (first_nonstatic_field.Parent);
427 Report.Warning (282, 3, field.Location,
428 "struct instance field `{0}' found in different declaration from instance field `{1}'",
429 field.GetSignatureForError (), first_nonstatic_field.GetSignatureForError ());
431 return true;
434 public void AddProperty (Property prop)
436 if (!AddMember (prop) ||
437 !AddMember (prop.Get) || !AddMember (prop.Set))
438 return;
440 if (properties == null)
441 properties = new List<MemberCore> ();
443 if (prop.MemberName.Left != null)
444 AddMemberToList (prop, properties, true);
445 else
446 AddMemberToList (prop, properties, false);
449 public void AddEvent (Event e)
451 if (!AddMember (e))
452 return;
454 if (e is EventProperty) {
455 if (!AddMember (e.Add))
456 return;
458 if (!AddMember (e.Remove))
459 return;
462 if (events == null)
463 events = new List<MemberCore> ();
465 events.Add (e);
468 /// <summary>
469 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
470 /// </summary>
471 public void AddIndexer (Indexer i)
473 if (indexers == null)
474 indexers = new List<MemberCore> ();
476 if (i.IsExplicitImpl)
477 AddMemberToList (i, indexers, true);
478 else
479 AddMemberToList (i, indexers, false);
482 public void AddOperator (Operator op)
484 if (!AddMember (op))
485 return;
487 if (operators == null)
488 operators = new List<MemberCore> ();
490 operators.Add (op);
493 public void AddCompilerGeneratedClass (CompilerGeneratedClass c)
495 Report.Debug (64, "ADD COMPILER GENERATED CLASS", this, c);
497 if (compiler_generated == null)
498 compiler_generated = new List<CompilerGeneratedClass> ();
500 compiler_generated.Add (c);
503 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
505 if (a.Type == pa.DefaultMember) {
506 if (Indexers != null) {
507 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
508 return;
512 base.ApplyAttributeBuilder (a, cb, pa);
515 public override AttributeTargets AttributeTargets {
516 get {
517 throw new NotSupportedException ();
521 public IList<TypeContainer> Types {
522 get {
523 return types;
527 public IList<MemberCore> Methods {
528 get {
529 return methods;
533 public IList<MemberCore> Constants {
534 get {
535 return constants;
539 protected virtual Type BaseType {
540 get {
541 return TypeBuilder.BaseType;
545 public IList<MemberCore> Fields {
546 get {
547 return fields;
551 public IList<MemberCore> InstanceConstructors {
552 get {
553 return instance_constructors;
557 public IList<MemberCore> Properties {
558 get {
559 return properties;
563 public IList<MemberCore> Events {
564 get {
565 return events;
569 public IList<MemberCore> Indexers {
570 get {
571 return indexers;
575 public IList<MemberCore> Operators {
576 get {
577 return operators;
581 public IList<TypeContainer> Delegates {
582 get {
583 return delegates;
587 public IList<CompilerGeneratedClass> CompilerGeneratedClasses {
588 get {
589 return compiler_generated;
593 protected override TypeAttributes TypeAttr {
594 get {
595 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel) | base.TypeAttr;
599 public string IndexerName {
600 get {
601 return indexers == null ? DefaultIndexerName : indexer_name;
605 public bool IsComImport {
606 get {
607 if (OptAttributes == null)
608 return false;
610 return OptAttributes.Contains (PredefinedAttributes.Get.ComImport);
614 public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
616 if ((field.ModFlags & Modifiers.STATIC) != 0){
617 if (initialized_static_fields == null) {
618 PartialContainer.HasStaticFieldInitializer = true;
619 initialized_static_fields = new List<FieldInitializer> (4);
622 initialized_static_fields.Add (expression);
623 } else {
624 if (initialized_fields == null)
625 initialized_fields = new List<FieldInitializer> (4);
627 initialized_fields.Add (expression);
631 public void ResolveFieldInitializers (BlockContext ec)
633 if (partial_parts != null) {
634 foreach (TypeContainer part in partial_parts) {
635 part.DoResolveFieldInitializers (ec);
638 DoResolveFieldInitializers (ec);
641 void DoResolveFieldInitializers (BlockContext ec)
643 if (ec.IsStatic) {
644 if (initialized_static_fields == null)
645 return;
647 bool has_complex_initializer = !RootContext.Optimize;
648 int i;
649 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
650 for (i = 0; i < initialized_static_fields.Count; ++i) {
651 FieldInitializer fi = initialized_static_fields [i];
652 ExpressionStatement s = fi.ResolveStatement (ec);
653 if (s == null) {
654 s = EmptyExpressionStatement.Instance;
655 } else if (fi.IsComplexInitializer) {
656 has_complex_initializer |= true;
659 init [i] = s;
662 for (i = 0; i < initialized_static_fields.Count; ++i) {
663 FieldInitializer fi = initialized_static_fields [i];
665 // Need special check to not optimize code like this
666 // static int a = b = 5;
667 // static int b = 0;
669 if (!has_complex_initializer && fi.IsDefaultInitializer)
670 continue;
672 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
675 return;
678 if (initialized_fields == null)
679 return;
681 for (int i = 0; i < initialized_fields.Count; ++i) {
682 FieldInitializer fi = (FieldInitializer) initialized_fields [i];
683 ExpressionStatement s = fi.ResolveStatement (ec);
684 if (s == null)
685 continue;
688 // Field is re-initialized to its default value => removed
690 if (fi.IsDefaultInitializer && RootContext.Optimize)
691 continue;
693 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
697 public override string DocComment {
698 get {
699 return comment;
701 set {
702 if (value == null)
703 return;
705 comment += value;
709 public PendingImplementation PendingImplementations {
710 get { return pending; }
713 public override bool GetClsCompliantAttributeValue ()
715 if (PartialContainer != this)
716 return PartialContainer.GetClsCompliantAttributeValue ();
718 return base.GetClsCompliantAttributeValue ();
721 public virtual void AddBasesForPart (DeclSpace part, List<FullNamedExpression> bases)
723 // FIXME: get rid of partial_parts and store lists of bases of each part here
724 // assumed, not verified: 'part' is in 'partial_parts'
725 ((TypeContainer) part).type_bases = bases;
728 /// <summary>
729 /// This function computes the Base class and also the
730 /// list of interfaces that the class or struct @c implements.
731 ///
732 /// The return value is an array (might be null) of
733 /// interfaces implemented (as Types).
734 ///
735 /// The @base_class argument is set to the base object or null
736 /// if this is `System.Object'.
737 /// </summary>
738 protected virtual TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
740 base_class = null;
741 if (type_bases == null)
742 return null;
744 int count = type_bases.Count;
745 TypeExpr [] ifaces = null;
746 IMemberContext base_context = new BaseContext (this);
747 for (int i = 0, j = 0; i < count; i++){
748 FullNamedExpression fne = (FullNamedExpression) type_bases [i];
751 // Standard ResolveAsTypeTerminal cannot be used in this case because
752 // it does ObsoleteAttribute and constraint checks which require
753 // base type to be set
755 TypeExpr fne_resolved = fne.ResolveAsBaseTerminal (base_context, false);
756 if (fne_resolved == null)
757 continue;
759 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.Type.IsInterface) {
760 if (fne_resolved is DynamicTypeExpr)
761 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
762 GetSignatureForError ());
763 else
764 base_class = fne_resolved;
765 continue;
768 if (ifaces == null)
769 ifaces = new TypeExpr [count - i];
771 if (fne_resolved.Type.IsInterface) {
772 for (int ii = 0; ii < j; ++ii) {
773 if (TypeManager.IsEqual (fne_resolved.Type, ifaces [ii].Type)) {
774 Report.Error (528, Location, "`{0}' is already listed in interface list",
775 fne_resolved.GetSignatureForError ());
776 break;
780 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved.Type)) {
781 Report.Error (61, fne.Location,
782 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
783 fne_resolved.GetSignatureForError (), GetSignatureForError ());
785 } else {
786 Report.SymbolRelatedToPreviousError (fne_resolved.Type);
787 if (Kind != MemberKind.Class) {
788 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
789 } else if (base_class != null)
790 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
791 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
792 else {
793 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
794 GetSignatureForError (), fne_resolved.GetSignatureForError ());
798 ifaces [j++] = fne_resolved;
801 return ifaces;
804 TypeExpr[] GetNormalPartialBases (ref TypeExpr base_class)
806 var ifaces = new List<TypeExpr> (0);
807 if (iface_exprs != null)
808 ifaces.AddRange (iface_exprs);
810 foreach (TypeContainer part in partial_parts) {
811 TypeExpr new_base_class;
812 TypeExpr[] new_ifaces = part.ResolveBaseTypes (out new_base_class);
813 if (new_base_class != TypeManager.system_object_expr) {
814 if (base_class == TypeManager.system_object_expr)
815 base_class = new_base_class;
816 else {
817 if (new_base_class != null && !TypeManager.IsEqual (new_base_class.Type, base_class.Type)) {
818 Report.SymbolRelatedToPreviousError (base_class.Location, "");
819 Report.Error (263, part.Location,
820 "Partial declarations of `{0}' must not specify different base classes",
821 part.GetSignatureForError ());
823 return null;
828 if (new_ifaces == null)
829 continue;
831 foreach (TypeExpr iface in new_ifaces) {
832 if (ifaces.Contains (iface))
833 continue;
835 ifaces.Add (iface);
839 if (ifaces.Count == 0)
840 return null;
842 return ifaces.ToArray ();
846 // Checks that some operators come in pairs:
847 // == and !=
848 // > and <
849 // >= and <=
850 // true and false
852 // They are matched based on the return type and the argument types
854 void CheckPairedOperators ()
856 bool has_equality_or_inequality = false;
857 var operators = this.operators.ToArray ();
858 bool[] has_pair = new bool[operators.Length];
860 for (int i = 0; i < operators.Length; ++i) {
861 if (operators[i] == null)
862 continue;
864 Operator o_a = (Operator) operators[i];
865 Operator.OpType o_type = o_a.OperatorType;
866 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
867 has_equality_or_inequality = true;
869 Operator.OpType matching_type = o_a.GetMatchingOperator ();
870 if (matching_type == Operator.OpType.TOP) {
871 operators[i] = null;
872 continue;
875 for (int ii = 0; ii < operators.Length; ++ii) {
876 Operator o_b = (Operator) operators[ii];
877 if (o_b == null || o_b.OperatorType != matching_type)
878 continue;
880 if (!TypeManager.IsEqual (o_a.ReturnType, o_b.ReturnType))
881 continue;
883 if (!TypeManager.IsEqual (o_a.ParameterTypes, o_b.ParameterTypes))
884 continue;
886 operators[i] = null;
889 // Used to ignore duplicate user conversions
891 has_pair[ii] = true;
895 for (int i = 0; i < operators.Length; ++i) {
896 if (operators[i] == null || has_pair[i])
897 continue;
899 Operator o = (Operator) operators [i];
900 Report.Error (216, o.Location,
901 "The operator `{0}' requires a matching operator `{1}' to also be defined",
902 o.GetSignatureForError (), Operator.GetName (o.GetMatchingOperator ()));
905 if (has_equality_or_inequality) {
906 if (Methods == null || !HasEquals)
907 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
908 GetSignatureForError ());
910 if (Methods == null || !HasGetHashCode)
911 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
912 GetSignatureForError ());
916 bool CheckGenericInterfaces (Type[] ifaces)
918 var already_checked = new List<Type> ();
920 for (int i = 0; i < ifaces.Length; i++) {
921 Type iface = ifaces [i];
922 foreach (Type t in already_checked) {
923 if (iface == t)
924 continue;
926 Type[] inferred = new Type [CountTypeParameters];
927 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t, inferred, null))
928 continue;
930 Report.Error (695, Location,
931 "`{0}' cannot implement both `{1}' and `{2}' " +
932 "because they may unify for some type parameter substitutions",
933 TypeManager.CSharpName (TypeBuilder), TypeManager.CSharpName (iface),
934 TypeManager.CSharpName (t));
935 return false;
938 already_checked.Add (iface);
941 return true;
944 bool error = false;
946 bool CreateTypeBuilder ()
948 try {
949 Type default_parent = null;
950 if (Kind == MemberKind.Struct)
951 default_parent = TypeManager.value_type;
952 else if (Kind == MemberKind.Enum)
953 default_parent = TypeManager.enum_type;
954 else if (Kind == MemberKind.Delegate)
955 default_parent = TypeManager.multicast_delegate_type;
958 // Sets .size to 1 for structs with no instance fields
960 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null ? 1 : 0;
962 if (IsTopLevel){
963 if (GlobalRootNamespace.Instance.IsNamespace (Name)) {
964 Report.Error (519, Location, "`{0}' clashes with a predefined namespace", Name);
965 return false;
968 ModuleBuilder builder = Module.Compiled.Builder;
969 TypeBuilder = builder.DefineType (
970 Name, TypeAttr, default_parent, type_size);
971 } else {
972 TypeBuilder builder = Parent.TypeBuilder;
974 TypeBuilder = builder.DefineNestedType (
975 Basename, TypeAttr, default_parent, type_size);
977 } catch (ArgumentException) {
978 Report.RuntimeMissingSupport (Location, "static classes");
979 return false;
982 TypeManager.AddUserType (this);
984 if (IsGeneric) {
985 string[] param_names = new string [TypeParameters.Length];
986 for (int i = 0; i < TypeParameters.Length; i++)
987 param_names [i] = TypeParameters [i].Name;
989 GenericTypeParameterBuilder[] gen_params = TypeBuilder.DefineGenericParameters (param_names);
991 int offset = CountTypeParameters;
992 if (CurrentTypeParameters != null)
993 offset -= CurrentTypeParameters.Length;
995 if (offset > 0) {
996 nested_gen_params = new GenericTypeParameterBuilder [offset];
997 Array.Copy (gen_params, nested_gen_params, offset);
1000 for (int i = offset; i < gen_params.Length; i++)
1001 CurrentTypeParameters [i - offset].Define (gen_params [i]);
1004 return true;
1007 bool DefineBaseTypes ()
1009 iface_exprs = ResolveBaseTypes (out base_type);
1010 if (partial_parts != null) {
1011 iface_exprs = GetNormalPartialBases (ref base_type);
1015 // GetClassBases calls ResolveBaseTypeExpr() on the various type expressions involved,
1016 // which in turn should have called DefineType()s on base types if necessary.
1018 // None of the code below should trigger DefineType()s on classes that we depend on.
1019 // Thus, we are eligible to be on the topological sort `type_container_resolve_order'.
1021 // Let's do it as soon as possible, since code below can call DefineType() on classes
1022 // that depend on us to be populated before they are.
1024 if (!(this is CompilerGeneratedClass) && !(this is Delegate))
1025 RootContext.RegisterOrder (this);
1027 if (!CheckRecursiveDefinition (this))
1028 return false;
1030 if (base_type != null && base_type.Type != null) {
1031 TypeBuilder.SetParent (base_type.Type);
1034 // add interfaces that were not added at type creation
1035 if (iface_exprs != null) {
1036 ifaces = TypeManager.ExpandInterfaces (iface_exprs);
1037 if (ifaces == null)
1038 return false;
1040 foreach (Type itype in ifaces)
1041 TypeBuilder.AddInterfaceImplementation (itype);
1043 if (!CheckGenericInterfaces (ifaces))
1044 return false;
1046 TypeManager.RegisterBuilder (TypeBuilder, ifaces);
1049 return true;
1053 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1055 public TypeBuilder CreateType ()
1057 if (TypeBuilder != null)
1058 return TypeBuilder;
1060 if (error)
1061 return null;
1063 if (!CreateTypeBuilder ()) {
1064 error = true;
1065 return null;
1068 if (partial_parts != null) {
1069 foreach (TypeContainer part in partial_parts)
1070 part.TypeBuilder = TypeBuilder;
1073 if (Types != null) {
1074 foreach (TypeContainer tc in Types) {
1075 if (tc.CreateType () == null) {
1076 error = true;
1077 return null;
1082 return TypeBuilder;
1085 bool type_defined;
1087 public override TypeBuilder DefineType ()
1089 if (error)
1090 return null;
1091 if (type_defined)
1092 return TypeBuilder;
1094 type_defined = true;
1096 if (CreateType () == null) {
1097 error = true;
1098 return null;
1101 if (!DefineBaseTypes ()) {
1102 error = true;
1103 return null;
1106 if (!DefineNestedTypes ()) {
1107 error = true;
1108 return null;
1111 return TypeBuilder;
1114 public override void SetParameterInfo (List<Constraints> constraints_list)
1116 base.SetParameterInfo (constraints_list);
1118 if (!is_generic || PartialContainer == this)
1119 return;
1121 TypeParameter[] tc_names = PartialContainer.TypeParameters;
1122 for (int i = 0; i < tc_names.Length; ++i) {
1123 if (tc_names [i].Name != type_params [i].Name) {
1124 Report.SymbolRelatedToPreviousError (PartialContainer.Location, "");
1125 Report.Error (264, Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
1126 GetSignatureForError ());
1127 break;
1130 if (tc_names [i].Variance != type_params [i].Variance) {
1131 Report.SymbolRelatedToPreviousError (PartialContainer.Location, "");
1132 Report.Error (1067, Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers",
1133 GetSignatureForError ());
1134 break;
1139 void UpdateTypeParameterConstraints (TypeContainer part)
1141 TypeParameter[] current_params = type_params;
1142 for (int i = 0; i < current_params.Length; i++) {
1143 Constraints c = part.type_params [i].Constraints;
1144 if (c == null)
1145 continue;
1147 if (current_params [i].UpdateConstraints (part, c))
1148 continue;
1150 Report.SymbolRelatedToPreviousError (Location, "");
1151 Report.Error (265, part.Location,
1152 "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'",
1153 GetSignatureForError (), current_params [i].GetSignatureForError ());
1157 public bool ResolveType ()
1159 if (!DoResolveType ())
1160 return false;
1162 if (compiler_generated != null) {
1163 foreach (CompilerGeneratedClass c in compiler_generated)
1164 if (!c.ResolveType ())
1165 return false;
1168 return true;
1171 protected virtual bool DoResolveType ()
1173 if (!IsGeneric)
1174 return true;
1176 if (PartialContainer != this)
1177 throw new InternalErrorException ();
1179 TypeExpr current_type = null;
1180 if (CurrentTypeParameters != null) {
1181 foreach (TypeParameter type_param in CurrentTypeParameters) {
1182 if (!type_param.Resolve (this)) {
1183 error = true;
1184 return false;
1188 if (partial_parts != null) {
1189 foreach (TypeContainer part in partial_parts)
1190 UpdateTypeParameterConstraints (part);
1194 for (int i = 0; i < TypeParameters.Length; ++i) {
1196 // FIXME: Same should be done for delegates
1197 // TODO: Quite ugly way how to propagate constraints to
1198 // nested types
1200 if (nested_gen_params != null && i < nested_gen_params.Length) {
1201 TypeParameters [i].SetConstraints (nested_gen_params [i]);
1202 } else {
1203 if (!TypeParameters [i].DefineType (this)) {
1204 error = true;
1205 return false;
1210 // TODO: Very strange, why not simple make generic type from
1211 // current type parameters
1212 current_type = new GenericTypeExpr (this, Location);
1213 current_type = current_type.ResolveAsTypeTerminal (this, false);
1214 if (current_type == null) {
1215 error = true;
1216 return false;
1219 currentType = current_type.Type;
1220 return true;
1223 protected virtual bool DefineNestedTypes ()
1225 if (Types != null) {
1226 foreach (TypeContainer tc in Types)
1227 if (tc.DefineType () == null)
1228 return false;
1231 if (Delegates != null) {
1232 foreach (Delegate d in Delegates)
1233 if (d.DefineType () == null)
1234 return false;
1237 return true;
1240 TypeContainer InTransit;
1242 protected bool CheckRecursiveDefinition (TypeContainer tc)
1244 if (InTransit != null) {
1245 Report.SymbolRelatedToPreviousError (this);
1246 if (this is Interface)
1247 Report.Error (
1248 529, tc.Location, "Inherited interface `{0}' causes a " +
1249 "cycle in the interface hierarchy of `{1}'",
1250 GetSignatureForError (), tc.GetSignatureForError ());
1251 else
1252 Report.Error (
1253 146, tc.Location, "Circular base class dependency " +
1254 "involving `{0}' and `{1}'",
1255 tc.GetSignatureForError (), GetSignatureForError ());
1256 return false;
1259 InTransit = tc;
1261 if (base_type != null && base_type.Type != null) {
1262 Type t = TypeManager.DropGenericTypeArguments (base_type.Type);
1263 TypeContainer ptc = TypeManager.LookupTypeContainer (t);
1264 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1265 return false;
1268 if (iface_exprs != null) {
1269 foreach (TypeExpr iface in iface_exprs) {
1270 Type itype = TypeManager.DropGenericTypeArguments (iface.Type);
1271 TypeContainer ptc = TypeManager.LookupTypeContainer (itype);
1272 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1273 return false;
1277 if (!IsTopLevel && !Parent.PartialContainer.CheckRecursiveDefinition (this))
1278 return false;
1280 InTransit = null;
1281 return true;
1284 public override TypeParameter[] CurrentTypeParameters {
1285 get {
1286 return PartialContainer.type_params;
1290 /// <summary>
1291 /// Populates our TypeBuilder with fields and methods
1292 /// </summary>
1293 public sealed override bool Define ()
1295 if (members_defined)
1296 return members_defined_ok;
1298 members_defined_ok = DoDefineMembers ();
1299 members_defined = true;
1301 return members_defined_ok;
1304 protected virtual bool DoDefineMembers ()
1306 if (iface_exprs != null) {
1307 foreach (TypeExpr iface in iface_exprs) {
1308 ObsoleteAttribute oa = AttributeTester.GetObsoleteAttribute (iface.Type);
1309 if ((oa != null) && !IsObsolete)
1310 AttributeTester.Report_ObsoleteMessage (
1311 oa, iface.GetSignatureForError (), Location, Report);
1313 GenericTypeExpr ct = iface as GenericTypeExpr;
1314 if (ct != null) {
1315 // TODO: passing `this' is wrong, should be base type iface instead
1316 TypeManager.CheckTypeVariance (ct.Type, Variance.Covariant, this);
1318 if (!ct.CheckConstraints (this))
1319 return false;
1321 if (ct.HasDynamicArguments ()) {
1322 Report.Error (1966, iface.Location,
1323 "`{0}': cannot implement a dynamic interface `{1}'",
1324 GetSignatureForError (), iface.GetSignatureForError ());
1325 return false;
1331 if (base_type != null) {
1332 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (base_type.Type);
1333 if (obsolete_attr != null && !IsObsolete)
1334 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), Location, Report);
1336 GenericTypeExpr ct = base_type as GenericTypeExpr;
1337 if ((ct != null) && !ct.CheckConstraints (this))
1338 return false;
1340 TypeContainer baseContainer = TypeManager.LookupTypeContainer(base_type.Type);
1341 if (baseContainer != null)
1342 baseContainer.Define();
1344 member_cache = new MemberCache (base_type.Type, this);
1345 } else if (Kind == MemberKind.Interface) {
1346 member_cache = new MemberCache (null, this);
1347 Type [] ifaces = TypeManager.GetInterfaces (TypeBuilder);
1348 for (int i = 0; i < ifaces.Length; ++i)
1349 member_cache.AddInterface (TypeManager.LookupMemberCache (ifaces [i]));
1350 } else {
1351 member_cache = new MemberCache (null, this);
1354 if (types != null)
1355 foreach (TypeContainer tc in types)
1356 member_cache.AddNestedType (tc);
1358 if (delegates != null)
1359 foreach (Delegate d in delegates)
1360 member_cache.AddNestedType (d);
1362 if (partial_parts != null) {
1363 foreach (TypeContainer part in partial_parts)
1364 part.member_cache = member_cache;
1367 if (!IsTopLevel) {
1368 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Basename, false);
1369 if (conflict_symbol == null) {
1370 if ((ModFlags & Modifiers.NEW) != 0)
1371 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
1372 } else {
1373 if ((ModFlags & Modifiers.NEW) == 0) {
1374 Report.SymbolRelatedToPreviousError (conflict_symbol);
1375 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
1376 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
1381 DefineContainerMembers (constants);
1382 DefineContainerMembers (fields);
1384 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1385 pending = PendingImplementation.GetPendingImplementations (this);
1387 if (requires_delayed_unmanagedtype_check) {
1388 requires_delayed_unmanagedtype_check = false;
1389 foreach (FieldBase f in fields) {
1390 if (f.MemberType != null && f.MemberType.IsPointer)
1391 TypeManager.VerifyUnmanaged (Compiler, f.MemberType, f.Location);
1397 // Constructors are not in the defined_names array
1399 DefineContainerMembers (instance_constructors);
1401 DefineContainerMembers (events);
1402 DefineContainerMembers (ordered_explicit_member_list);
1403 DefineContainerMembers (ordered_member_list);
1405 if (operators != null) {
1406 DefineContainerMembers (operators);
1407 CheckPairedOperators ();
1410 DefineContainerMembers (delegates);
1412 ComputeIndexerName();
1413 CheckEqualsAndGetHashCode();
1415 if (CurrentType != null) {
1416 GenericType = CurrentType;
1420 // FIXME: This hack is needed because member cache does not work
1421 // with generic types, we rely on runtime to inflate dynamic types.
1422 // TODO: This hack requires member cache refactoring to be removed
1424 if (TypeManager.IsGenericType (TypeBuilder))
1425 member_cache = new MemberCache (this);
1427 return true;
1430 protected virtual void DefineContainerMembers (System.Collections.IList mcal) // IList<MemberCore>
1432 if (mcal != null) {
1433 foreach (MemberCore mc in mcal) {
1434 try {
1435 mc.Define ();
1436 } catch (Exception e) {
1437 throw new InternalErrorException (mc, e);
1443 protected virtual void ComputeIndexerName ()
1445 if (indexers == null)
1446 return;
1448 string class_indexer_name = null;
1451 // If there's both an explicit and an implicit interface implementation, the
1452 // explicit one actually implements the interface while the other one is just
1453 // a normal indexer. See bug #37714.
1456 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
1457 foreach (Indexer i in indexers) {
1458 if (i.InterfaceType != null) {
1459 if (seen_normal_indexers)
1460 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
1461 continue;
1464 seen_normal_indexers = true;
1466 if (class_indexer_name == null) {
1467 class_indexer_name = i.ShortName;
1468 continue;
1471 if (i.ShortName != class_indexer_name)
1472 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");
1475 if (class_indexer_name != null)
1476 indexer_name = class_indexer_name;
1479 protected virtual void EmitIndexerName ()
1481 if (!seen_normal_indexers)
1482 return;
1484 PredefinedAttribute pa = PredefinedAttributes.Get.DefaultMember;
1485 if (pa.Constructor == null &&
1486 !pa.ResolveConstructor (Location, TypeManager.string_type))
1487 return;
1489 CustomAttributeBuilder cb = new CustomAttributeBuilder (pa.Constructor, new string [] { IndexerName });
1490 TypeBuilder.SetCustomAttribute (cb);
1493 protected virtual void CheckEqualsAndGetHashCode ()
1495 if (methods == null)
1496 return;
1498 if (HasEquals && !HasGetHashCode) {
1499 Report.Warning (659, 3, this.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", this.GetSignatureForError ());
1503 public MemberInfo FindBaseMemberWithSameName (string name, bool ignore_methods)
1505 return BaseCache == null ? null : BaseCache.FindMemberWithSameName (name, ignore_methods, null);
1508 /// <summary>
1509 /// This function is based by a delegate to the FindMembers routine
1510 /// </summary>
1511 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1513 return true;
1516 /// <summary>
1517 /// This filter is used by FindMembers, and we just keep
1518 /// a global for the filter to `AlwaysAccept'
1519 /// </summary>
1520 static MemberFilter accepting_filter;
1523 static TypeContainer ()
1525 accepting_filter = new MemberFilter (AlwaysAccept);
1528 public MethodInfo[] GetMethods ()
1530 var members = new List<MethodInfo> ();
1532 Define ();
1534 if (methods != null) {
1535 int len = methods.Count;
1536 for (int i = 0; i < len; i++) {
1537 Method m = (Method) methods [i];
1539 members.Add (m.MethodBuilder);
1543 if (operators != null) {
1544 int len = operators.Count;
1545 for (int i = 0; i < len; i++) {
1546 Operator o = (Operator) operators [i];
1548 members.Add (o.MethodBuilder);
1552 if (properties != null) {
1553 int len = properties.Count;
1554 for (int i = 0; i < len; i++) {
1555 Property p = (Property) properties [i];
1557 if (p.GetBuilder != null)
1558 members.Add (p.GetBuilder);
1559 if (p.SetBuilder != null)
1560 members.Add (p.SetBuilder);
1564 if (indexers != null) {
1565 int len = indexers.Count;
1566 for (int i = 0; i < len; i++) {
1567 Indexer ix = (Indexer) indexers [i];
1569 if (ix.GetBuilder != null)
1570 members.Add (ix.GetBuilder);
1571 if (ix.SetBuilder != null)
1572 members.Add (ix.SetBuilder);
1576 if (events != null) {
1577 int len = events.Count;
1578 for (int i = 0; i < len; i++) {
1579 Event e = (Event) events [i];
1581 if (e.AddBuilder != null)
1582 members.Add (e.AddBuilder);
1583 if (e.RemoveBuilder != null)
1584 members.Add (e.RemoveBuilder);
1588 return members.ToArray ();
1591 // Indicated whether container has StructLayout attribute set Explicit
1592 public bool HasExplicitLayout {
1593 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
1594 set { caching_flags |= Flags.HasExplicitLayout; }
1597 public bool HasStructLayout {
1598 get { return (caching_flags & Flags.HasStructLayout) != 0; }
1599 set { caching_flags |= Flags.HasStructLayout; }
1603 // Return the nested type with name @name. Ensures that the nested type
1604 // is defined if necessary. Do _not_ use this when you have a MemberCache handy.
1606 public Type FindNestedType (string name)
1608 if (PartialContainer != this)
1609 throw new InternalErrorException ("should not happen");
1611 var lists = new[] { types, delegates };
1613 for (int j = 0; j < lists.Length; ++j) {
1614 var list = lists [j];
1615 if (list == null)
1616 continue;
1618 int len = list.Count;
1619 for (int i = 0; i < len; ++i) {
1620 var ds = list [i];
1621 if (ds.Basename == name) {
1622 return ds.DefineType ();
1627 return null;
1630 private void FindMembers_NestedTypes (Modifiers modflags,
1631 BindingFlags bf, MemberFilter filter, object criteria,
1632 ref List<MemberInfo> members)
1634 var lists = new[] { types, delegates };
1636 for (int j = 0; j < lists.Length; ++j) {
1637 var list = lists [j];
1638 if (list == null)
1639 continue;
1641 int len = list.Count;
1642 for (int i = 0; i < len; i++) {
1643 var ds = list [i];
1645 if ((ds.ModFlags & modflags) == 0)
1646 continue;
1648 TypeBuilder tb = ds.TypeBuilder;
1649 if (tb == null) {
1650 if (!(criteria is string) || ds.Basename.Equals (criteria))
1651 tb = ds.DefineType ();
1654 if (tb != null && (filter (tb, criteria) == true)) {
1655 if (members == null)
1656 members = new List<MemberInfo> ();
1658 members.Add (tb);
1664 /// <summary>
1665 /// This method returns the members of this type just like Type.FindMembers would
1666 /// Only, we need to use this for types which are _being_ defined because MS'
1667 /// implementation can't take care of that.
1668 /// </summary>
1670 // FIXME: return an empty static array instead of null, that cleans up
1671 // some code and is consistent with some coding conventions I just found
1672 // out existed ;-)
1675 // Notice that in various cases we check if our field is non-null,
1676 // something that would normally mean that there was a bug elsewhere.
1678 // The problem happens while we are defining p-invoke methods, as those
1679 // will trigger a FindMembers, but this happens before things are defined
1681 // Since the whole process is a no-op, it is fine to check for null here.
1683 // TODO: This approach will be one day completely removed, it's already
1684 // used at few places only
1687 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1688 MemberFilter filter, object criteria)
1690 List<MemberInfo> members = null;
1692 Modifiers modflags = 0;
1693 if ((bf & BindingFlags.Public) != 0)
1694 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1695 Modifiers.INTERNAL;
1696 if ((bf & BindingFlags.NonPublic) != 0)
1697 modflags |= Modifiers.PRIVATE;
1699 Modifiers static_mask = 0, static_flags = 0;
1700 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1701 case BindingFlags.Static:
1702 static_mask = static_flags = Modifiers.STATIC;
1703 break;
1705 case BindingFlags.Instance:
1706 static_mask = Modifiers.STATIC;
1707 static_flags = 0;
1708 break;
1710 default:
1711 static_mask = static_flags = 0;
1712 break;
1715 Timer.StartTimer (TimerType.TcFindMembers);
1717 if (filter == null)
1718 filter = accepting_filter;
1720 if ((mt & MemberTypes.Field) != 0) {
1721 if (fields != null) {
1722 int len = fields.Count;
1723 for (int i = 0; i < len; i++) {
1724 FieldBase f = (FieldBase) fields [i];
1726 if ((f.ModFlags & modflags) == 0)
1727 continue;
1728 if ((f.ModFlags & static_mask) != static_flags)
1729 continue;
1731 FieldBuilder fb = f.FieldBuilder;
1732 if (fb != null && filter (fb, criteria) == true) {
1733 if (members == null)
1734 members = new List<MemberInfo> ();
1736 members.Add (fb);
1741 if (constants != null) {
1742 int len = constants.Count;
1743 for (int i = 0; i < len; i++) {
1744 Const con = (Const) constants [i];
1746 if ((con.ModFlags & modflags) == 0)
1747 continue;
1748 if ((con.ModFlags & static_mask) != static_flags)
1749 continue;
1751 FieldBuilder fb = con.FieldBuilder;
1752 if (fb == null) {
1753 // Define parent and not member, otherwise membercache can be null
1754 if (con.Parent.Define ())
1755 fb = con.FieldBuilder;
1757 if (fb != null && filter (fb, criteria) == true) {
1758 if (members == null)
1759 members = new List<MemberInfo> ();
1761 members.Add (fb);
1767 if ((mt & MemberTypes.Method) != 0) {
1768 if (methods != null) {
1769 int len = methods.Count;
1770 for (int i = 0; i < len; i++) {
1771 MethodOrOperator m = (MethodOrOperator) methods [i];
1773 if ((m.ModFlags & modflags) == 0)
1774 continue;
1775 if ((m.ModFlags & static_mask) != static_flags)
1776 continue;
1778 MethodBuilder mb = m.MethodBuilder;
1780 if (mb != null && filter (mb, criteria) == true) {
1781 if (members == null)
1782 members = new List<MemberInfo> ();
1784 members.Add (mb);
1789 if (operators != null) {
1790 int len = operators.Count;
1791 for (int i = 0; i < len; i++) {
1792 Operator o = (Operator) operators [i];
1794 if ((o.ModFlags & modflags) == 0)
1795 continue;
1796 if ((o.ModFlags & static_mask) != static_flags)
1797 continue;
1799 MethodBuilder ob = o.MethodBuilder;
1800 if (ob != null && filter (ob, criteria) == true) {
1801 if (members == null)
1802 members = new List<MemberInfo> ();
1804 members.Add (ob);
1809 if (events != null) {
1810 foreach (Event e in events) {
1811 if ((e.ModFlags & modflags) == 0)
1812 continue;
1813 if ((e.ModFlags & static_mask) != static_flags)
1814 continue;
1816 MethodBuilder b = e.AddBuilder;
1817 if (b != null && filter (b, criteria)) {
1818 if (members == null)
1819 members = new List<MemberInfo> ();
1821 members.Add (b);
1824 b = e.RemoveBuilder;
1825 if (b != null && filter (b, criteria)) {
1826 if (members == null)
1827 members = new List<MemberInfo> ();
1829 members.Add (b);
1834 if (properties != null) {
1835 int len = properties.Count;
1836 for (int i = 0; i < len; i++) {
1837 Property p = (Property) properties [i];
1839 if ((p.ModFlags & modflags) == 0)
1840 continue;
1841 if ((p.ModFlags & static_mask) != static_flags)
1842 continue;
1844 MethodBuilder b;
1846 b = p.GetBuilder;
1847 if (b != null && filter (b, criteria) == true) {
1848 if (members == null)
1849 members = new List<MemberInfo> ();
1851 members.Add (b);
1854 b = p.SetBuilder;
1855 if (b != null && filter (b, criteria) == true) {
1856 if (members == null)
1857 members = new List<MemberInfo> ();
1859 members.Add (b);
1864 if (indexers != null) {
1865 int len = indexers.Count;
1866 for (int i = 0; i < len; i++) {
1867 Indexer ix = (Indexer) indexers [i];
1869 if ((ix.ModFlags & modflags) == 0)
1870 continue;
1871 if ((ix.ModFlags & static_mask) != static_flags)
1872 continue;
1874 MethodBuilder b;
1876 b = ix.GetBuilder;
1877 if (b != null && filter (b, criteria) == true) {
1878 if (members == null)
1879 members = new List<MemberInfo> ();
1881 members.Add (b);
1884 b = ix.SetBuilder;
1885 if (b != null && filter (b, criteria) == true) {
1886 if (members == null)
1887 members = new List<MemberInfo> ();
1889 members.Add (b);
1895 if ((mt & MemberTypes.Event) != 0) {
1896 if (events != null) {
1897 int len = events.Count;
1898 for (int i = 0; i < len; i++) {
1899 Event e = (Event) events [i];
1901 if ((e.ModFlags & modflags) == 0)
1902 continue;
1903 if ((e.ModFlags & static_mask) != static_flags)
1904 continue;
1906 MemberInfo eb = e.EventBuilder;
1907 if (eb != null && filter (eb, criteria) == true) {
1908 if (members == null)
1909 members = new List<MemberInfo> ();
1911 members.Add (e.EventBuilder);
1917 if ((mt & MemberTypes.Property) != 0){
1918 if (properties != null) {
1919 int len = properties.Count;
1920 for (int i = 0; i < len; i++) {
1921 Property p = (Property) properties [i];
1923 if ((p.ModFlags & modflags) == 0)
1924 continue;
1925 if ((p.ModFlags & static_mask) != static_flags)
1926 continue;
1928 MemberInfo pb = p.PropertyBuilder;
1929 if (pb != null && filter (pb, criteria) == true) {
1930 if (members == null)
1931 members = new List<MemberInfo> ();
1933 members.Add (p.PropertyBuilder);
1938 if (indexers != null) {
1939 int len = indexers.Count;
1940 for (int i = 0; i < len; i++) {
1941 Indexer ix = (Indexer) indexers [i];
1943 if ((ix.ModFlags & modflags) == 0)
1944 continue;
1945 if ((ix.ModFlags & static_mask) != static_flags)
1946 continue;
1948 MemberInfo ib = ix.PropertyBuilder;
1949 if (ib != null && filter (ib, criteria) == true) {
1950 if (members == null)
1951 members = new List<MemberInfo> ();
1953 members.Add (ix.PropertyBuilder);
1959 if ((mt & MemberTypes.NestedType) != 0)
1960 FindMembers_NestedTypes (modflags, bf, filter, criteria, ref members);
1962 if ((mt & MemberTypes.Constructor) != 0){
1963 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1964 int len = instance_constructors.Count;
1965 for (int i = 0; i < len; i++) {
1966 Constructor c = (Constructor) instance_constructors [i];
1968 ConstructorBuilder cb = c.ConstructorBuilder;
1969 if (cb != null && filter (cb, criteria) == true) {
1970 if (members == null)
1971 members = new List<MemberInfo> ();
1973 members.Add (cb);
1978 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1979 ConstructorBuilder cb =
1980 default_static_constructor.ConstructorBuilder;
1982 if (cb != null && filter (cb, criteria) == true) {
1983 if (members == null)
1984 members = new List<MemberInfo> ();
1986 members.Add (cb);
1992 // Lookup members in base if requested.
1994 if ((bf & BindingFlags.DeclaredOnly) == 0) {
1995 if (TypeBuilder.BaseType != null) {
1996 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1997 if (list.Count > 0) {
1998 if (members == null)
1999 members = new List<MemberInfo> ();
2001 members.AddRange (list);
2006 Timer.StopTimer (TimerType.TcFindMembers);
2008 if (members == null)
2009 return MemberList.Empty;
2010 else
2011 return new MemberList (members);
2014 public override MemberCache MemberCache {
2015 get {
2016 return member_cache;
2020 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
2021 MemberFilter filter, object criteria)
2023 DeclSpace ds = TypeManager.LookupDeclSpace (t);
2025 if (ds != null)
2026 return ds.FindMembers (mt, bf, filter, criteria);
2027 else
2028 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
2031 /// <summary>
2032 /// Emits the values for the constants
2033 /// </summary>
2034 public void EmitConstants ()
2036 if (constants != null)
2037 foreach (Const con in constants)
2038 con.Emit ();
2039 return;
2042 void CheckMemberUsage (List<MemberCore> al, string member_type)
2044 if (al == null)
2045 return;
2047 foreach (MemberCore mc in al) {
2048 if ((mc.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE)
2049 continue;
2051 if (!mc.IsUsed && (mc.caching_flags & Flags.Excluded) == 0) {
2052 Report.Warning (169, 3, mc.Location, "The private {0} `{1}' is never used", member_type, mc.GetSignatureForError ());
2057 public virtual void VerifyMembers ()
2060 // Check for internal or private fields that were never assigned
2062 if (Report.WarningLevel >= 3) {
2063 if (RootContext.EnhancedWarnings) {
2064 CheckMemberUsage (properties, "property");
2065 CheckMemberUsage (methods, "method");
2066 CheckMemberUsage (constants, "constant");
2069 if (fields != null){
2070 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
2071 foreach (FieldBase f in fields) {
2072 if ((f.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
2073 if (is_type_exposed)
2074 continue;
2076 f.SetIsUsed ();
2079 if (!f.IsUsed){
2080 if ((f.caching_flags & Flags.IsAssigned) == 0)
2081 Report.Warning (169, 3, f.Location, "The private field `{0}' is never used", f.GetSignatureForError ());
2082 else {
2083 Report.Warning (414, 3, f.Location, "The private field `{0}' is assigned but its value is never used",
2084 f.GetSignatureForError ());
2086 continue;
2090 // Only report 649 on level 4
2092 if (Report.WarningLevel < 4)
2093 continue;
2095 if ((f.caching_flags & Flags.IsAssigned) != 0)
2096 continue;
2099 // Don't be pendatic over serializable attributes
2101 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2102 continue;
2104 Constant c = New.Constantify (f.MemberType);
2105 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value `{1}'",
2106 f.GetSignatureForError (), c == null ? "null" : c.AsString ());
2112 // TODO: move to ClassOrStruct
2113 void EmitConstructors ()
2115 if (instance_constructors == null)
2116 return;
2118 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && RootContext.VerifyClsCompliance && IsClsComplianceRequired ()) {
2119 bool has_compliant_args = false;
2121 foreach (Constructor c in instance_constructors) {
2122 try {
2123 c.Emit ();
2125 catch (Exception e) {
2126 throw new InternalErrorException (c, e);
2129 if (has_compliant_args)
2130 continue;
2132 has_compliant_args = c.HasCompliantArgs;
2134 if (!has_compliant_args)
2135 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2136 } else {
2137 foreach (Constructor c in instance_constructors) {
2138 try {
2139 c.Emit ();
2141 catch (Exception e) {
2142 throw new InternalErrorException (c, e);
2148 /// <summary>
2149 /// Emits the code, this step is performed after all
2150 /// the types, enumerations, constructors
2151 /// </summary>
2152 public virtual void EmitType ()
2154 if (OptAttributes != null)
2155 OptAttributes.Emit ();
2157 Emit ();
2159 EmitConstructors ();
2161 // Can not continue if constants are broken
2162 EmitConstants ();
2163 if (Report.Errors > 0)
2164 return;
2166 if (default_static_constructor != null)
2167 default_static_constructor.Emit ();
2169 if (operators != null)
2170 foreach (Operator o in operators)
2171 o.Emit ();
2173 if (properties != null)
2174 foreach (Property p in properties)
2175 p.Emit ();
2177 if (indexers != null) {
2178 foreach (Indexer indx in indexers)
2179 indx.Emit ();
2180 EmitIndexerName ();
2183 if (events != null){
2184 foreach (Event e in Events)
2185 e.Emit ();
2188 if (methods != null) {
2189 for (int i = 0; i < methods.Count; ++i)
2190 ((MethodOrOperator) methods [i]).Emit ();
2193 if (fields != null)
2194 foreach (FieldBase f in fields)
2195 f.Emit ();
2197 if (delegates != null) {
2198 foreach (Delegate d in Delegates) {
2199 d.Emit ();
2203 if (pending != null)
2204 pending.VerifyPendingMethods (Report);
2206 if (Report.Errors > 0)
2207 return;
2209 if (compiler_generated != null) {
2210 for (int i = 0; i < compiler_generated.Count; ++i)
2211 ((CompilerGeneratedClass) compiler_generated [i]).EmitType ();
2215 public override void CloseType ()
2217 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2218 return;
2220 try {
2221 caching_flags |= Flags.CloseTypeCreated;
2222 TypeBuilder.CreateType ();
2223 } catch (TypeLoadException){
2225 // This is fine, the code still created the type
2227 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
2228 // Console.WriteLine (e.Message);
2229 } catch (Exception e) {
2230 throw new InternalErrorException (this, e);
2233 if (Types != null){
2234 foreach (TypeContainer tc in Types)
2235 if (tc.Kind == MemberKind.Struct)
2236 tc.CloseType ();
2238 foreach (TypeContainer tc in Types)
2239 if (tc.Kind != MemberKind.Struct)
2240 tc.CloseType ();
2243 if (Delegates != null)
2244 foreach (Delegate d in Delegates)
2245 d.CloseType ();
2247 if (compiler_generated != null)
2248 foreach (CompilerGeneratedClass c in compiler_generated)
2249 c.CloseType ();
2251 PartialContainer = null;
2252 types = null;
2253 // properties = null;
2254 delegates = null;
2255 fields = null;
2256 initialized_fields = null;
2257 initialized_static_fields = null;
2258 constants = null;
2259 ordered_explicit_member_list = null;
2260 ordered_member_list = null;
2261 methods = null;
2262 events = null;
2263 indexers = null;
2264 operators = null;
2265 compiler_generated = null;
2266 default_constructor = null;
2267 default_static_constructor = null;
2268 type_bases = null;
2269 OptAttributes = null;
2270 ifaces = null;
2271 base_cache = null;
2272 member_cache = null;
2276 // Performs the validation on a Method's modifiers (properties have
2277 // the same properties).
2279 public bool MethodModifiersValid (MemberCore mc)
2281 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2282 const Modifiers va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2283 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2284 bool ok = true;
2285 var flags = mc.ModFlags;
2288 // At most one of static, virtual or override
2290 if ((flags & Modifiers.STATIC) != 0){
2291 if ((flags & vao) != 0){
2292 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2293 mc.GetSignatureForError ());
2294 ok = false;
2298 if (Kind == MemberKind.Struct){
2299 if ((flags & va) != 0){
2300 ModifiersExtensions.Error_InvalidModifier (mc.Location, "virtual or abstract", Report);
2301 ok = false;
2305 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2306 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2307 mc.GetSignatureForError ());
2308 ok = false;
2312 // If the declaration includes the abstract modifier, then the
2313 // declaration does not include static, virtual or extern
2315 if ((flags & Modifiers.ABSTRACT) != 0){
2316 if ((flags & Modifiers.EXTERN) != 0){
2317 Report.Error (
2318 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2319 ok = false;
2322 if ((flags & Modifiers.SEALED) != 0) {
2323 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2324 ok = false;
2327 if ((flags & Modifiers.VIRTUAL) != 0){
2328 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2329 ok = false;
2332 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2333 Report.SymbolRelatedToPreviousError (this);
2334 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2335 mc.GetSignatureForError (), GetSignatureForError ());
2336 ok = false;
2340 if ((flags & Modifiers.PRIVATE) != 0){
2341 if ((flags & vao) != 0){
2342 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2343 ok = false;
2347 if ((flags & Modifiers.SEALED) != 0){
2348 if ((flags & Modifiers.OVERRIDE) == 0){
2349 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2350 ok = false;
2354 return ok;
2357 public Constructor DefaultStaticConstructor {
2358 get { return default_static_constructor; }
2361 protected override bool VerifyClsCompliance ()
2363 if (!base.VerifyClsCompliance ())
2364 return false;
2366 VerifyClsName ();
2368 Type base_type = TypeBuilder.BaseType;
2369 if (base_type != null && !AttributeTester.IsClsCompliant (base_type)) {
2370 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (base_type));
2372 return true;
2376 /// <summary>
2377 /// Checks whether container name is CLS Compliant
2378 /// </summary>
2379 void VerifyClsName ()
2381 Dictionary<string, object> base_members = base_cache == null ?
2382 new Dictionary<string, object> () :
2383 base_cache.GetPublicMembers ();
2384 var this_members = new Dictionary<string, object> ();
2386 foreach (var entry in defined_names) {
2387 MemberCore mc = entry.Value;
2388 if (!mc.IsClsComplianceRequired ())
2389 continue;
2391 string name = entry.Key;
2392 string basename = name.Substring (name.LastIndexOf ('.') + 1);
2394 string lcase = basename.ToLower (System.Globalization.CultureInfo.InvariantCulture);
2395 object found;
2396 if (!base_members.TryGetValue (lcase, out found)) {
2397 if (!this_members.TryGetValue (lcase, out found)) {
2398 this_members.Add (lcase, mc);
2399 continue;
2403 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
2404 continue;
2406 if (found is MemberInfo) {
2407 if (basename == ((MemberInfo) found).Name)
2408 continue;
2409 Report.SymbolRelatedToPreviousError ((MemberInfo) found);
2410 } else {
2411 Report.SymbolRelatedToPreviousError ((MemberCore) found);
2414 Report.Warning (3005, 1, mc.Location, "Identifier `{0}' differing only in case is not CLS-compliant", mc.GetSignatureForError ());
2419 /// <summary>
2420 /// Performs checks for an explicit interface implementation. First it
2421 /// checks whether the `interface_type' is a base inteface implementation.
2422 /// Then it checks whether `name' exists in the interface type.
2423 /// </summary>
2424 public bool VerifyImplements (InterfaceMemberBase mb)
2426 if (ifaces != null) {
2427 foreach (Type t in ifaces){
2428 if (TypeManager.IsEqual (t, mb.InterfaceType))
2429 return true;
2433 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2434 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2435 mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType));
2436 return false;
2439 public override Type LookupAnyGeneric (string typeName)
2441 if (types != null) {
2442 foreach (TypeContainer tc in types) {
2443 if (!tc.IsGeneric)
2444 continue;
2446 int pos = tc.Basename.LastIndexOf ('`');
2447 if (pos == typeName.Length && String.Compare (typeName, 0, tc.Basename, 0, pos) == 0)
2448 return tc.TypeBuilder;
2452 return base.LookupAnyGeneric (typeName);
2455 public void Mark_HasEquals ()
2457 cached_method |= CachedMethods.Equals;
2460 public void Mark_HasGetHashCode ()
2462 cached_method |= CachedMethods.GetHashCode;
2465 /// <summary>
2466 /// Method container contains Equals method
2467 /// </summary>
2468 public bool HasEquals {
2469 get {
2470 return (cached_method & CachedMethods.Equals) != 0;
2474 /// <summary>
2475 /// Method container contains GetHashCode method
2476 /// </summary>
2477 public bool HasGetHashCode {
2478 get {
2479 return (cached_method & CachedMethods.GetHashCode) != 0;
2483 public bool HasStaticFieldInitializer {
2484 get {
2485 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2487 set {
2488 if (value)
2489 cached_method |= CachedMethods.HasStaticFieldInitializer;
2490 else
2491 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2496 // IMemberContainer
2499 string IMemberContainer.Name {
2500 get {
2501 return Name;
2505 Type IMemberContainer.Type {
2506 get {
2507 return TypeBuilder;
2511 bool IMemberContainer.IsInterface {
2512 get {
2513 return Kind == MemberKind.Interface;
2517 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2519 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2521 if (GenericType != null)
2522 return TypeManager.FindMembers (GenericType, mt, new_bf,
2523 null, null);
2524 else
2525 return FindMembers (mt, new_bf, null, null);
2529 // Generates xml doc comments (if any), and if required,
2530 // handle warning report.
2532 internal override void GenerateDocComment (DeclSpace ds)
2534 DocUtil.GenerateTypeDocComment (this, ds, Report);
2537 public override string DocCommentHeader {
2538 get { return "T:"; }
2541 public MemberCache BaseCache {
2542 get {
2543 if (base_cache != null)
2544 return base_cache;
2545 if (TypeBuilder.BaseType != null)
2546 base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
2547 if (TypeBuilder.IsInterface)
2548 base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
2549 return base_cache;
2554 public abstract class ClassOrStruct : TypeContainer
2556 Dictionary<SecurityAction, PermissionSet> declarative_security;
2558 public ClassOrStruct (NamespaceEntry ns, DeclSpace parent,
2559 MemberName name, Attributes attrs, MemberKind kind)
2560 : base (ns, parent, name, attrs, kind)
2564 protected override bool AddToContainer (MemberCore symbol, string name)
2566 if (name == MemberName.Name) {
2567 if (symbol is TypeParameter) {
2568 Report.Error (694, symbol.Location,
2569 "Type parameter `{0}' has same name as containing type, or method",
2570 symbol.GetSignatureForError ());
2571 return false;
2574 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2575 if (imb == null || !imb.IsExplicitImpl) {
2576 Report.SymbolRelatedToPreviousError (this);
2577 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2578 symbol.GetSignatureForError ());
2579 return false;
2583 return base.AddToContainer (symbol, name);
2586 public override void VerifyMembers ()
2588 base.VerifyMembers ();
2590 if ((events != null) && Report.WarningLevel >= 3) {
2591 foreach (Event e in events){
2592 // Note: The event can be assigned from same class only, so we can report
2593 // this warning for all accessibility modes
2594 if ((e.caching_flags & Flags.IsUsed) == 0)
2595 Report.Warning (67, 3, e.Location, "The event `{0}' is never used", e.GetSignatureForError ());
2600 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2602 if (a.IsValidSecurityAttribute ()) {
2603 if (declarative_security == null)
2604 declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
2606 a.ExtractSecurityPermissionSet (declarative_security);
2607 return;
2610 if (a.Type == pa.StructLayout) {
2611 PartialContainer.HasStructLayout = true;
2613 if (a.GetLayoutKindValue () == LayoutKind.Explicit)
2614 PartialContainer.HasExplicitLayout = true;
2617 if (a.Type == pa.Dynamic) {
2618 a.Error_MisusedDynamicAttribute ();
2619 return;
2622 base.ApplyAttributeBuilder (a, cb, pa);
2625 /// <summary>
2626 /// Defines the default constructors
2627 /// </summary>
2628 protected void DefineDefaultConstructor (bool is_static)
2630 // The default instance constructor is public
2631 // If the class is abstract, the default constructor is protected
2632 // The default static constructor is private
2634 Modifiers mods;
2635 if (is_static) {
2636 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2637 } else {
2638 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2641 Constructor c = new Constructor (this, MemberName.Name, mods,
2642 null, ParametersCompiled.EmptyReadOnlyParameters,
2643 new GeneratedBaseInitializer (Location),
2644 Location);
2646 AddConstructor (c);
2647 c.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
2650 protected override bool DoDefineMembers ()
2652 CheckProtectedModifier ();
2654 base.DoDefineMembers ();
2656 if (default_static_constructor != null)
2657 default_static_constructor.Define ();
2659 return true;
2662 public override void Emit ()
2664 if (default_static_constructor == null && PartialContainer.HasStaticFieldInitializer) {
2665 DefineDefaultConstructor (true);
2666 default_static_constructor.Define ();
2669 base.Emit ();
2671 if (declarative_security != null) {
2672 foreach (var de in declarative_security) {
2673 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2678 public override ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
2680 DeclSpace top_level = Parent;
2681 if (top_level != null) {
2682 while (top_level.Parent != null)
2683 top_level = top_level.Parent;
2685 var candidates = NamespaceEntry.NS.LookupExtensionMethod (extensionType, this, name);
2686 if (candidates != null)
2687 return new ExtensionMethodGroupExpr (candidates, NamespaceEntry, extensionType, loc);
2690 return NamespaceEntry.LookupExtensionMethod (extensionType, name, loc);
2693 protected override TypeAttributes TypeAttr {
2694 get {
2695 if (default_static_constructor == null)
2696 return base.TypeAttr | TypeAttributes.BeforeFieldInit;
2698 return base.TypeAttr;
2704 // TODO: should be sealed
2705 public class Class : ClassOrStruct {
2706 const Modifiers AllowedModifiers =
2707 Modifiers.NEW |
2708 Modifiers.PUBLIC |
2709 Modifiers.PROTECTED |
2710 Modifiers.INTERNAL |
2711 Modifiers.PRIVATE |
2712 Modifiers.ABSTRACT |
2713 Modifiers.SEALED |
2714 Modifiers.STATIC |
2715 Modifiers.UNSAFE;
2717 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2719 public Class (NamespaceEntry ns, DeclSpace parent, MemberName name, Modifiers mod,
2720 Attributes attrs)
2721 : base (ns, parent, name, attrs, MemberKind.Class)
2723 var accmods = Parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2724 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2726 if (IsStatic && RootContext.Version == LanguageVersion.ISO_1) {
2727 Report.FeatureIsNotAvailable (Location, "static classes");
2731 public override void AddBasesForPart (DeclSpace part, List<FullNamedExpression> bases)
2733 if (part.Name == "System.Object")
2734 Report.Error (537, part.Location,
2735 "The class System.Object cannot have a base class or implement an interface.");
2736 base.AddBasesForPart (part, bases);
2739 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2741 if (a.Type == pa.AttributeUsage) {
2742 if (!TypeManager.IsAttributeType (BaseType) &&
2743 TypeBuilder.FullName != "System.Attribute") {
2744 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2748 if (a.Type == pa.Conditional && !TypeManager.IsAttributeType (BaseType)) {
2749 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2750 return;
2753 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2754 a.Error_MissingGuidAttribute ();
2755 return;
2758 if (a.Type == pa.Extension) {
2759 a.Error_MisusedExtensionAttribute ();
2760 return;
2763 if (AttributeTester.IsAttributeExcluded (a.Type, Location))
2764 return;
2766 base.ApplyAttributeBuilder (a, cb, pa);
2769 public override AttributeTargets AttributeTargets {
2770 get {
2771 return AttributeTargets.Class;
2775 protected override void DefineContainerMembers (System.Collections.IList list)
2777 if (list == null)
2778 return;
2780 if (!IsStatic) {
2781 base.DefineContainerMembers (list);
2782 return;
2785 foreach (MemberCore m in list) {
2786 if (m is Operator) {
2787 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2788 continue;
2791 if (m is Destructor) {
2792 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2793 continue;
2796 if (m is Indexer) {
2797 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2798 continue;
2801 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is Enum || m is Delegate)
2802 continue;
2804 if (m is Constructor) {
2805 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2806 continue;
2809 Method method = m as Method;
2810 if (method != null && method.Parameters.HasExtensionMethodType) {
2811 Report.Error (1105, m.Location, "`{0}': Extension methods must be declared static", m.GetSignatureForError ());
2812 continue;
2815 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2818 base.DefineContainerMembers (list);
2821 protected override bool DoDefineMembers ()
2823 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2824 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2827 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2828 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2831 if (InstanceConstructors == null && !IsStatic)
2832 DefineDefaultConstructor (false);
2834 return base.DoDefineMembers ();
2837 public override void Emit ()
2839 base.Emit ();
2841 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2842 PredefinedAttributes.Get.Extension.EmitAttribute (TypeBuilder);
2845 protected override TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
2847 TypeExpr[] ifaces = base.ResolveBaseTypes (out base_class);
2849 if (base_class == null) {
2850 if (RootContext.StdLib)
2851 base_class = TypeManager.system_object_expr;
2852 else if (Name != "System.Object")
2853 base_class = TypeManager.system_object_expr;
2854 } else {
2855 if (Kind == MemberKind.Class && TypeManager.IsGenericParameter (base_class.Type)){
2856 Report.Error (
2857 689, base_class.Location,
2858 "Cannot derive from `{0}' because it is a type parameter",
2859 base_class.GetSignatureForError ());
2860 return ifaces;
2863 if (IsGeneric && TypeManager.IsAttributeType (base_class.Type)) {
2864 Report.Error (698, base_class.Location,
2865 "A generic type cannot derive from `{0}' because it is an attribute class",
2866 base_class.GetSignatureForError ());
2869 if (base_class.IsSealed){
2870 Report.SymbolRelatedToPreviousError (base_class.Type);
2871 if (base_class.Type.IsAbstract) {
2872 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2873 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
2874 } else {
2875 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2876 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
2878 return ifaces;
2881 if (!base_class.CanInheritFrom ()){
2882 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2883 GetSignatureForError (), base_class.GetSignatureForError ());
2884 return ifaces;
2887 if (!IsAccessibleAs (base_class.Type)) {
2888 Report.SymbolRelatedToPreviousError (base_class.Type);
2889 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2890 TypeManager.CSharpName (base_class.Type), GetSignatureForError ());
2894 if (PartialContainer.IsStaticClass) {
2895 if (base_class.Type != TypeManager.object_type) {
2896 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2897 GetSignatureForError (), base_class.GetSignatureForError ());
2898 return ifaces;
2901 if (ifaces != null) {
2902 foreach (TypeExpr t in ifaces)
2903 Report.SymbolRelatedToPreviousError (t.Type);
2904 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2908 return ifaces;
2911 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2912 /// Valid only for attribute classes.
2913 public bool IsExcluded ()
2915 if ((caching_flags & Flags.Excluded_Undetected) == 0)
2916 return (caching_flags & Flags.Excluded) != 0;
2918 caching_flags &= ~Flags.Excluded_Undetected;
2920 if (OptAttributes == null)
2921 return false;
2923 Attribute[] attrs = OptAttributes.SearchMulti (PredefinedAttributes.Get.Conditional);
2924 if (attrs == null)
2925 return false;
2927 foreach (Attribute a in attrs) {
2928 string condition = a.GetConditionalAttributeValue ();
2929 if (Location.CompilationUnit.IsConditionalDefined (condition))
2930 return false;
2933 caching_flags |= Flags.Excluded;
2934 return true;
2938 // FIXME: How do we deal with the user specifying a different
2939 // layout?
2941 protected override TypeAttributes TypeAttr {
2942 get {
2943 TypeAttributes ta = base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2944 if (IsStatic)
2945 ta |= StaticClassAttribute;
2946 return ta;
2951 public sealed class Struct : ClassOrStruct {
2953 bool is_unmanaged, has_unmanaged_check_done;
2955 // <summary>
2956 // Modifiers allowed in a struct declaration
2957 // </summary>
2958 const Modifiers AllowedModifiers =
2959 Modifiers.NEW |
2960 Modifiers.PUBLIC |
2961 Modifiers.PROTECTED |
2962 Modifiers.INTERNAL |
2963 Modifiers.UNSAFE |
2964 Modifiers.PRIVATE;
2966 public Struct (NamespaceEntry ns, DeclSpace parent, MemberName name,
2967 Modifiers mod, Attributes attrs)
2968 : base (ns, parent, name, attrs, MemberKind.Struct)
2970 var accmods = parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2972 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2974 this.ModFlags |= Modifiers.SEALED;
2977 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2979 base.ApplyAttributeBuilder (a, cb, pa);
2982 // When struct constains fixed fixed and struct layout has explicitly
2983 // set CharSet, its value has to be propagated to compiler generated
2984 // fixed field types
2986 if (a.Type == pa.StructLayout && Fields != null && a.HasField ("CharSet")) {
2987 for (int i = 0; i < Fields.Count; ++i) {
2988 FixedField ff = Fields [i] as FixedField;
2989 if (ff != null)
2990 ff.SetCharSet (TypeBuilder.Attributes);
2995 public override AttributeTargets AttributeTargets {
2996 get {
2997 return AttributeTargets.Struct;
3001 public override bool IsUnmanagedType ()
3003 if (fields == null)
3004 return true;
3006 if (requires_delayed_unmanagedtype_check)
3007 return true;
3009 if (has_unmanaged_check_done)
3010 return is_unmanaged;
3012 has_unmanaged_check_done = true;
3014 foreach (FieldBase f in fields) {
3015 if ((f.ModFlags & Modifiers.STATIC) != 0)
3016 continue;
3018 // It can happen when recursive unmanaged types are defined
3019 // struct S { S* s; }
3020 Type mt = f.MemberType;
3021 if (mt == null) {
3022 has_unmanaged_check_done = false;
3023 requires_delayed_unmanagedtype_check = true;
3024 return true;
3027 // TODO: Remove when pointer types are under mcs control
3028 while (mt.IsPointer)
3029 mt = TypeManager.GetElementType (mt);
3030 if (TypeManager.IsEqual (mt, TypeBuilder))
3031 continue;
3033 if (TypeManager.IsUnmanagedType (mt))
3034 continue;
3036 return false;
3039 is_unmanaged = true;
3040 return true;
3043 protected override TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
3045 TypeExpr[] ifaces = base.ResolveBaseTypes (out base_class);
3047 // If we are compiling our runtime,
3048 // and we are defining ValueType, then our
3049 // base is `System.Object'.
3051 if (base_class == null) {
3052 if (!RootContext.StdLib && Name == "System.ValueType")
3053 base_class = TypeManager.system_object_expr;
3054 else
3055 base_class = TypeManager.system_valuetype_expr;
3058 return ifaces;
3062 // FIXME: Allow the user to specify a different set of attributes
3063 // in some cases (Sealed for example is mandatory for a class,
3064 // but what SequentialLayout can be changed
3066 protected override TypeAttributes TypeAttr {
3067 get {
3068 const TypeAttributes DefaultTypeAttributes =
3069 TypeAttributes.SequentialLayout |
3070 TypeAttributes.Sealed;
3072 return base.TypeAttr | DefaultTypeAttributes;
3076 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
3078 if ((field.ModFlags & Modifiers.STATIC) == 0) {
3079 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
3080 field.GetSignatureForError ());
3081 return;
3083 base.RegisterFieldForInitialization (field, expression);
3088 /// <summary>
3089 /// Interfaces
3090 /// </summary>
3091 public sealed class Interface : TypeContainer, IMemberContainer {
3093 /// <summary>
3094 /// Modifiers allowed in a class declaration
3095 /// </summary>
3096 public const Modifiers AllowedModifiers =
3097 Modifiers.NEW |
3098 Modifiers.PUBLIC |
3099 Modifiers.PROTECTED |
3100 Modifiers.INTERNAL |
3101 Modifiers.UNSAFE |
3102 Modifiers.PRIVATE;
3104 public Interface (NamespaceEntry ns, DeclSpace parent, MemberName name, Modifiers mod,
3105 Attributes attrs)
3106 : base (ns, parent, name, attrs, MemberKind.Interface)
3108 var accmods = parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3110 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
3113 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
3115 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3116 a.Error_MissingGuidAttribute ();
3117 return;
3120 base.ApplyAttributeBuilder (a, cb, pa);
3124 public override AttributeTargets AttributeTargets {
3125 get {
3126 return AttributeTargets.Interface;
3130 protected override TypeAttributes TypeAttr {
3131 get {
3132 const TypeAttributes DefaultTypeAttributes =
3133 TypeAttributes.AutoLayout |
3134 TypeAttributes.Abstract |
3135 TypeAttributes.Interface;
3137 return base.TypeAttr | DefaultTypeAttributes;
3141 protected override bool VerifyClsCompliance ()
3143 if (!base.VerifyClsCompliance ())
3144 return false;
3146 if (ifaces != null) {
3147 foreach (Type t in ifaces) {
3148 if (AttributeTester.IsClsCompliant (t))
3149 continue;
3151 Report.SymbolRelatedToPreviousError (t);
3152 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3153 GetSignatureForError (), TypeManager.CSharpName (t));
3157 return true;
3161 public abstract class InterfaceMemberBase : MemberBase {
3163 // Whether this is an interface member.
3165 public bool IsInterface;
3168 // If true, this is an explicit interface implementation
3170 public bool IsExplicitImpl;
3172 protected bool is_external_implementation;
3175 // The interface type we are explicitly implementing
3177 public Type InterfaceType;
3180 // The method we're overriding if this is an override method.
3182 protected MethodInfo base_method;
3184 readonly Modifiers explicit_mod_flags;
3185 public MethodAttributes flags;
3187 public InterfaceMemberBase (DeclSpace parent, GenericMethod generic,
3188 FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
3189 MemberName name, Attributes attrs)
3190 : base (parent, generic, type, mod, allowed_mod, Modifiers.PRIVATE,
3191 name, attrs)
3193 IsInterface = parent.PartialContainer.Kind == MemberKind.Interface;
3194 IsExplicitImpl = (MemberName.Left != null);
3195 explicit_mod_flags = mod;
3198 protected override bool CheckBase ()
3200 if (!base.CheckBase ())
3201 return false;
3203 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3204 CheckForDuplications ();
3206 if (IsExplicitImpl || this is Destructor)
3207 return true;
3209 // Is null for System.Object while compiling corlib and base interfaces
3210 if (Parent.PartialContainer.BaseCache == null) {
3211 if ((ModFlags & Modifiers.NEW) != 0) {
3212 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3214 return true;
3217 Type base_ret_type = null;
3218 base_method = FindOutBaseMethod (ref base_ret_type);
3220 // method is override
3221 if (base_method != null) {
3222 if (!CheckMethodAgainstBase (base_ret_type))
3223 return false;
3225 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3226 ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (base_method);
3227 if (oa != null) {
3228 if (OptAttributes == null || !OptAttributes.Contains (PredefinedAttributes.Get.Obsolete)) {
3229 Report.SymbolRelatedToPreviousError (base_method);
3230 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3231 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3233 } else {
3234 if (OptAttributes != null && OptAttributes.Contains (PredefinedAttributes.Get.Obsolete)) {
3235 Report.SymbolRelatedToPreviousError (base_method);
3236 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3237 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3241 return true;
3244 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Name, !((this is Event) || (this is Property)));
3245 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3246 if (conflict_symbol != null) {
3247 Report.SymbolRelatedToPreviousError (conflict_symbol);
3248 if (this is Event)
3249 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3250 else if (this is PropertyBase)
3251 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3252 else
3253 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3254 } else {
3255 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3256 GetSignatureForError (), SimpleName.GetMemberType (this));
3258 return false;
3261 if (conflict_symbol == null) {
3262 if ((ModFlags & Modifiers.NEW) != 0) {
3263 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3265 return true;
3268 if ((ModFlags & Modifiers.NEW) == 0) {
3269 if (this is MethodOrOperator && conflict_symbol.MemberType == MemberTypes.Method)
3270 return true;
3272 Report.SymbolRelatedToPreviousError (conflict_symbol);
3273 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3274 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3277 return true;
3280 protected virtual bool CheckForDuplications ()
3282 return Parent.MemberCache.CheckExistingMembersOverloads (
3283 this, GetFullName (MemberName), ParametersCompiled.EmptyReadOnlyParameters, Report);
3287 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3288 // that have been defined.
3290 // `name' is the user visible name for reporting errors (this is used to
3291 // provide the right name regarding method names and properties)
3293 bool CheckMethodAgainstBase (Type base_method_type)
3295 bool ok = true;
3297 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3298 if (!(base_method.IsAbstract || base_method.IsVirtual)){
3299 Report.SymbolRelatedToPreviousError (base_method);
3300 Report.Error (506, Location,
3301 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3302 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3303 ok = false;
3306 // Now we check that the overriden method is not final
3308 if (base_method.IsFinal) {
3309 Report.SymbolRelatedToPreviousError (base_method);
3310 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3311 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3312 ok = false;
3315 // Check that the permissions are not being changed
3317 MethodAttributes thisp = flags & MethodAttributes.MemberAccessMask;
3318 MethodAttributes base_classp = base_method.Attributes & MethodAttributes.MemberAccessMask;
3320 if (!CheckAccessModifiers (thisp, base_classp, base_method)) {
3321 Error_CannotChangeAccessModifiers (Location, base_method, base_classp, null);
3322 ok = false;
3325 if (!TypeManager.IsEqual (MemberType, TypeManager.TypeToCoreType (base_method_type))) {
3326 Report.SymbolRelatedToPreviousError (base_method);
3327 if (this is PropertyBasedMember) {
3328 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3329 GetSignatureForError (), TypeManager.CSharpName (base_method_type), TypeManager.CSharpSignature (base_method));
3331 else {
3332 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3333 GetSignatureForError (), TypeManager.CSharpName (base_method_type), TypeManager.CSharpSignature (base_method));
3335 ok = false;
3339 if ((ModFlags & Modifiers.NEW) == 0) {
3340 if ((ModFlags & Modifiers.OVERRIDE) == 0) {
3341 ModFlags |= Modifiers.NEW;
3342 Report.SymbolRelatedToPreviousError (base_method);
3343 if (!IsInterface && (base_method.IsVirtual || base_method.IsAbstract)) {
3344 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",
3345 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3346 if (base_method.IsAbstract){
3347 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3348 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3349 ok = false;
3351 } else {
3352 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3353 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3356 } else {
3357 if (base_method.IsAbstract && !IsInterface) {
3358 Report.SymbolRelatedToPreviousError (base_method);
3359 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3360 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3361 return ok = false;
3365 return ok;
3368 protected bool CheckAccessModifiers (MethodAttributes thisp, MethodAttributes base_classp, MethodInfo base_method)
3370 if ((base_classp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3372 // when overriding protected internal, the method can be declared
3373 // protected internal only within the same assembly or assembly
3374 // which has InternalsVisibleTo
3376 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3377 return TypeManager.IsThisOrFriendAssembly (Parent.Module.Assembly, base_method.DeclaringType.Assembly);
3378 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3380 // if it's not "protected internal", it must be "protected"
3383 return false;
3384 } else if (Parent.TypeBuilder.Assembly == base_method.DeclaringType.Assembly) {
3386 // protected within the same assembly - an error
3388 return false;
3389 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3390 (base_classp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3392 // protected ok, but other attributes differ - report an error
3394 return false;
3396 return true;
3397 } else {
3398 return (thisp == base_classp);
3402 public override bool Define ()
3404 if (IsInterface) {
3405 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3406 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3408 flags = MethodAttributes.Public |
3409 MethodAttributes.Abstract |
3410 MethodAttributes.HideBySig |
3411 MethodAttributes.NewSlot |
3412 MethodAttributes.Virtual;
3413 } else {
3414 Parent.PartialContainer.MethodModifiersValid (this);
3416 flags = ModifiersExtensions.MethodAttr (ModFlags);
3419 if (IsExplicitImpl) {
3420 TypeExpr iface_texpr = MemberName.Left.GetTypeExpression ().ResolveAsTypeTerminal (this, false);
3421 if (iface_texpr == null)
3422 return false;
3424 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3425 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3426 GetSignatureForError ());
3429 InterfaceType = iface_texpr.Type;
3431 if (!InterfaceType.IsInterface) {
3432 Report.SymbolRelatedToPreviousError (InterfaceType);
3433 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3434 TypeManager.CSharpName (InterfaceType));
3435 } else {
3436 Parent.PartialContainer.VerifyImplements (this);
3439 ModifiersExtensions.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location, Report);
3442 return base.Define ();
3445 protected bool DefineParameters (ParametersCompiled parameters)
3447 if (!parameters.Resolve (this))
3448 return false;
3450 bool error = false;
3451 for (int i = 0; i < parameters.Count; ++i) {
3452 Parameter p = parameters [i];
3454 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3455 p.Warning_UselessOptionalParameter (Report);
3457 if (p.CheckAccessibility (this))
3458 continue;
3460 Type t = parameters.Types [i];
3461 Report.SymbolRelatedToPreviousError (t);
3462 if (this is Indexer)
3463 Report.Error (55, Location,
3464 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3465 TypeManager.CSharpName (t), GetSignatureForError ());
3466 else if (this is Operator)
3467 Report.Error (57, Location,
3468 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3469 TypeManager.CSharpName (t), GetSignatureForError ());
3470 else
3471 Report.Error (51, Location,
3472 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3473 TypeManager.CSharpName (t), GetSignatureForError ());
3474 error = true;
3476 return !error;
3479 public override void Emit()
3481 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3482 // We are more strict than csc and report this as an error because SRE does not allow emit that
3483 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation) {
3484 if (this is Constructor) {
3485 Report.Error (824, Location,
3486 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3487 } else {
3488 Report.Error (626, Location,
3489 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3490 GetSignatureForError ());
3494 base.Emit ();
3497 public override bool EnableOverloadChecks (MemberCore overload)
3500 // Two members can differ in their explicit interface
3501 // type parameter only
3503 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3504 if (imb != null && imb.IsExplicitImpl) {
3505 if (IsExplicitImpl) {
3506 caching_flags |= Flags.MethodOverloadsExist;
3508 return true;
3511 return IsExplicitImpl;
3514 protected void Error_CannotChangeAccessModifiers (Location loc, MemberInfo base_method, MethodAttributes ma, string suffix)
3516 Report.SymbolRelatedToPreviousError (base_method);
3517 string base_name = TypeManager.GetFullNameSignature (base_method);
3518 string this_name = GetSignatureForError ();
3519 if (suffix != null) {
3520 base_name += suffix;
3521 this_name += suffix;
3524 Report.Error (507, loc, "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3525 this_name, ModifiersExtensions.GetDescription (ma), base_name);
3528 protected static string Error722 {
3529 get {
3530 return "`{0}': static types cannot be used as return types";
3534 /// <summary>
3535 /// Gets base method and its return type
3536 /// </summary>
3537 protected abstract MethodInfo FindOutBaseMethod (ref Type base_ret_type);
3540 // The "short" name of this property / indexer / event. This is the
3541 // name without the explicit interface.
3543 public string ShortName
3545 get { return MemberName.Name; }
3546 set { SetMemberName (new MemberName (MemberName.Left, value, Location)); }
3550 // Returns full metadata method name
3552 public string GetFullName (MemberName name)
3554 if (!IsExplicitImpl)
3555 return name.Name;
3558 // When dealing with explicit members a full interface type
3559 // name is added to member name to avoid possible name conflicts
3561 // We use CSharpName which gets us full name with benefit of
3562 // replacing predefined names which saves some space and name
3563 // is still unique
3565 return TypeManager.CSharpName (InterfaceType) + "." + name.Name;
3568 protected override bool VerifyClsCompliance ()
3570 if (!base.VerifyClsCompliance ()) {
3571 if (IsInterface && HasClsCompliantAttribute && Parent.IsClsComplianceRequired ()) {
3572 Report.Warning (3010, 1, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
3575 if ((ModFlags & Modifiers.ABSTRACT) != 0 && Parent.TypeBuilder.IsClass && IsExposedFromAssembly () && Parent.IsClsComplianceRequired ()) {
3576 Report.Warning (3011, 1, Location, "`{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
3578 return false;
3581 if (GenericMethod != null)
3582 GenericMethod.VerifyClsCompliance ();
3584 return true;
3587 public override bool IsUsed
3589 get { return IsExplicitImpl || base.IsUsed; }
3594 public abstract class MemberBase : MemberCore
3596 protected FullNamedExpression type_name;
3597 protected Type member_type;
3599 public readonly DeclSpace ds;
3600 public readonly GenericMethod GenericMethod;
3602 protected MemberBase (DeclSpace parent, GenericMethod generic,
3603 FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod,
3604 MemberName name, Attributes attrs)
3605 : base (parent, name, attrs)
3607 this.ds = generic != null ? generic : (DeclSpace) parent;
3608 this.type_name = type;
3609 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3610 GenericMethod = generic;
3611 if (GenericMethod != null)
3612 GenericMethod.ModFlags = ModFlags;
3616 // Main member define entry
3618 public override bool Define ()
3620 DoMemberTypeIndependentChecks ();
3623 // Returns false only when type resolution failed
3625 if (!ResolveMemberType ())
3626 return false;
3628 DoMemberTypeDependentChecks ();
3629 return true;
3633 // Any type_name independent checks
3635 protected virtual void DoMemberTypeIndependentChecks ()
3637 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3638 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3639 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3640 GetSignatureForError (), Parent.GetSignatureForError ());
3645 // Any type_name dependent checks
3647 protected virtual void DoMemberTypeDependentChecks ()
3649 // verify accessibility
3650 if (!IsAccessibleAs (MemberType)) {
3651 Report.SymbolRelatedToPreviousError (MemberType);
3652 if (this is Property)
3653 Report.Error (53, Location,
3654 "Inconsistent accessibility: property type `" +
3655 TypeManager.CSharpName (MemberType) + "' is less " +
3656 "accessible than property `" + GetSignatureForError () + "'");
3657 else if (this is Indexer)
3658 Report.Error (54, Location,
3659 "Inconsistent accessibility: indexer return type `" +
3660 TypeManager.CSharpName (MemberType) + "' is less " +
3661 "accessible than indexer `" + GetSignatureForError () + "'");
3662 else if (this is MethodCore) {
3663 if (this is Operator)
3664 Report.Error (56, Location,
3665 "Inconsistent accessibility: return type `" +
3666 TypeManager.CSharpName (MemberType) + "' is less " +
3667 "accessible than operator `" + GetSignatureForError () + "'");
3668 else
3669 Report.Error (50, Location,
3670 "Inconsistent accessibility: return type `" +
3671 TypeManager.CSharpName (MemberType) + "' is less " +
3672 "accessible than method `" + GetSignatureForError () + "'");
3673 } else {
3674 Report.Error (52, Location,
3675 "Inconsistent accessibility: field type `" +
3676 TypeManager.CSharpName (MemberType) + "' is less " +
3677 "accessible than field `" + GetSignatureForError () + "'");
3681 Variance variance = this is Event ? Variance.Contravariant : Variance.Covariant;
3682 TypeManager.CheckTypeVariance (MemberType, variance, this);
3685 protected bool IsTypePermitted ()
3687 if (TypeManager.IsSpecialType (MemberType)) {
3688 Report.Error (610, Location, "Field or property cannot be of type `{0}'", TypeManager.CSharpName (MemberType));
3689 return false;
3691 return true;
3694 protected virtual bool CheckBase ()
3696 CheckProtectedModifier ();
3698 return true;
3701 public Type MemberType {
3702 get { return member_type; }
3705 protected virtual bool ResolveMemberType ()
3707 if (member_type != null)
3708 throw new InternalErrorException ("Multi-resolve");
3710 TypeExpr te = type_name.ResolveAsTypeTerminal (this, false);
3711 if (te == null)
3712 return false;
3715 // Replace original type name, error reporting can use fully resolved name
3717 type_name = te;
3719 member_type = te.Type;
3720 return true;