2 // class.cs: Class and Struct handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@ximian.com)
6 // Marek Safar (marek.safar@gmail.com)
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2008 Novell, Inc
12 // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
16 using System.Collections.Generic;
17 using System.Runtime.InteropServices;
18 using System.Security;
19 using System.Security.Permissions;
23 using XmlElement = System.Object;
27 using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
28 using IKVM.Reflection;
29 using IKVM.Reflection.Emit;
31 using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
32 using System.Reflection;
33 using System.Reflection.Emit;
39 public interface ITypesContainer
41 Location Location { get; }
42 MemberName MemberName { get; }
46 /// This is the base class for structs and classes.
48 public abstract class TypeContainer : DeclSpace, ITypeDefinition, ITypesContainer
51 // Different context is needed when resolving type container base
52 // types. Type names come from the parent scope but type parameter
53 // names from the container scope.
55 public struct BaseContext : IMemberContext
59 public BaseContext (TypeContainer tc)
64 #region IMemberContext Members
66 public CompilerContext Compiler {
67 get { return tc.Compiler; }
70 public TypeSpec CurrentType {
71 get { return tc.Parent.CurrentType; }
74 public TypeParameter[] CurrentTypeParameters {
75 get { return tc.PartialContainer.CurrentTypeParameters; }
78 public MemberCore CurrentMemberDefinition {
82 public bool IsObsolete {
83 get { return tc.IsObsolete; }
86 public bool IsUnsafe {
87 get { return tc.IsUnsafe; }
90 public bool IsStatic {
91 get { return tc.IsStatic; }
94 public ModuleContainer Module {
95 get { return tc.Module; }
98 public string GetSignatureForError ()
100 return tc.GetSignatureForError ();
103 public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
108 public FullNamedExpression LookupNamespaceAlias (string name)
110 return tc.Parent.LookupNamespaceAlias (name);
113 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
116 TypeParameter[] tp = CurrentTypeParameters;
118 TypeParameter t = TypeParameter.FindTypeParameter (tp, name);
120 return new TypeParameterExpr (t, loc);
124 return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc);
134 GetHashCode = 1 << 1,
135 HasStaticFieldInitializer = 1 << 2
139 // Whether this is a struct, class or interface
140 public readonly MemberKind Kind;
142 // Holds a list of classes and structures
143 protected List<TypeContainer> types;
145 List<MemberCore> ordered_explicit_member_list;
146 List<MemberCore> ordered_member_list;
148 // Holds the list of properties
149 List<MemberCore> properties;
151 // Holds the list of constructors
152 protected List<Constructor> instance_constructors;
154 // Holds the list of fields
155 protected List<FieldBase> fields;
157 // Holds a list of fields that have initializers
158 protected List<FieldInitializer> initialized_fields;
160 // Holds a list of static fields that have initializers
161 protected List<FieldInitializer> initialized_static_fields;
163 // Holds the list of constants
164 protected List<MemberCore> constants;
166 // Holds the methods.
167 List<MemberCore> methods;
170 protected List<MemberCore> events;
172 // Holds the indexers
173 List<MemberCore> indexers;
175 // Holds the operators
176 List<MemberCore> operators;
178 // Holds the compiler generated classes
179 protected List<CompilerGeneratedClass> compiler_generated;
181 Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
183 Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
186 // Pointers to the default constructor and the default static constructor
188 protected Constructor default_constructor;
189 protected Constructor default_static_constructor;
192 // Points to the first non-static field added to the container.
194 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
195 // and the first one's as good as any.
197 FieldBase first_nonstatic_field;
200 // This one is computed after we can distinguish interfaces
201 // from classes from the arraylist `type_bases'
203 protected TypeSpec base_type;
204 protected FullNamedExpression base_type_expr; // TODO: It's temporary variable
205 protected TypeSpec[] iface_exprs;
207 protected List<FullNamedExpression> type_bases;
209 bool members_defined;
210 bool members_defined_ok;
213 TypeContainer InTransit;
215 GenericTypeParameterBuilder[] all_tp_builders;
217 public const string DefaultIndexerName = "Item";
219 private bool seen_normal_indexers = false;
220 private string indexer_name = DefaultIndexerName;
221 protected bool requires_delayed_unmanagedtype_check;
224 private CachedMethods cached_method;
226 protected TypeSpec spec;
227 TypeSpec current_type;
229 List<TypeContainer> partial_parts;
231 public int DynamicSitesCounter;
234 /// The pending methods that need to be implemented
235 // (interfaces or abstract methods)
237 PendingImplementation pending;
239 public TypeContainer (NamespaceContainer ns, DeclSpace parent, MemberName name,
240 Attributes attrs, MemberKind kind)
241 : base (ns, parent, name, attrs)
243 if (parent != null && parent.NamespaceEntry != ns)
244 throw new InternalErrorException ("A nested type should be in the same NamespaceEntry as its enclosing class");
247 this.PartialContainer = this;
252 public override TypeSpec CurrentType {
254 if (current_type == null) {
257 // Switch to inflated version as it's used by all expressions
259 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Select (l => l.Type).ToArray ();
260 current_type = spec.MakeGenericType (this, targs);
270 public override TypeParameter[] CurrentTypeParameters {
272 return PartialContainer.type_params;
276 int CurrentTypeParametersStartIndex {
278 int total = all_tp_builders.Length;
279 if (CurrentTypeParameters != null) {
280 return total - CurrentTypeParameters.Length;
286 public virtual AssemblyDefinition DeclaringAssembly {
288 return Module.DeclaringAssembly;
292 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
294 return Module.DeclaringAssembly;
298 public TypeSpec Definition {
304 public bool HasMembersDefined {
306 return members_defined;
310 public TypeSpec[] Interfaces {
318 public abstract void Accept (StructuralVisitor visitor);
320 public bool AddMember (MemberCore symbol)
322 return AddToContainer (symbol, symbol.MemberName.Basename);
325 public bool AddMember (MemberCore symbol, string name)
327 return AddToContainer (symbol, name);
330 protected virtual bool AddMemberType (TypeContainer ds)
332 return AddToContainer (ds, ds.Basename);
335 protected virtual void RemoveMemberType (TypeContainer ds)
337 RemoveFromContainer (ds.Basename);
340 public void AddConstant (Const constant)
342 if (!AddMember (constant))
345 if (constants == null)
346 constants = new List<MemberCore> ();
348 constants.Add (constant);
351 public TypeContainer AddTypeContainer (TypeContainer tc)
353 if (!AddMemberType (tc))
357 types = new List<TypeContainer> ();
363 public virtual TypeContainer AddPartial (TypeContainer next_part)
365 return AddPartial (next_part, next_part.Basename);
368 protected TypeContainer AddPartial (TypeContainer next_part, string name)
370 next_part.ModFlags |= Modifiers.PARTIAL;
371 TypeContainer tc = GetDefinition (name) as TypeContainer;
373 return AddTypeContainer (next_part);
375 if ((tc.ModFlags & Modifiers.PARTIAL) == 0) {
376 Report.SymbolRelatedToPreviousError (next_part);
377 Error_MissingPartialModifier (tc);
380 if (tc.Kind != next_part.Kind) {
381 Report.SymbolRelatedToPreviousError (tc);
382 Report.Error (261, next_part.Location,
383 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
384 next_part.GetSignatureForError ());
387 if ((tc.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) &&
388 ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 &&
389 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
390 Report.SymbolRelatedToPreviousError (tc);
391 Report.Error (262, next_part.Location,
392 "Partial declarations of `{0}' have conflicting accessibility modifiers",
393 next_part.GetSignatureForError ());
396 if (tc.partial_parts == null)
397 tc.partial_parts = new List<TypeContainer> (1);
399 if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
400 tc.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
401 } else if ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
402 tc.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
403 tc.ModFlags |= next_part.ModFlags;
405 tc.ModFlags |= next_part.ModFlags;
408 tc.spec.Modifiers = tc.ModFlags;
410 if (next_part.attributes != null) {
411 if (tc.attributes == null)
412 tc.attributes = next_part.attributes;
414 tc.attributes.AddAttributes (next_part.attributes.Attrs);
417 next_part.PartialContainer = tc;
418 tc.partial_parts.Add (next_part);
422 public virtual void RemoveTypeContainer (TypeContainer next_part)
425 types.Remove (next_part);
427 Cache.Remove (next_part.Basename);
428 RemoveMemberType (next_part);
431 public void AddDelegate (Delegate d)
433 AddTypeContainer (d);
436 private void AddMemberToList (MemberCore mc, List<MemberCore> alist, bool isexplicit)
438 if (ordered_explicit_member_list == null) {
439 ordered_explicit_member_list = new List<MemberCore> ();
440 ordered_member_list = new List<MemberCore> ();
444 if (Kind == MemberKind.Interface) {
445 Report.Error (541, mc.Location,
446 "`{0}': explicit interface declaration can only be declared in a class or struct",
447 mc.GetSignatureForError ());
450 ordered_explicit_member_list.Add (mc);
451 alist.Insert (0, mc);
453 ordered_member_list.Add (mc);
459 public void AddMethod (MethodOrOperator method)
461 if (!AddToContainer (method, method.MemberName.Basename))
465 methods = new List<MemberCore> ();
467 if (method.MemberName.Left != null)
468 AddMemberToList (method, methods, true);
470 AddMemberToList (method, methods, false);
473 public void AddConstructor (Constructor c)
475 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
476 if (!AddToContainer (c, is_static ? Constructor.ConstructorName : Constructor.TypeConstructorName))
479 if (is_static && c.ParameterInfo.IsEmpty){
480 if (default_static_constructor != null) {
481 Report.SymbolRelatedToPreviousError (default_static_constructor);
482 Report.Error (111, c.Location,
483 "A member `{0}' is already defined. Rename this member or use different parameter types",
484 c.GetSignatureForError ());
488 default_static_constructor = c;
490 if (c.ParameterInfo.IsEmpty)
491 default_constructor = c;
493 if (instance_constructors == null)
494 instance_constructors = new List<Constructor> ();
496 instance_constructors.Add (c);
500 public bool AddField (FieldBase field)
502 if (!AddMember (field))
506 fields = new List<FieldBase> ();
510 if ((field.ModFlags & Modifiers.STATIC) != 0)
513 if (first_nonstatic_field == null) {
514 first_nonstatic_field = field;
518 if (Kind == MemberKind.Struct && first_nonstatic_field.Parent != field.Parent) {
519 Report.SymbolRelatedToPreviousError (first_nonstatic_field.Parent);
520 Report.Warning (282, 3, field.Location,
521 "struct instance field `{0}' found in different declaration from instance field `{1}'",
522 field.GetSignatureForError (), first_nonstatic_field.GetSignatureForError ());
527 public void AddProperty (Property prop)
529 if (!AddMember (prop))
532 if (properties == null)
533 properties = new List<MemberCore> ();
535 if (prop.MemberName.Left != null)
536 AddMemberToList (prop, properties, true);
538 AddMemberToList (prop, properties, false);
541 public void AddEvent (Event e)
547 events = new List<MemberCore> ();
553 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
555 public void AddIndexer (Indexer i)
557 if (indexers == null)
558 indexers = new List<MemberCore> ();
560 if (i.IsExplicitImpl)
561 AddMemberToList (i, indexers, true);
563 AddMemberToList (i, indexers, false);
566 public void AddOperator (Operator op)
571 if (operators == null)
572 operators = new List<MemberCore> ();
577 public void AddCompilerGeneratedClass (CompilerGeneratedClass c)
579 if (compiler_generated == null)
580 compiler_generated = new List<CompilerGeneratedClass> ();
582 compiler_generated.Add (c);
585 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
587 if (a.Type == pa.DefaultMember) {
588 if (Indexers != null) {
589 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
594 if (a.Type == pa.Required) {
595 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
599 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
602 public override AttributeTargets AttributeTargets {
604 throw new NotSupportedException ();
608 public IList<TypeContainer> Types {
614 public IList<MemberCore> Methods {
620 public IList<MemberCore> Constants {
626 public TypeSpec BaseType {
628 return spec.BaseType;
632 public IList<FieldBase> Fields {
638 public IList<Constructor> InstanceConstructors {
640 return instance_constructors;
644 public IList<MemberCore> Properties {
650 public IList<MemberCore> Events {
656 public IList<MemberCore> Indexers {
662 public IList<MemberCore> Operators {
668 protected override TypeAttributes TypeAttr {
670 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
674 public int TypeParametersCount {
676 return MemberName.Arity;
680 TypeParameterSpec[] ITypeDefinition.TypeParameters {
682 // TODO MemberCache: this is going to hurt
683 return PartialContainer.type_params.Select (l => l.Type).ToArray ();
687 public string GetAttributeDefaultMember ()
689 return indexers == null ? DefaultIndexerName : indexer_name;
692 public bool IsComImport {
694 if (OptAttributes == null)
697 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
701 string ITypeDefinition.Namespace {
703 return NamespaceEntry.NS.MemberName.GetSignatureForError ();
707 public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
709 if ((field.ModFlags & Modifiers.STATIC) != 0){
710 if (initialized_static_fields == null) {
711 PartialContainer.HasStaticFieldInitializer = true;
712 initialized_static_fields = new List<FieldInitializer> (4);
715 initialized_static_fields.Add (expression);
717 if (initialized_fields == null)
718 initialized_fields = new List<FieldInitializer> (4);
720 initialized_fields.Add (expression);
724 public void ResolveFieldInitializers (BlockContext ec)
726 if (partial_parts != null) {
727 foreach (TypeContainer part in partial_parts) {
728 part.DoResolveFieldInitializers (ec);
731 DoResolveFieldInitializers (ec);
734 void DoResolveFieldInitializers (BlockContext ec)
737 if (initialized_static_fields == null)
740 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
742 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
743 for (i = 0; i < initialized_static_fields.Count; ++i) {
744 FieldInitializer fi = initialized_static_fields [i];
745 ExpressionStatement s = fi.ResolveStatement (ec);
747 s = EmptyExpressionStatement.Instance;
748 } else if (!fi.IsSideEffectFree) {
749 has_complex_initializer |= true;
755 for (i = 0; i < initialized_static_fields.Count; ++i) {
756 FieldInitializer fi = initialized_static_fields [i];
758 // Need special check to not optimize code like this
759 // static int a = b = 5;
762 if (!has_complex_initializer && fi.IsDefaultInitializer)
765 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
771 if (initialized_fields == null)
774 for (int i = 0; i < initialized_fields.Count; ++i) {
775 FieldInitializer fi = initialized_fields [i];
776 ExpressionStatement s = fi.ResolveStatement (ec);
781 // Field is re-initialized to its default value => removed
783 if (fi.IsDefaultInitializer && ec.Module.Compiler.Settings.Optimize)
786 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
790 public override string DocComment {
802 public PendingImplementation PendingImplementations {
803 get { return pending; }
806 internal override void GenerateDocComment (DocumentationBuilder builder)
808 base.GenerateDocComment (builder);
810 if (DefaultStaticConstructor != null)
811 DefaultStaticConstructor.GenerateDocComment (builder);
813 if (InstanceConstructors != null)
814 foreach (Constructor c in InstanceConstructors)
815 c.GenerateDocComment (builder);
818 foreach (TypeContainer tc in Types)
819 tc.GenerateDocComment (builder);
821 if (Constants != null)
822 foreach (Const c in Constants)
823 c.GenerateDocComment (builder);
826 foreach (FieldBase f in Fields)
827 f.GenerateDocComment (builder);
830 foreach (Event e in Events)
831 e.GenerateDocComment (builder);
833 if (Indexers != null)
834 foreach (Indexer ix in Indexers)
835 ix.GenerateDocComment (builder);
837 if (Properties != null)
838 foreach (Property p in Properties)
839 p.GenerateDocComment (builder);
842 foreach (MethodOrOperator m in Methods)
843 m.GenerateDocComment (builder);
845 if (Operators != null)
846 foreach (Operator o in Operators)
847 o.GenerateDocComment (builder);
850 public TypeSpec GetAttributeCoClass ()
852 if (OptAttributes == null)
855 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
859 return a.GetCoClassAttributeValue ();
862 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
865 if (OptAttributes != null) {
866 a = OptAttributes.Search (pa);
872 return a.GetAttributeUsageAttribute ();
875 public virtual void AddBasesForPart (DeclSpace part, List<FullNamedExpression> bases)
877 // FIXME: get rid of partial_parts and store lists of bases of each part here
878 // assumed, not verified: 'part' is in 'partial_parts'
879 ((TypeContainer) part).type_bases = bases;
883 /// This function computes the Base class and also the
884 /// list of interfaces that the class or struct @c implements.
886 /// The return value is an array (might be null) of
887 /// interfaces implemented (as Types).
889 /// The @base_class argument is set to the base object or null
890 /// if this is `System.Object'.
892 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
895 if (type_bases == null)
898 int count = type_bases.Count;
899 TypeSpec[] ifaces = null;
900 var base_context = new BaseContext (this);
901 for (int i = 0, j = 0; i < count; i++){
902 FullNamedExpression fne = type_bases [i];
904 var fne_resolved = fne.ResolveAsType (base_context);
905 if (fne_resolved == null)
908 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
909 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
910 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
911 GetSignatureForError ());
916 base_type = fne_resolved;
922 ifaces = new TypeSpec [count - i];
924 if (fne_resolved.IsInterface) {
925 for (int ii = 0; ii < j; ++ii) {
926 if (fne_resolved == ifaces [ii]) {
927 Report.Error (528, Location, "`{0}' is already listed in interface list",
928 fne_resolved.GetSignatureForError ());
933 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
934 Report.Error (61, fne.Location,
935 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
936 fne_resolved.GetSignatureForError (), GetSignatureForError ());
939 Report.SymbolRelatedToPreviousError (fne_resolved);
940 if (Kind != MemberKind.Class) {
941 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
942 } else if (base_class != null)
943 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
944 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
946 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
947 GetSignatureForError (), fne_resolved.GetSignatureForError ());
951 ifaces [j++] = fne_resolved;
957 TypeSpec[] GetNormalPartialBases ()
959 var ifaces = new List<TypeSpec> (0);
960 if (iface_exprs != null)
961 ifaces.AddRange (iface_exprs);
963 foreach (TypeContainer part in partial_parts) {
964 FullNamedExpression new_base_class;
965 var new_ifaces = part.ResolveBaseTypes (out new_base_class);
966 if (new_base_class != null) {
967 if (base_type_expr != null && part.base_type != base_type) {
968 Report.SymbolRelatedToPreviousError (new_base_class.Location, "");
969 Report.Error (263, part.Location,
970 "Partial declarations of `{0}' must not specify different base classes",
971 part.GetSignatureForError ());
973 base_type_expr = new_base_class;
974 base_type = part.base_type;
978 if (new_ifaces == null)
981 foreach (var iface in new_ifaces) {
982 if (ifaces.Contains (iface))
989 if (ifaces.Count == 0)
992 return ifaces.ToArray ();
996 // Checks that some operators come in pairs:
1002 // They are matched based on the return type and the argument types
1004 void CheckPairedOperators ()
1006 bool has_equality_or_inequality = false;
1007 var operators = this.operators.ToArray ();
1008 bool[] has_pair = new bool[operators.Length];
1010 for (int i = 0; i < operators.Length; ++i) {
1011 if (operators[i] == null)
1014 Operator o_a = (Operator) operators[i];
1015 Operator.OpType o_type = o_a.OperatorType;
1016 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1017 has_equality_or_inequality = true;
1019 Operator.OpType matching_type = o_a.GetMatchingOperator ();
1020 if (matching_type == Operator.OpType.TOP) {
1021 operators[i] = null;
1025 for (int ii = 0; ii < operators.Length; ++ii) {
1026 Operator o_b = (Operator) operators[ii];
1027 if (o_b == null || o_b.OperatorType != matching_type)
1030 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1033 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1036 operators[i] = null;
1039 // Used to ignore duplicate user conversions
1041 has_pair[ii] = true;
1045 for (int i = 0; i < operators.Length; ++i) {
1046 if (operators[i] == null || has_pair[i])
1049 Operator o = (Operator) operators [i];
1050 Report.Error (216, o.Location,
1051 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1052 o.GetSignatureForError (), Operator.GetName (o.GetMatchingOperator ()));
1055 if (has_equality_or_inequality) {
1056 if (Methods == null || !HasEquals)
1057 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1058 GetSignatureForError ());
1060 if (Methods == null || !HasGetHashCode)
1061 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1062 GetSignatureForError ());
1066 bool CreateTypeBuilder ()
1069 // Sets .size to 1 for structs with no instance fields
1071 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null ? 1 : 0;
1074 TypeBuilder = Module.CreateBuilder (Name, TypeAttr, type_size);
1076 TypeBuilder = Parent.TypeBuilder.DefineNestedType (Basename, TypeAttr, null, type_size);
1079 if (DeclaringAssembly.Importer != null)
1080 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1082 spec.SetMetaInfo (TypeBuilder);
1083 spec.MemberCache = new MemberCache (this);
1084 spec.DeclaringType = Parent.CurrentType;
1087 Parent.MemberCache.AddMember (spec);
1090 string[] param_names = new string[TypeParameters.Length];
1091 for (int i = 0; i < TypeParameters.Length; i++)
1092 param_names [i] = TypeParameters[i].Name;
1094 all_tp_builders = TypeBuilder.DefineGenericParameters (param_names);
1096 int offset = CurrentTypeParametersStartIndex;
1097 for (int i = offset; i < all_tp_builders.Length; i++) {
1098 CurrentTypeParameters [i - offset].Define (all_tp_builders [i], spec);
1106 // Creates a proxy base method call inside this container for hoisted base member calls
1108 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1110 Method proxy_method;
1113 // One proxy per base method is enough
1115 if (hoisted_base_call_proxies == null) {
1116 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1117 proxy_method = null;
1119 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1122 if (proxy_method == null) {
1123 string name = CompilerGeneratedClass.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1124 var base_parameters = new Parameter[method.Parameters.Count];
1125 for (int i = 0; i < base_parameters.Length; ++i) {
1126 var base_param = method.Parameters.FixedParameters[i];
1127 base_parameters[i] = new Parameter (new TypeExpression (method.Parameters.Types[i], Location),
1128 base_param.Name, base_param.ModFlags, null, Location);
1129 base_parameters[i].Resolve (this, i);
1132 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
1133 if (method.Parameters.HasArglist) {
1134 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1135 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1138 GenericMethod generic_method;
1139 MemberName member_name;
1140 TypeArguments targs = null;
1141 if (method.IsGeneric) {
1143 // Copy all base generic method type parameters info
1145 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1146 var type_params = new TypeParameter[hoisted_tparams.Length];
1147 targs = new TypeArguments ();
1148 targs.Arguments = new TypeSpec[type_params.Length];
1149 for (int i = 0; i < type_params.Length; ++i) {
1150 var tp = hoisted_tparams[i];
1151 targs.Add (new TypeParameterName (tp.Name, null, Location));
1152 targs.Arguments[i] = tp;
1153 type_params[i] = new TypeParameter (tp, this, null, new MemberName (tp.Name), null);
1156 member_name = new MemberName (name, targs, Location);
1157 generic_method = new GenericMethod (NamespaceEntry, this, member_name, type_params,
1158 new TypeExpression (method.ReturnType, Location), cloned_params);
1160 member_name = new MemberName (name);
1161 generic_method = null;
1164 // Compiler generated proxy
1165 proxy_method = new Method (this, generic_method, new TypeExpression (method.ReturnType, Location),
1166 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1167 member_name, cloned_params, null);
1169 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location);
1171 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1172 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1174 mg.SetTypeArguments (rc, targs);
1176 // Get all the method parameters and pass them as arguments
1177 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1178 Statement statement;
1179 if (method.ReturnType.Kind == MemberKind.Void)
1180 statement = new StatementExpression (real_base_call);
1182 statement = new Return (real_base_call, Location);
1184 block.AddStatement (statement);
1185 proxy_method.Block = block;
1187 methods.Add (proxy_method);
1188 proxy_method.Define ();
1190 hoisted_base_call_proxies.Add (method, proxy_method);
1193 return proxy_method.Spec;
1196 bool DefineBaseTypes ()
1198 iface_exprs = ResolveBaseTypes (out base_type_expr);
1199 if (partial_parts != null) {
1200 iface_exprs = GetNormalPartialBases ();
1203 var cycle = CheckRecursiveDefinition (this);
1204 if (cycle != null) {
1205 Report.SymbolRelatedToPreviousError (cycle);
1206 if (this is Interface) {
1207 Report.Error (529, Location,
1208 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1209 GetSignatureForError (), cycle.GetSignatureForError ());
1213 Report.Error (146, Location,
1214 "Circular base class dependency involving `{0}' and `{1}'",
1215 GetSignatureForError (), cycle.GetSignatureForError ());
1221 if (iface_exprs != null) {
1222 foreach (var iface_type in iface_exprs) {
1223 // Prevents a crash, the interface might not have been resolved: 442144
1224 if (iface_type == null)
1227 if (!spec.AddInterfaceDefined (iface_type))
1230 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1232 // Ensure the base is always setup
1233 var compiled_iface = iface_type.MemberDefinition as Interface;
1234 if (compiled_iface != null) {
1235 // TODO: Need DefineBaseType only
1236 compiled_iface.DefineType ();
1239 if (iface_type.Interfaces != null) {
1240 var base_ifaces = new List<TypeSpec> (iface_type.Interfaces);
1241 for (int i = 0; i < base_ifaces.Count; ++i) {
1242 var ii_iface_type = base_ifaces[i];
1243 if (spec.AddInterfaceDefined (ii_iface_type)) {
1244 TypeBuilder.AddInterfaceImplementation (ii_iface_type.GetMetaInfo ());
1246 if (ii_iface_type.Interfaces != null)
1247 base_ifaces.AddRange (ii_iface_type.Interfaces);
1254 if (Kind == MemberKind.Interface) {
1255 spec.BaseType = Compiler.BuiltinTypes.Object;
1259 if (base_type != null) {
1260 spec.BaseType = base_type;
1262 // Set base type after type creation
1263 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1265 TypeBuilder.SetParent (null);
1271 public virtual void DefineConstants ()
1273 if (constants != null) {
1274 foreach (Const c in constants) {
1279 if (instance_constructors != null) {
1280 foreach (MethodCore m in instance_constructors) {
1281 var p = m.ParameterInfo;
1283 p.ResolveDefaultValues (m);
1288 if (methods != null) {
1289 foreach (MethodCore m in methods) {
1290 var p = m.ParameterInfo;
1292 p.ResolveDefaultValues (m);
1297 if (indexers != null) {
1298 foreach (Indexer i in indexers) {
1299 i.ParameterInfo.ResolveDefaultValues (i);
1303 if (types != null) {
1304 foreach (var t in types)
1305 t.DefineConstants ();
1310 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1312 public bool CreateType ()
1314 if (TypeBuilder != null)
1320 if (!CreateTypeBuilder ()) {
1325 if (partial_parts != null) {
1326 foreach (TypeContainer part in partial_parts) {
1328 part.current_type = current_type;
1329 part.TypeBuilder = TypeBuilder;
1333 if (Types != null) {
1334 foreach (TypeContainer tc in Types) {
1342 public override void DefineType ()
1349 type_defined = true;
1351 // TODO: Driver resolves only first level of namespace, do the rest here for now
1352 if (IsTopLevel && (ModFlags & Modifiers.COMPILER_GENERATED) == 0) {
1353 NamespaceEntry.Resolve ();
1356 if (!DefineBaseTypes ()) {
1361 if (!DefineNestedTypes ()) {
1367 public override void SetParameterInfo (List<Constraints> constraints_list)
1369 base.SetParameterInfo (constraints_list);
1371 if (PartialContainer.CurrentTypeParameters == null || PartialContainer == this)
1374 TypeParameter[] tc_names = PartialContainer.CurrentTypeParameters;
1375 for (int i = 0; i < tc_names.Length; ++i) {
1376 if (tc_names [i].Name != type_params [i].Name) {
1377 Report.SymbolRelatedToPreviousError (PartialContainer.Location, "");
1378 Report.Error (264, Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
1379 GetSignatureForError ());
1383 if (tc_names [i].Variance != type_params [i].Variance) {
1384 Report.SymbolRelatedToPreviousError (PartialContainer.Location, "");
1385 Report.Error (1067, Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers",
1386 GetSignatureForError ());
1393 // Replaces normal spec with predefined one when compiling corlib
1394 // and this type container defines predefined type
1396 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1398 // When compiling build-in types we start with two
1399 // version of same type. One is of BuiltinTypeSpec and
1400 // second one is ordinary TypeSpec. The unification
1401 // happens at later stage when we know which type
1402 // really matches the builtin type signature. However
1403 // that means TypeSpec create during CreateType of this
1404 // type has to be replaced with builtin one
1406 spec.SetMetaInfo (TypeBuilder);
1407 spec.MemberCache = this.spec.MemberCache;
1408 spec.DeclaringType = this.spec.DeclaringType;
1411 current_type = null;
1414 void UpdateTypeParameterConstraints (TypeContainer part)
1416 TypeParameter[] current_params = type_params;
1417 for (int i = 0; i < current_params.Length; i++) {
1418 if (current_params [i].AddPartialConstraints (part, part.type_params [i]))
1421 Report.SymbolRelatedToPreviousError (Location, "");
1422 Report.Error (265, part.Location,
1423 "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'",
1424 GetSignatureForError (), current_params [i].GetSignatureForError ());
1428 public bool ResolveTypeParameters ()
1430 if (!DoResolveTypeParameters ())
1433 if (types != null) {
1434 foreach (var type in types)
1435 if (!type.ResolveTypeParameters ())
1439 if (compiler_generated != null) {
1440 foreach (CompilerGeneratedClass c in compiler_generated)
1441 if (!c.ResolveTypeParameters ())
1448 protected virtual bool DoResolveTypeParameters ()
1450 if (CurrentTypeParameters == null)
1453 if (PartialContainer != this)
1454 throw new InternalErrorException ();
1456 var base_context = new BaseContext (this);
1457 foreach (TypeParameter type_param in CurrentTypeParameters) {
1458 if (!type_param.ResolveConstraints (base_context)) {
1464 if (partial_parts != null) {
1465 foreach (TypeContainer part in partial_parts)
1466 UpdateTypeParameterConstraints (part);
1472 protected virtual bool DefineNestedTypes ()
1474 if (Types != null) {
1475 foreach (TypeContainer tc in Types)
1482 TypeSpec CheckRecursiveDefinition (TypeContainer tc)
1484 if (InTransit != null)
1489 if (base_type != null) {
1490 var ptc = base_type.MemberDefinition as TypeContainer;
1491 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1495 if (iface_exprs != null) {
1496 foreach (var iface in iface_exprs) {
1497 // the interface might not have been resolved, prevents a crash, see #442144
1500 var ptc = iface.MemberDefinition as Interface;
1501 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1506 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1514 /// Populates our TypeBuilder with fields and methods
1516 public sealed override bool Define ()
1518 if (members_defined)
1519 return members_defined_ok;
1521 members_defined_ok = DoDefineMembers ();
1522 members_defined = true;
1524 if (types != null) {
1525 foreach (var nested in types)
1529 return members_defined_ok;
1532 protected virtual bool DoDefineMembers ()
1534 if (iface_exprs != null) {
1535 foreach (var iface_type in iface_exprs) {
1536 if (iface_type == null)
1539 // Ensure the base is always setup
1540 var compiled_iface = iface_type.MemberDefinition as Interface;
1541 if (compiled_iface != null)
1542 compiled_iface.Define ();
1544 if (Kind == MemberKind.Interface)
1545 MemberCache.AddInterface (iface_type);
1547 ObsoleteAttribute oa = iface_type.GetAttributeObsolete ();
1548 if (oa != null && !IsObsolete)
1549 AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report);
1551 if (iface_type.Arity > 0) {
1552 // TODO: passing `this' is wrong, should be base type iface instead
1553 TypeManager.CheckTypeVariance (iface_type, Variance.Covariant, this);
1555 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1556 Report.Error (1966, Location,
1557 "`{0}': cannot implement a dynamic interface `{1}'",
1558 GetSignatureForError (), iface_type.GetSignatureForError ());
1562 if (spec.Interfaces != null) {
1563 foreach (var prev_iface in iface_exprs) {
1564 if (prev_iface == iface_type)
1567 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1570 Report.Error (695, Location,
1571 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1572 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1579 if (base_type != null) {
1581 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1583 if (base_type_expr != null) {
1584 ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
1585 if (obsolete_attr != null && !IsObsolete)
1586 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report);
1588 if (IsGeneric && base_type.IsAttribute) {
1589 Report.Error (698, base_type_expr.Location,
1590 "A generic type cannot derive from `{0}' because it is an attribute class",
1591 base_type.GetSignatureForError ());
1595 if (base_type.Interfaces != null) {
1596 foreach (var iface in base_type.Interfaces)
1597 spec.AddInterface (iface);
1600 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1601 if (baseContainer != null) {
1602 baseContainer.Define ();
1605 // It can trigger define of this type (for generic types only)
1607 if (HasMembersDefined)
1612 DefineContainerMembers (constants);
1613 DefineContainerMembers (fields);
1615 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1616 pending = PendingImplementation.GetPendingImplementations (this);
1618 if (requires_delayed_unmanagedtype_check) {
1619 requires_delayed_unmanagedtype_check = false;
1620 foreach (FieldBase f in fields) {
1621 if (f.MemberType != null && f.MemberType.IsPointer)
1622 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
1628 // Constructors are not in the defined_names array
1630 DefineContainerMembers (instance_constructors);
1632 DefineContainerMembers (events);
1633 DefineContainerMembers (ordered_explicit_member_list);
1634 DefineContainerMembers (ordered_member_list);
1636 if (operators != null) {
1637 DefineContainerMembers (operators);
1638 CheckPairedOperators ();
1641 ComputeIndexerName();
1642 CheckEqualsAndGetHashCode();
1644 if (Kind == MemberKind.Interface && iface_exprs != null) {
1645 MemberCache.RemoveHiddenMembers (spec);
1651 protected virtual void DefineContainerMembers (System.Collections.IList mcal) // IList<MemberCore>
1654 for (int i = 0; i < mcal.Count; ++i) {
1655 MemberCore mc = (MemberCore) mcal[i];
1658 } catch (Exception e) {
1659 throw new InternalErrorException (mc, e);
1665 protected virtual void ComputeIndexerName ()
1667 if (indexers == null)
1670 string class_indexer_name = null;
1673 // If there's both an explicit and an implicit interface implementation, the
1674 // explicit one actually implements the interface while the other one is just
1675 // a normal indexer. See bug #37714.
1678 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
1679 foreach (Indexer i in indexers) {
1680 if (i.InterfaceType != null) {
1681 if (seen_normal_indexers)
1682 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
1686 seen_normal_indexers = true;
1688 if (class_indexer_name == null) {
1689 class_indexer_name = i.ShortName;
1693 if (i.ShortName != class_indexer_name)
1694 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");
1697 if (class_indexer_name != null)
1698 indexer_name = class_indexer_name;
1701 void EmitIndexerName ()
1703 if (!seen_normal_indexers)
1706 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
1710 var encoder = new AttributeEncoder ();
1711 encoder.Encode (GetAttributeDefaultMember ());
1712 encoder.EncodeEmptyNamedArguments ();
1714 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1717 protected virtual void CheckEqualsAndGetHashCode ()
1719 if (methods == null)
1722 if (HasEquals && !HasGetHashCode) {
1723 Report.Warning (659, 3, this.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", this.GetSignatureForError ());
1727 // Indicated whether container has StructLayout attribute set Explicit
1728 public bool HasExplicitLayout {
1729 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
1730 set { caching_flags |= Flags.HasExplicitLayout; }
1733 public bool HasStructLayout {
1734 get { return (caching_flags & Flags.HasStructLayout) != 0; }
1735 set { caching_flags |= Flags.HasStructLayout; }
1738 public MemberCache MemberCache {
1740 return spec.MemberCache;
1744 void CheckMemberUsage (List<MemberCore> al, string member_type)
1749 foreach (MemberCore mc in al) {
1750 if ((mc.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE)
1753 if ((mc.ModFlags & Modifiers.PARTIAL) != 0)
1756 if (!mc.IsUsed && (mc.caching_flags & Flags.Excluded) == 0) {
1757 Report.Warning (169, 3, mc.Location, "The private {0} `{1}' is never used", member_type, mc.GetSignatureForError ());
1762 public virtual void VerifyMembers ()
1765 // Check for internal or private fields that were never assigned
1767 if (Report.WarningLevel >= 3) {
1768 if (Compiler.Settings.EnhancedWarnings) {
1769 CheckMemberUsage (properties, "property");
1770 CheckMemberUsage (methods, "method");
1771 CheckMemberUsage (constants, "constant");
1774 if (fields != null){
1775 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
1776 foreach (FieldBase f in fields) {
1777 if ((f.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
1778 if (is_type_exposed)
1785 if ((f.caching_flags & Flags.IsAssigned) == 0)
1786 Report.Warning (169, 3, f.Location, "The private field `{0}' is never used", f.GetSignatureForError ());
1788 Report.Warning (414, 3, f.Location, "The private field `{0}' is assigned but its value is never used",
1789 f.GetSignatureForError ());
1794 if ((f.caching_flags & Flags.IsAssigned) != 0)
1798 // Only report 649 on level 4
1800 if (Report.WarningLevel < 4)
1804 // Don't be pendatic over serializable attributes
1806 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
1809 Constant c = New.Constantify (f.MemberType, f.Location);
1812 value = c.GetValueAsLiteral ();
1813 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
1816 // Ignore this warning for struct value fields (they are always initialized)
1817 if (f.MemberType.IsStruct)
1824 value = " `" + value + "'";
1826 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
1827 f.GetSignatureForError (), value);
1833 public override void Emit ()
1836 MemberSpec candidate;
1837 bool overrides = false;
1838 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
1839 if (conflict_symbol == null && candidate == null) {
1840 if ((ModFlags & Modifiers.NEW) != 0)
1841 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
1842 GetSignatureForError ());
1844 if ((ModFlags & Modifiers.NEW) == 0) {
1845 if (candidate == null)
1846 candidate = conflict_symbol;
1848 Report.SymbolRelatedToPreviousError (candidate);
1849 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
1850 GetSignatureForError (), candidate.GetSignatureForError ());
1855 // Run constraints check on all possible generic types
1856 if ((ModFlags & Modifiers.COMPILER_GENERATED) == 0) {
1857 if (base_type != null && base_type_expr != null) {
1858 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
1861 if (iface_exprs != null) {
1862 foreach (var iface_type in iface_exprs) {
1863 if (iface_type == null)
1866 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
1871 if (all_tp_builders != null) {
1872 int current_starts_index = CurrentTypeParametersStartIndex;
1873 for (int i = 0; i < all_tp_builders.Length; i++) {
1874 if (i < current_starts_index) {
1875 TypeParameters[i].EmitConstraints (all_tp_builders [i]);
1877 var tp = CurrentTypeParameters [i - current_starts_index];
1878 tp.CheckGenericConstraints (!IsObsolete);
1884 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
1885 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
1888 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
1889 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
1895 // TODO: move to ClassOrStruct
1896 void EmitConstructors ()
1898 if (instance_constructors == null)
1901 if (spec.IsAttribute && IsExposedFromAssembly () && Compiler.Settings.VerifyClsCompliance && IsClsComplianceRequired ()) {
1902 bool has_compliant_args = false;
1904 foreach (Constructor c in instance_constructors) {
1908 catch (Exception e) {
1909 throw new InternalErrorException (c, e);
1912 if (has_compliant_args)
1915 has_compliant_args = c.HasCompliantArgs;
1917 if (!has_compliant_args)
1918 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
1920 foreach (Constructor c in instance_constructors) {
1924 catch (Exception e) {
1925 throw new InternalErrorException (c, e);
1932 /// Emits the code, this step is performed after all
1933 /// the types, enumerations, constructors
1935 public virtual void EmitType ()
1937 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1940 if (OptAttributes != null)
1941 OptAttributes.Emit ();
1945 EmitConstructors ();
1947 if (constants != null)
1948 foreach (Const con in constants)
1951 if (default_static_constructor != null)
1952 default_static_constructor.Emit ();
1954 if (operators != null)
1955 foreach (Operator o in operators)
1958 if (properties != null)
1959 foreach (Property p in properties)
1962 if (indexers != null) {
1963 foreach (Indexer indx in indexers)
1968 if (events != null){
1969 foreach (Event e in Events)
1973 if (methods != null) {
1974 for (int i = 0; i < methods.Count; ++i)
1975 ((MethodOrOperator) methods [i]).Emit ();
1979 foreach (FieldBase f in fields)
1982 if (types != null) {
1983 foreach (TypeContainer t in types)
1987 if (pending != null)
1988 pending.VerifyPendingMethods ();
1990 if (Report.Errors > 0)
1993 if (compiler_generated != null) {
1994 for (int i = 0; i < compiler_generated.Count; ++i)
1995 compiler_generated [i].EmitType ();
1999 public virtual void CloseType ()
2001 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2004 // Close base type container first to avoid TypeLoadException
2005 if (spec.BaseType != null) {
2006 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2007 if (btype != null) {
2010 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2016 caching_flags |= Flags.CloseTypeCreated;
2017 TypeBuilder.CreateType ();
2018 } catch (TypeLoadException){
2020 // This is fine, the code still created the type
2022 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
2023 // Console.WriteLine (e.Message);
2024 } catch (Exception e) {
2025 throw new InternalErrorException (this, e);
2029 foreach (TypeContainer tc in Types)
2033 if (compiler_generated != null)
2034 foreach (CompilerGeneratedClass c in compiler_generated)
2038 initialized_fields = null;
2039 initialized_static_fields = null;
2041 ordered_explicit_member_list = null;
2042 ordered_member_list = null;
2047 compiler_generated = null;
2048 default_constructor = null;
2049 default_static_constructor = null;
2051 OptAttributes = null;
2055 // Performs the validation on a Method's modifiers (properties have
2056 // the same properties).
2058 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2060 public bool MethodModifiersValid (MemberCore mc)
2062 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2063 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2065 var flags = mc.ModFlags;
2068 // At most one of static, virtual or override
2070 if ((flags & Modifiers.STATIC) != 0){
2071 if ((flags & vao) != 0){
2072 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2073 mc.GetSignatureForError ());
2078 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2079 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2080 mc.GetSignatureForError ());
2085 // If the declaration includes the abstract modifier, then the
2086 // declaration does not include static, virtual or extern
2088 if ((flags & Modifiers.ABSTRACT) != 0){
2089 if ((flags & Modifiers.EXTERN) != 0){
2091 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2095 if ((flags & Modifiers.SEALED) != 0) {
2096 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2100 if ((flags & Modifiers.VIRTUAL) != 0){
2101 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2105 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2106 Report.SymbolRelatedToPreviousError (this);
2107 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2108 mc.GetSignatureForError (), GetSignatureForError ());
2113 if ((flags & Modifiers.PRIVATE) != 0){
2114 if ((flags & vao) != 0){
2115 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2120 if ((flags & Modifiers.SEALED) != 0){
2121 if ((flags & Modifiers.OVERRIDE) == 0){
2122 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2130 public Constructor DefaultStaticConstructor {
2131 get { return default_static_constructor; }
2134 protected override bool VerifyClsCompliance ()
2136 if (!base.VerifyClsCompliance ())
2139 // Check this name against other containers
2140 NamespaceEntry.NS.VerifyClsCompliance ();
2142 // Check all container names for user classes
2143 if (Kind != MemberKind.Delegate)
2144 MemberCache.VerifyClsCompliance (Definition, Report);
2146 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2147 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2148 GetSignatureForError (), BaseType.GetSignatureForError ());
2154 /// Performs checks for an explicit interface implementation. First it
2155 /// checks whether the `interface_type' is a base inteface implementation.
2156 /// Then it checks whether `name' exists in the interface type.
2158 public bool VerifyImplements (InterfaceMemberBase mb)
2160 var ifaces = spec.Interfaces;
2161 if (ifaces != null) {
2162 foreach (TypeSpec t in ifaces){
2163 if (t == mb.InterfaceType)
2168 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2169 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2170 mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType));
2175 // Used for visiblity checks to tests whether this definition shares
2176 // base type baseType, it does member-definition search
2178 public bool IsBaseTypeDefinition (TypeSpec baseType)
2180 // RootContext check
2181 if (TypeBuilder == null)
2186 if (type.MemberDefinition == baseType.MemberDefinition)
2189 type = type.BaseType;
2190 } while (type != null);
2195 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2197 return Module.DeclaringAssembly == assembly;
2200 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2202 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2206 // Public function used to locate types.
2208 // Set 'ignore_cs0104' to true if you want to ignore cs0104 errors.
2210 // Returns: Type or null if they type can not be found.
2212 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2214 FullNamedExpression e;
2215 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2221 TypeParameter[] tp = CurrentTypeParameters;
2223 TypeParameter tparam = TypeParameter.FindTypeParameter (tp, name);
2225 e = new TypeParameterExpr (tparam, Location.Null);
2230 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2232 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2233 e = new TypeExpression (t, Location.Null);
2234 else if (Parent != null) {
2235 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2237 int errors = Report.Errors;
2239 e = NamespaceEntry.LookupNamespaceOrType (name, arity, mode, loc);
2241 if (errors != Report.Errors)
2246 // TODO MemberCache: How to cache arity stuff ?
2247 if (arity == 0 && mode == LookupMode.Normal)
2253 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2255 // TODO: GenericMethod only
2256 if (PartialContainer == null)
2259 // Has any nested type
2260 // Does not work, because base type can have
2261 //if (PartialContainer.Types == null)
2264 var container = PartialContainer.CurrentType;
2266 // Is not Root container
2267 if (container == null)
2270 return MemberCache.FindNestedType (container, name, arity);
2273 public void Mark_HasEquals ()
2275 cached_method |= CachedMethods.Equals;
2278 public void Mark_HasGetHashCode ()
2280 cached_method |= CachedMethods.GetHashCode;
2284 /// Method container contains Equals method
2286 public bool HasEquals {
2288 return (cached_method & CachedMethods.Equals) != 0;
2293 /// Method container contains GetHashCode method
2295 public bool HasGetHashCode {
2297 return (cached_method & CachedMethods.GetHashCode) != 0;
2301 public bool HasStaticFieldInitializer {
2303 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2307 cached_method |= CachedMethods.HasStaticFieldInitializer;
2309 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2313 public override string DocCommentHeader {
2314 get { return "T:"; }
2318 public abstract class ClassOrStruct : TypeContainer
2320 SecurityType declarative_security;
2322 public ClassOrStruct (NamespaceContainer ns, DeclSpace parent,
2323 MemberName name, Attributes attrs, MemberKind kind)
2324 : base (ns, parent, name, attrs, kind)
2328 protected override bool AddToContainer (MemberCore symbol, string name)
2330 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2331 if (symbol is TypeParameter) {
2332 Report.Error (694, symbol.Location,
2333 "Type parameter `{0}' has same name as containing type, or method",
2334 symbol.GetSignatureForError ());
2338 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2339 if (imb == null || !imb.IsExplicitImpl) {
2340 Report.SymbolRelatedToPreviousError (this);
2341 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2342 symbol.GetSignatureForError ());
2347 return base.AddToContainer (symbol, name);
2350 public override void VerifyMembers ()
2352 base.VerifyMembers ();
2354 if ((events != null) && Report.WarningLevel >= 3) {
2355 foreach (Event e in events){
2356 // Note: The event can be assigned from same class only, so we can report
2357 // this warning for all accessibility modes
2358 if ((e.caching_flags & Flags.IsUsed) == 0)
2359 Report.Warning (67, 3, e.Location, "The event `{0}' is never used", e.GetSignatureForError ());
2363 if (types != null) {
2364 foreach (var t in types)
2369 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2371 if (a.IsValidSecurityAttribute ()) {
2372 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2376 if (a.Type == pa.StructLayout) {
2377 PartialContainer.HasStructLayout = true;
2378 if (a.IsExplicitLayoutKind ())
2379 PartialContainer.HasExplicitLayout = true;
2382 if (a.Type == pa.Dynamic) {
2383 a.Error_MisusedDynamicAttribute ();
2387 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2391 /// Defines the default constructors
2393 protected void DefineDefaultConstructor (bool is_static)
2395 // The default instance constructor is public
2396 // If the class is abstract, the default constructor is protected
2397 // The default static constructor is private
2401 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2403 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2406 Constructor c = new Constructor (this, MemberName.Name, mods,
2407 null, ParametersCompiled.EmptyReadOnlyParameters,
2408 new GeneratedBaseInitializer (Location),
2412 c.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
2415 protected override bool DoDefineMembers ()
2417 CheckProtectedModifier ();
2419 base.DoDefineMembers ();
2421 if (default_static_constructor != null)
2422 default_static_constructor.Define ();
2427 public override void Emit ()
2429 if (default_static_constructor == null && PartialContainer.HasStaticFieldInitializer) {
2430 DefineDefaultConstructor (true);
2431 default_static_constructor.Define ();
2436 if (declarative_security != null) {
2437 foreach (var de in declarative_security) {
2439 TypeBuilder.__AddDeclarativeSecurity (de);
2441 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2447 public override ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
2449 DeclSpace top_level = Parent;
2450 if (top_level != null) {
2451 var methods = NamespaceEntry.NS.LookupExtensionMethod (this, extensionType, name, arity);
2452 if (methods != null) {
2453 return new ExtensionMethodCandidates (methods, NamespaceEntry, NamespaceEntry.NS) {
2454 HasUninspectedMembers = true
2459 return NamespaceEntry.LookupExtensionMethod (extensionType, name, arity);
2462 protected override TypeAttributes TypeAttr {
2464 if (default_static_constructor == null)
2465 return base.TypeAttr | TypeAttributes.BeforeFieldInit;
2467 return base.TypeAttr;
2473 // TODO: should be sealed
2474 public class Class : ClassOrStruct {
2475 const Modifiers AllowedModifiers =
2478 Modifiers.PROTECTED |
2479 Modifiers.INTERNAL |
2481 Modifiers.ABSTRACT |
2486 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2488 public Class (NamespaceContainer ns, DeclSpace parent, MemberName name, Modifiers mod,
2490 : base (ns, parent, name, attrs, MemberKind.Class)
2492 var accmods = (Parent == null || Parent.Parent == null) ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2493 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2494 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2497 public override void Accept (StructuralVisitor visitor)
2499 visitor.Visit (this);
2502 public override void AddBasesForPart (DeclSpace part, List<FullNamedExpression> bases)
2504 if (part.Name == "System.Object")
2505 Report.Error (537, part.Location,
2506 "The class System.Object cannot have a base class or implement an interface.");
2507 base.AddBasesForPart (part, bases);
2510 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2512 if (a.Type == pa.AttributeUsage) {
2513 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2514 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2518 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2519 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2523 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2524 a.Error_MissingGuidAttribute ();
2528 if (a.Type == pa.Extension) {
2529 a.Error_MisusedExtensionAttribute ();
2533 if (a.Type.IsConditionallyExcluded (Compiler, Location))
2536 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2539 public override AttributeTargets AttributeTargets {
2541 return AttributeTargets.Class;
2545 protected override void DefineContainerMembers (System.Collections.IList list)
2551 base.DefineContainerMembers (list);
2555 foreach (MemberCore m in list) {
2556 if (m is Operator) {
2557 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2561 if (m is Destructor) {
2562 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2567 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2571 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is Enum || m is Delegate)
2574 if (m is Constructor) {
2575 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2579 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2582 base.DefineContainerMembers (list);
2585 protected override bool DoDefineMembers ()
2587 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2588 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2591 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2592 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2595 if (InstanceConstructors == null && !IsStatic)
2596 DefineDefaultConstructor (false);
2598 return base.DoDefineMembers ();
2601 public override void Emit ()
2605 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2606 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2608 if (base_type != null && base_type.HasDynamicElement) {
2609 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2613 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2615 var ifaces = base.ResolveBaseTypes (out base_class);
2617 if (base_class == null) {
2618 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2619 base_type = Compiler.BuiltinTypes.Object;
2621 if (base_type.IsGenericParameter){
2622 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2623 GetSignatureForError (), base_type.GetSignatureForError ());
2624 } else if (base_type.IsStatic) {
2625 Report.SymbolRelatedToPreviousError (base_type);
2626 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2627 GetSignatureForError (), base_type.GetSignatureForError ());
2628 } else if (base_type.IsSealed) {
2629 Report.SymbolRelatedToPreviousError (base_type);
2630 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2631 GetSignatureForError (), base_type.GetSignatureForError ());
2632 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2633 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2634 GetSignatureForError (), base_type.GetSignatureForError ());
2637 switch (base_type.BuiltinType) {
2638 case BuiltinTypeSpec.Type.Enum:
2639 case BuiltinTypeSpec.Type.ValueType:
2640 case BuiltinTypeSpec.Type.MulticastDelegate:
2641 case BuiltinTypeSpec.Type.Delegate:
2642 case BuiltinTypeSpec.Type.Array:
2643 if (!(spec is BuiltinTypeSpec)) {
2644 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2645 GetSignatureForError (), base_type.GetSignatureForError ());
2647 base_type = Compiler.BuiltinTypes.Object;
2652 if (!IsAccessibleAs (base_type)) {
2653 Report.SymbolRelatedToPreviousError (base_type);
2654 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2655 base_type.GetSignatureForError (), GetSignatureForError ());
2659 if (PartialContainer.IsStatic && ifaces != null) {
2660 foreach (var t in ifaces)
2661 Report.SymbolRelatedToPreviousError (t);
2662 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2668 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2669 /// Valid only for attribute classes.
2670 public override string[] ConditionalConditions ()
2672 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2675 caching_flags &= ~Flags.Excluded_Undetected;
2677 if (OptAttributes == null)
2680 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2684 string[] conditions = new string[attrs.Length];
2685 for (int i = 0; i < conditions.Length; ++i)
2686 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2688 caching_flags |= Flags.Excluded;
2693 // FIXME: How do we deal with the user specifying a different
2696 protected override TypeAttributes TypeAttr {
2698 TypeAttributes ta = base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2700 ta |= StaticClassAttribute;
2706 public sealed class Struct : ClassOrStruct {
2708 bool is_unmanaged, has_unmanaged_check_done;
2712 // Modifiers allowed in a struct declaration
2714 const Modifiers AllowedModifiers =
2717 Modifiers.PROTECTED |
2718 Modifiers.INTERNAL |
2722 public Struct (NamespaceContainer ns, DeclSpace parent, MemberName name,
2723 Modifiers mod, Attributes attrs)
2724 : base (ns, parent, name, attrs, MemberKind.Struct)
2726 var accmods = parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2727 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2728 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2731 public override AttributeTargets AttributeTargets {
2733 return AttributeTargets.Struct;
2737 public override void Accept (StructuralVisitor visitor)
2739 visitor.Visit (this);
2742 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2744 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2747 // When struct constains fixed fixed and struct layout has explicitly
2748 // set CharSet, its value has to be propagated to compiler generated
2751 if (a.Type == pa.StructLayout && Fields != null) {
2752 var value = a.GetNamedValue ("CharSet");
2756 for (int i = 0; i < Fields.Count; ++i) {
2757 FixedField ff = Fields [i] as FixedField;
2761 ff.CharSet = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
2766 bool CheckStructCycles (Struct s)
2768 if (s.Fields == null)
2775 foreach (FieldBase field in s.Fields) {
2776 TypeSpec ftype = field.Spec.MemberType;
2777 if (!ftype.IsStruct)
2780 if (ftype is BuiltinTypeSpec)
2783 foreach (var targ in ftype.TypeArguments) {
2784 if (!CheckFieldTypeCycle (targ)) {
2785 Report.Error (523, field.Location,
2786 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2787 field.GetSignatureForError (), ftype.GetSignatureForError ());
2793 // Static fields of exactly same type are allowed
2795 if (field.IsStatic && ftype == s.CurrentType)
2798 if (!CheckFieldTypeCycle (ftype)) {
2799 Report.Error (523, field.Location,
2800 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2801 field.GetSignatureForError (), ftype.GetSignatureForError ());
2806 s.InTransit = false;
2810 bool CheckFieldTypeCycle (TypeSpec ts)
2812 var fts = ts.MemberDefinition as Struct;
2816 return CheckStructCycles (fts);
2819 public override void Emit ()
2821 CheckStructCycles (this);
2826 public override bool IsUnmanagedType ()
2828 if (has_unmanaged_check_done)
2829 return is_unmanaged;
2831 if (requires_delayed_unmanagedtype_check)
2834 if (Parent != null && Parent.IsGeneric) {
2835 has_unmanaged_check_done = true;
2839 if (fields != null) {
2840 requires_delayed_unmanagedtype_check = true;
2842 foreach (FieldBase f in fields) {
2846 // It can happen when recursive unmanaged types are defined
2847 // struct S { S* s; }
2848 TypeSpec mt = f.MemberType;
2856 has_unmanaged_check_done = true;
2860 has_unmanaged_check_done = true;
2863 is_unmanaged = true;
2867 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2869 var ifaces = base.ResolveBaseTypes (out base_class);
2870 base_type = Compiler.BuiltinTypes.ValueType;
2874 protected override TypeAttributes TypeAttr {
2876 const TypeAttributes DefaultTypeAttributes =
2877 TypeAttributes.SequentialLayout |
2878 TypeAttributes.Sealed;
2880 return base.TypeAttr | DefaultTypeAttributes;
2884 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
2886 if ((field.ModFlags & Modifiers.STATIC) == 0) {
2887 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
2888 field.GetSignatureForError ());
2891 base.RegisterFieldForInitialization (field, expression);
2899 public sealed class Interface : TypeContainer {
2902 /// Modifiers allowed in a class declaration
2904 const Modifiers AllowedModifiers =
2907 Modifiers.PROTECTED |
2908 Modifiers.INTERNAL |
2912 public Interface (NamespaceContainer ns, DeclSpace parent, MemberName name, Modifiers mod,
2914 : base (ns, parent, name, attrs, MemberKind.Interface)
2916 var accmods = parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2918 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
2919 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2924 public override AttributeTargets AttributeTargets {
2926 return AttributeTargets.Interface;
2930 protected override TypeAttributes TypeAttr {
2932 const TypeAttributes DefaultTypeAttributes =
2933 TypeAttributes.AutoLayout |
2934 TypeAttributes.Abstract |
2935 TypeAttributes.Interface;
2937 return base.TypeAttr | DefaultTypeAttributes;
2943 public override void Accept (StructuralVisitor visitor)
2945 visitor.Visit (this);
2948 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2950 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2951 a.Error_MissingGuidAttribute ();
2955 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2958 protected override bool VerifyClsCompliance ()
2960 if (!base.VerifyClsCompliance ())
2963 if (iface_exprs != null) {
2964 foreach (var iface in iface_exprs) {
2965 if (iface.IsCLSCompliant ())
2968 Report.SymbolRelatedToPreviousError (iface);
2969 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
2970 GetSignatureForError (), TypeManager.CSharpName (iface));
2978 public abstract class InterfaceMemberBase : MemberBase
2981 // Common modifiers allowed in a class declaration
2983 protected const Modifiers AllowedModifiersClass =
2986 Modifiers.PROTECTED |
2987 Modifiers.INTERNAL |
2992 Modifiers.OVERRIDE |
2993 Modifiers.ABSTRACT |
2998 // Common modifiers allowed in a struct declaration
3000 protected const Modifiers AllowedModifiersStruct =
3003 Modifiers.PROTECTED |
3004 Modifiers.INTERNAL |
3007 Modifiers.OVERRIDE |
3012 // Common modifiers allowed in a interface declaration
3014 protected const Modifiers AllowedModifiersInterface =
3019 // Whether this is an interface member.
3021 public bool IsInterface;
3024 // If true, this is an explicit interface implementation
3026 public bool IsExplicitImpl;
3028 protected bool is_external_implementation;
3031 // The interface type we are explicitly implementing
3033 public TypeSpec InterfaceType;
3036 // The method we're overriding if this is an override method.
3038 protected MethodSpec base_method;
3040 readonly Modifiers explicit_mod_flags;
3041 public MethodAttributes flags;
3043 public InterfaceMemberBase (DeclSpace parent, GenericMethod generic,
3044 FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
3045 MemberName name, Attributes attrs)
3046 : base (parent, generic, type, mod, allowed_mod, Modifiers.PRIVATE,
3049 IsInterface = parent.PartialContainer.Kind == MemberKind.Interface;
3050 IsExplicitImpl = (MemberName.Left != null);
3051 explicit_mod_flags = mod;
3054 public abstract Variance ExpectedMemberTypeVariance { get; }
3056 protected override bool CheckBase ()
3058 if (!base.CheckBase ())
3061 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3062 CheckForDuplications ();
3067 // For System.Object only
3068 if (Parent.BaseType == null)
3071 MemberSpec candidate;
3072 bool overrides = false;
3073 var base_member = FindBaseMember (out candidate, ref overrides);
3075 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3076 if (base_member == null) {
3077 if (candidate == null) {
3078 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3079 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3080 "object.Finalize()");
3082 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3083 GetSignatureForError (), SimpleName.GetMemberType (this));
3086 Report.SymbolRelatedToPreviousError (candidate);
3088 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3089 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3090 else if (this is PropertyBase)
3091 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3092 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3094 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3095 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3102 // Handles ambiguous overrides
3104 if (candidate != null) {
3105 Report.SymbolRelatedToPreviousError (candidate);
3106 Report.SymbolRelatedToPreviousError (base_member);
3108 // Get member definition for error reporting
3109 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3110 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3112 Report.Error (462, Location,
3113 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3114 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3117 if (!CheckOverrideAgainstBase (base_member))
3120 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3122 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3123 Report.SymbolRelatedToPreviousError (base_member);
3124 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3125 GetSignatureForError (), base_member.GetSignatureForError ());
3128 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3129 Report.SymbolRelatedToPreviousError (base_member);
3130 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3131 GetSignatureForError (), base_member.GetSignatureForError ());
3135 base_method = base_member as MethodSpec;
3139 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3140 base_member = candidate;
3142 if (base_member == null) {
3143 if ((ModFlags & Modifiers.NEW) != 0) {
3144 if (base_member == null) {
3145 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3146 GetSignatureForError ());
3150 if ((ModFlags & Modifiers.NEW) == 0) {
3151 ModFlags |= Modifiers.NEW;
3152 if (!IsCompilerGenerated) {
3153 Report.SymbolRelatedToPreviousError (base_member);
3154 if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3155 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",
3156 GetSignatureForError (), base_member.GetSignatureForError ());
3158 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3159 GetSignatureForError (), base_member.GetSignatureForError ());
3164 if (!IsInterface && base_member.IsAbstract && !overrides) {
3165 Report.SymbolRelatedToPreviousError (base_member);
3166 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3167 GetSignatureForError (), base_member.GetSignatureForError ());
3174 protected virtual bool CheckForDuplications ()
3176 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3180 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3181 // that have been defined.
3183 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3187 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3188 Report.SymbolRelatedToPreviousError (base_member);
3189 Report.Error (506, Location,
3190 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3191 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3195 // Now we check that the overriden method is not final
3196 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3197 Report.SymbolRelatedToPreviousError (base_member);
3198 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3199 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3203 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3204 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3205 Report.SymbolRelatedToPreviousError (base_member);
3206 if (this is PropertyBasedMember) {
3207 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3208 GetSignatureForError (), TypeManager.CSharpName (base_member_type), TypeManager.CSharpSignature (base_member));
3210 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3211 GetSignatureForError (), TypeManager.CSharpName (base_member_type), TypeManager.CSharpSignature (base_member));
3219 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3221 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3222 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3224 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3226 // It must be at least "protected"
3228 if ((thisp & Modifiers.PROTECTED) == 0) {
3233 // when overriding protected internal, the method can be declared
3234 // protected internal only within the same assembly or assembly
3235 // which has InternalsVisibleTo
3237 if ((thisp & Modifiers.INTERNAL) != 0) {
3238 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3242 // protected overriding protected internal inside same assembly
3243 // requires internal modifier as well
3245 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3252 return thisp == base_classp;
3255 public override bool Define ()
3258 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3259 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3261 flags = MethodAttributes.Public |
3262 MethodAttributes.Abstract |
3263 MethodAttributes.HideBySig |
3264 MethodAttributes.NewSlot |
3265 MethodAttributes.Virtual;
3267 Parent.PartialContainer.MethodModifiersValid (this);
3269 flags = ModifiersExtensions.MethodAttr (ModFlags);
3272 if (IsExplicitImpl) {
3273 InterfaceType = MemberName.Left.GetTypeExpression ().ResolveAsType (Parent);
3274 if (InterfaceType == null)
3277 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3278 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3279 GetSignatureForError ());
3282 if (!InterfaceType.IsInterface) {
3283 Report.SymbolRelatedToPreviousError (InterfaceType);
3284 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3285 TypeManager.CSharpName (InterfaceType));
3287 Parent.PartialContainer.VerifyImplements (this);
3290 ModifiersExtensions.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location, Report);
3293 return base.Define ();
3296 protected bool DefineParameters (ParametersCompiled parameters)
3298 if (!parameters.Resolve (this))
3302 for (int i = 0; i < parameters.Count; ++i) {
3303 Parameter p = parameters [i];
3305 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3306 p.Warning_UselessOptionalParameter (Report);
3308 if (p.CheckAccessibility (this))
3311 TypeSpec t = parameters.Types [i];
3312 Report.SymbolRelatedToPreviousError (t);
3313 if (this is Indexer)
3314 Report.Error (55, Location,
3315 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3316 TypeManager.CSharpName (t), GetSignatureForError ());
3317 else if (this is Operator)
3318 Report.Error (57, Location,
3319 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3320 TypeManager.CSharpName (t), GetSignatureForError ());
3322 Report.Error (51, Location,
3323 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3324 TypeManager.CSharpName (t), GetSignatureForError ());
3330 protected override void DoMemberTypeDependentChecks ()
3332 base.DoMemberTypeDependentChecks ();
3334 TypeManager.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3337 public override void Emit()
3339 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3340 // We are more strict than csc and report this as an error because SRE does not allow emit that
3341 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation) {
3342 if (this is Constructor) {
3343 Report.Warning (824, 1, Location,
3344 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3346 Report.Warning (626, 1, Location,
3347 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3348 GetSignatureForError ());
3355 public override bool EnableOverloadChecks (MemberCore overload)
3358 // Two members can differ in their explicit interface
3359 // type parameter only
3361 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3362 if (imb != null && imb.IsExplicitImpl) {
3363 if (IsExplicitImpl) {
3364 caching_flags |= Flags.MethodOverloadsExist;
3369 return IsExplicitImpl;
3372 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3374 var base_modifiers = base_member.Modifiers;
3376 // Remove internal modifier from types which are not internally accessible
3377 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3378 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3379 base_modifiers = Modifiers.PROTECTED;
3381 Report.SymbolRelatedToPreviousError (base_member);
3382 Report.Error (507, member.Location,
3383 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3384 member.GetSignatureForError (),
3385 ModifiersExtensions.AccessibilityName (base_modifiers),
3386 base_member.GetSignatureForError ());
3389 protected void Error_StaticReturnType ()
3391 Report.Error (722, Location,
3392 "`{0}': static types cannot be used as return types",
3393 MemberType.GetSignatureForError ());
3397 /// Gets base method and its return type
3399 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3401 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3405 // The "short" name of this property / indexer / event. This is the
3406 // name without the explicit interface.
3408 public string ShortName {
3409 get { return MemberName.Name; }
3410 set { SetMemberName (new MemberName (MemberName.Left, value, Location)); }
3414 // Returns full metadata method name
3416 public string GetFullName (MemberName name)
3418 return GetFullName (name.Name);
3421 public string GetFullName (string name)
3423 if (!IsExplicitImpl)
3427 // When dealing with explicit members a full interface type
3428 // name is added to member name to avoid possible name conflicts
3430 // We use CSharpName which gets us full name with benefit of
3431 // replacing predefined names which saves some space and name
3434 return TypeManager.CSharpName (InterfaceType) + "." + name;
3437 public override string GetSignatureForDocumentation ()
3440 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetExplicitNameSignatureForDocumentation () + "#" + ShortName;
3442 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3445 protected override bool VerifyClsCompliance ()
3447 if (!base.VerifyClsCompliance ()) {
3451 if (GenericMethod != null)
3452 GenericMethod.VerifyClsCompliance ();
3457 public override bool IsUsed
3459 get { return IsExplicitImpl || base.IsUsed; }
3464 public abstract class MemberBase : MemberCore
3466 protected FullNamedExpression type_expr;
3467 protected TypeSpec member_type;
3469 public readonly DeclSpace ds;
3470 public readonly GenericMethod GenericMethod;
3472 protected MemberBase (DeclSpace parent, GenericMethod generic,
3473 FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod,
3474 MemberName name, Attributes attrs)
3475 : base (parent, name, attrs)
3477 this.ds = generic != null ? generic : (DeclSpace) parent;
3478 this.type_expr = type;
3479 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3480 GenericMethod = generic;
3481 if (GenericMethod != null)
3482 GenericMethod.ModFlags = ModFlags;
3487 public TypeSpec MemberType {
3493 public FullNamedExpression TypeExpression {
3502 // Main member define entry
3504 public override bool Define ()
3506 DoMemberTypeIndependentChecks ();
3509 // Returns false only when type resolution failed
3511 if (!ResolveMemberType ())
3514 DoMemberTypeDependentChecks ();
3519 // Any type_name independent checks
3521 protected virtual void DoMemberTypeIndependentChecks ()
3523 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3524 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3525 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3526 GetSignatureForError (), Parent.GetSignatureForError ());
3531 // Any type_name dependent checks
3533 protected virtual void DoMemberTypeDependentChecks ()
3535 // verify accessibility
3536 if (!IsAccessibleAs (MemberType)) {
3537 Report.SymbolRelatedToPreviousError (MemberType);
3538 if (this is Property)
3539 Report.Error (53, Location,
3540 "Inconsistent accessibility: property type `" +
3541 TypeManager.CSharpName (MemberType) + "' is less " +
3542 "accessible than property `" + GetSignatureForError () + "'");
3543 else if (this is Indexer)
3544 Report.Error (54, Location,
3545 "Inconsistent accessibility: indexer return type `" +
3546 TypeManager.CSharpName (MemberType) + "' is less " +
3547 "accessible than indexer `" + GetSignatureForError () + "'");
3548 else if (this is MethodCore) {
3549 if (this is Operator)
3550 Report.Error (56, Location,
3551 "Inconsistent accessibility: return type `" +
3552 TypeManager.CSharpName (MemberType) + "' is less " +
3553 "accessible than operator `" + GetSignatureForError () + "'");
3555 Report.Error (50, Location,
3556 "Inconsistent accessibility: return type `" +
3557 TypeManager.CSharpName (MemberType) + "' is less " +
3558 "accessible than method `" + GetSignatureForError () + "'");
3560 Report.Error (52, Location,
3561 "Inconsistent accessibility: field type `" +
3562 TypeManager.CSharpName (MemberType) + "' is less " +
3563 "accessible than field `" + GetSignatureForError () + "'");
3568 protected void IsTypePermitted ()
3570 if (MemberType.IsSpecialRuntimeType) {
3571 if (Parent is StateMachine) {
3572 Report.Error (4012, Location,
3573 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3574 MemberType.GetSignatureForError ());
3575 } else if (Parent is HoistedStoreyClass) {
3576 Report.Error (4013, Location,
3577 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3578 MemberType.GetSignatureForError ());
3580 Report.Error (610, Location,
3581 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3586 protected virtual bool CheckBase ()
3588 CheckProtectedModifier ();
3593 public override string GetSignatureForDocumentation ()
3595 return Parent.Name + "." + Name;
3598 protected virtual bool ResolveMemberType ()
3600 if (member_type != null)
3601 throw new InternalErrorException ("Multi-resolve");
3603 member_type = type_expr.ResolveAsType (this);
3604 return member_type != null;