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-2011 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;
21 using System.Diagnostics;
22 using Mono.CompilerServices.SymbolWriter;
25 using XmlElement = System.Object;
29 using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
30 using IKVM.Reflection;
31 using IKVM.Reflection.Emit;
33 using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
34 using System.Reflection;
35 using System.Reflection.Emit;
41 // General types container, used as a base class for all constructs which can hold types
43 public abstract class TypeContainer : MemberCore
45 public readonly MemberKind Kind;
46 public readonly string Basename;
48 protected List<TypeContainer> containers;
50 TypeDefinition main_container;
52 protected Dictionary<string, MemberCore> defined_names;
54 protected bool is_defined;
56 public TypeContainer (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
57 : base (parent, name, attrs)
61 this.Basename = name.Basename;
63 defined_names = new Dictionary<string, MemberCore> ();
66 public override TypeSpec CurrentType {
72 public Dictionary<string, MemberCore> DefinedNames {
78 public TypeDefinition PartialContainer {
80 return main_container;
83 main_container = value;
87 public IList<TypeContainer> Containers {
94 // Any unattached attributes during parsing get added here. User
97 public Attributes UnattachedAttributes {
101 public virtual void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
106 public virtual void AddPartial (TypeDefinition next_part)
109 (PartialContainer ?? this).defined_names.TryGetValue (next_part.Basename, out mc);
111 AddPartial (next_part, mc as TypeDefinition);
114 protected void AddPartial (TypeDefinition next_part, TypeDefinition existing)
116 next_part.ModFlags |= Modifiers.PARTIAL;
118 if (existing == null) {
119 AddTypeContainer (next_part);
123 if ((existing.ModFlags & Modifiers.PARTIAL) == 0) {
124 if (existing.Kind != next_part.Kind) {
125 AddTypeContainer (next_part);
127 Report.SymbolRelatedToPreviousError (next_part);
128 Error_MissingPartialModifier (existing);
134 if (existing.Kind != next_part.Kind) {
135 Report.SymbolRelatedToPreviousError (existing);
136 Report.Error (261, next_part.Location,
137 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
138 next_part.GetSignatureForError ());
141 if ((existing.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) &&
142 ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 &&
143 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
144 Report.SymbolRelatedToPreviousError (existing);
145 Report.Error (262, next_part.Location,
146 "Partial declarations of `{0}' have conflicting accessibility modifiers",
147 next_part.GetSignatureForError ());
150 var tc_names = existing.CurrentTypeParameters;
151 if (tc_names != null) {
152 for (int i = 0; i < tc_names.Count; ++i) {
153 var tp = next_part.MemberName.TypeParameters[i];
154 if (tc_names[i].MemberName.Name != tp.MemberName.Name) {
155 Report.SymbolRelatedToPreviousError (existing.Location, "");
156 Report.Error (264, next_part.Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
157 next_part.GetSignatureForError ());
161 if (tc_names[i].Variance != tp.Variance) {
162 Report.SymbolRelatedToPreviousError (existing.Location, "");
163 Report.Error (1067, next_part.Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers",
164 next_part.GetSignatureForError ());
170 if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
171 existing.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
172 } else if ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
173 existing.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
174 existing.ModFlags |= next_part.ModFlags;
176 existing.ModFlags |= next_part.ModFlags;
179 existing.Definition.Modifiers = existing.ModFlags;
181 if (next_part.attributes != null) {
182 if (existing.attributes == null)
183 existing.attributes = next_part.attributes;
185 existing.attributes.AddAttributes (next_part.attributes.Attrs);
188 next_part.PartialContainer = existing;
190 if (containers == null)
191 containers = new List<TypeContainer> ();
193 containers.Add (next_part);
196 public virtual void AddTypeContainer (TypeContainer tc)
200 var tparams = tc.MemberName.TypeParameters;
201 if (tparams != null && tc.PartialContainer != null) {
202 var td = (TypeDefinition) tc;
203 for (int i = 0; i < tparams.Count; ++i) {
205 if (tp.MemberName == null)
208 td.AddNameToContainer (tp, tp.Name);
213 public virtual void CloseContainer ()
215 if (containers != null) {
216 foreach (TypeContainer tc in containers) {
217 tc.CloseContainer ();
222 public virtual void CreateMetadataName (StringBuilder sb)
224 if (Parent != null && Parent.MemberName != null)
225 Parent.CreateMetadataName (sb);
227 MemberName.CreateMetadataName (sb);
230 public virtual bool CreateContainer ()
232 if (containers != null) {
233 foreach (TypeContainer tc in containers) {
234 tc.CreateContainer ();
241 public override bool Define ()
243 if (containers != null) {
244 foreach (TypeContainer tc in containers) {
249 // Release cache used by parser only
250 if (Module.Evaluator == null) {
251 defined_names = null;
253 defined_names.Clear ();
259 public virtual void PrepareEmit ()
261 if (containers != null) {
262 foreach (var t in containers) {
265 } catch (Exception e) {
266 if (MemberName == MemberName.Null)
269 throw new InternalErrorException (t, e);
275 public virtual bool DefineContainer ()
282 DoDefineContainer ();
284 if (containers != null) {
285 foreach (TypeContainer tc in containers) {
287 tc.DefineContainer ();
288 } catch (Exception e) {
289 if (MemberName == MemberName.Null)
292 throw new InternalErrorException (tc, e);
300 public virtual void ExpandBaseInterfaces ()
302 if (containers != null) {
303 foreach (TypeContainer tc in containers) {
304 tc.ExpandBaseInterfaces ();
309 protected virtual void DefineNamespace ()
311 if (containers != null) {
312 foreach (var tc in containers) {
314 tc.DefineNamespace ();
315 } catch (Exception e) {
316 throw new InternalErrorException (tc, e);
322 protected virtual void DoDefineContainer ()
326 public virtual void EmitContainer ()
328 if (containers != null) {
329 for (int i = 0; i < containers.Count; ++i)
330 containers[i].EmitContainer ();
334 protected void Error_MissingPartialModifier (MemberCore type)
336 Report.Error (260, type.Location,
337 "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
338 type.GetSignatureForError ());
341 public override string GetSignatureForDocumentation ()
343 if (Parent != null && Parent.MemberName != null)
344 return Parent.GetSignatureForDocumentation () + "." + MemberName.GetSignatureForDocumentation ();
346 return MemberName.GetSignatureForDocumentation ();
349 public override string GetSignatureForError ()
351 if (Parent != null && Parent.MemberName != null)
352 return Parent.GetSignatureForError () + "." + MemberName.GetSignatureForError ();
354 return MemberName.GetSignatureForError ();
357 public string GetSignatureForMetadata ()
360 if (Parent is TypeDefinition) {
361 return Parent.GetSignatureForMetadata () + "+" + TypeNameParser.Escape (MemberName.Basename);
364 var sb = new StringBuilder ();
365 CreateMetadataName (sb);
366 return sb.ToString ();
368 throw new NotImplementedException ();
372 public virtual void RemoveContainer (TypeContainer cont)
374 if (containers != null)
375 containers.Remove (cont);
377 var tc = Parent == Module ? Module : this;
378 tc.defined_names.Remove (cont.Basename);
381 public virtual void VerifyMembers ()
383 if (containers != null) {
384 foreach (TypeContainer tc in containers)
389 public override void WriteDebugSymbol (MonoSymbolFile file)
391 if (containers != null) {
392 foreach (TypeContainer tc in containers) {
393 tc.WriteDebugSymbol (file);
399 public abstract class TypeDefinition : TypeContainer, ITypeDefinition
402 // Different context is needed when resolving type container base
403 // types. Type names come from the parent scope but type parameter
404 // names from the container scope.
406 public struct BaseContext : IMemberContext
410 public BaseContext (TypeContainer tc)
415 #region IMemberContext Members
417 public CompilerContext Compiler {
418 get { return tc.Compiler; }
421 public TypeSpec CurrentType {
422 get { return tc.Parent.CurrentType; }
425 public TypeParameters CurrentTypeParameters {
426 get { return tc.PartialContainer.CurrentTypeParameters; }
429 public MemberCore CurrentMemberDefinition {
433 public bool IsObsolete {
434 get { return tc.IsObsolete; }
437 public bool IsUnsafe {
438 get { return tc.IsUnsafe; }
441 public bool IsStatic {
442 get { return tc.IsStatic; }
445 public ModuleContainer Module {
446 get { return tc.Module; }
449 public string GetSignatureForError ()
451 return tc.GetSignatureForError ();
454 public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
459 public FullNamedExpression LookupNamespaceAlias (string name)
461 return tc.Parent.LookupNamespaceAlias (name);
464 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
467 var tp = CurrentTypeParameters;
469 TypeParameter t = tp.Find (name);
471 return new TypeParameterExpr (t, loc);
475 return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc);
485 GetHashCode = 1 << 1,
486 HasStaticFieldInitializer = 1 << 2
489 readonly List<MemberCore> members;
491 // Holds a list of fields that have initializers
492 protected List<FieldInitializer> initialized_fields;
494 // Holds a list of static fields that have initializers
495 protected List<FieldInitializer> initialized_static_fields;
497 Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
499 Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
502 // Points to the first non-static field added to the container.
504 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
505 // and the first one's as good as any.
507 protected FieldBase first_nonstatic_field;
510 // This one is computed after we can distinguish interfaces
511 // from classes from the arraylist `type_bases'
513 protected TypeSpec base_type;
514 FullNamedExpression base_type_expr; // TODO: It's temporary variable
515 protected TypeSpec[] iface_exprs;
517 protected List<FullNamedExpression> type_bases;
519 TypeDefinition InTransit;
521 public TypeBuilder TypeBuilder;
522 GenericTypeParameterBuilder[] all_tp_builders;
524 // All recursive type parameters put together sharing same
525 // TypeParameter instances
527 TypeParameters all_type_parameters;
529 public const string DefaultIndexerName = "Item";
531 bool has_normal_indexers;
533 protected bool requires_delayed_unmanagedtype_check;
535 bool members_defined;
536 bool members_defined_ok;
537 protected bool has_static_constructor;
539 private CachedMethods cached_method;
541 protected TypeSpec spec;
542 TypeSpec current_type;
544 public int DynamicSitesCounter;
545 public int AnonymousMethodsCounter;
546 public int MethodGroupsCounter;
548 static readonly string[] attribute_targets = new string[] { "type" };
551 /// The pending methods that need to be implemented
552 // (interfaces or abstract methods)
554 PendingImplementation pending;
556 public TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
557 : base (parent, name, attrs, kind)
559 PartialContainer = this;
560 members = new List<MemberCore> ();
565 public List<FullNamedExpression> BaseTypeExpressions {
571 public override TypeSpec CurrentType {
573 if (current_type == null) {
574 if (IsGenericOrParentIsGeneric) {
576 // Switch to inflated version as it's used by all expressions
578 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Types;
579 current_type = spec.MakeGenericType (this, targs);
589 public override TypeParameters CurrentTypeParameters {
591 return PartialContainer.MemberName.TypeParameters;
595 int CurrentTypeParametersStartIndex {
597 int total = all_tp_builders.Length;
598 if (CurrentTypeParameters != null) {
599 return total - CurrentTypeParameters.Count;
605 public virtual AssemblyDefinition DeclaringAssembly {
607 return Module.DeclaringAssembly;
611 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
613 return Module.DeclaringAssembly;
617 public TypeSpec Definition {
623 public bool HasMembersDefined {
625 return members_defined;
629 public bool HasInstanceConstructor {
631 return (caching_flags & Flags.HasInstanceConstructor) != 0;
634 caching_flags |= Flags.HasInstanceConstructor;
638 // Indicated whether container has StructLayout attribute set Explicit
639 public bool HasExplicitLayout {
640 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
641 set { caching_flags |= Flags.HasExplicitLayout; }
644 public bool HasOperators {
646 return (caching_flags & Flags.HasUserOperators) != 0;
649 caching_flags |= Flags.HasUserOperators;
653 public bool HasStructLayout {
654 get { return (caching_flags & Flags.HasStructLayout) != 0; }
655 set { caching_flags |= Flags.HasStructLayout; }
658 public TypeSpec[] Interfaces {
664 public bool IsGenericOrParentIsGeneric {
666 return all_type_parameters != null;
670 public bool IsTopLevel {
672 return !(Parent is TypeDefinition);
676 public bool IsPartial {
678 return (ModFlags & Modifiers.PARTIAL) != 0;
682 bool ITypeDefinition.IsTypeForwarder {
689 // Returns true for secondary partial containers
693 return PartialContainer != this;
697 public MemberCache MemberCache {
699 return spec.MemberCache;
703 public List<MemberCore> Members {
709 string ITypeDefinition.Namespace {
712 while (p.Kind != MemberKind.Namespace)
715 return p.MemberName == null ? null : p.GetSignatureForError ();
719 public TypeParameters TypeParametersAll {
721 return all_type_parameters;
725 public override string[] ValidAttributeTargets {
727 return attribute_targets;
733 public override void Accept (StructuralVisitor visitor)
735 visitor.Visit (this);
738 public void AddMember (MemberCore symbol)
740 if (symbol.MemberName.ExplicitInterface != null) {
741 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
742 Report.Error (541, symbol.Location,
743 "`{0}': explicit interface declaration can only be declared in a class or struct",
744 symbol.GetSignatureForError ());
748 AddNameToContainer (symbol, symbol.MemberName.Basename);
749 members.Add (symbol);
752 public override void AddTypeContainer (TypeContainer tc)
754 AddNameToContainer (tc, tc.Basename);
756 if (containers == null)
757 containers = new List<TypeContainer> ();
760 base.AddTypeContainer (tc);
763 public override void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
767 if (containers == null)
768 containers = new List<TypeContainer> ();
770 base.AddCompilerGeneratedClass (c);
774 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
776 public virtual void AddNameToContainer (MemberCore symbol, string name)
778 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
782 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
783 PartialContainer.defined_names.Add (name, symbol);
787 if (symbol.EnableOverloadChecks (mc))
790 InterfaceMemberBase im = mc as InterfaceMemberBase;
791 if (im != null && im.IsExplicitImpl)
794 Report.SymbolRelatedToPreviousError (mc);
795 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
796 Error_MissingPartialModifier (symbol);
800 if (symbol is TypeParameter) {
801 Report.Error (692, symbol.Location,
802 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
804 Report.Error (102, symbol.Location,
805 "The type `{0}' already contains a definition for `{1}'",
806 GetSignatureForError (), name);
812 public void AddConstructor (Constructor c)
814 AddConstructor (c, false);
817 public void AddConstructor (Constructor c, bool isDefault)
819 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
821 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
823 if (is_static && c.ParameterInfo.IsEmpty) {
824 PartialContainer.has_static_constructor = true;
826 PartialContainer.HasInstanceConstructor = true;
832 public bool AddField (FieldBase field)
836 if ((field.ModFlags & Modifiers.STATIC) != 0)
839 var first_field = PartialContainer.first_nonstatic_field;
840 if (first_field == null) {
841 PartialContainer.first_nonstatic_field = field;
845 if (Kind == MemberKind.Struct && first_field.Parent != field.Parent) {
846 Report.SymbolRelatedToPreviousError (first_field.Parent);
847 Report.Warning (282, 3, field.Location,
848 "struct instance field `{0}' found in different declaration from instance field `{1}'",
849 field.GetSignatureForError (), first_field.GetSignatureForError ());
855 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
857 public void AddIndexer (Indexer i)
862 public void AddOperator (Operator op)
864 PartialContainer.HasOperators = true;
868 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
870 if (has_normal_indexers && a.Type == pa.DefaultMember) {
871 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
875 if (a.Type == pa.Required) {
876 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
880 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
883 public override AttributeTargets AttributeTargets {
885 throw new NotSupportedException ();
889 public TypeSpec BaseType {
891 return spec.BaseType;
895 protected virtual TypeAttributes TypeAttr {
897 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
901 public int TypeParametersCount {
903 return MemberName.Arity;
907 TypeParameterSpec[] ITypeDefinition.TypeParameters {
909 return PartialContainer.CurrentTypeParameters.Types;
913 public string GetAttributeDefaultMember ()
915 return indexer_name ?? DefaultIndexerName;
918 public bool IsComImport {
920 if (OptAttributes == null)
923 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
927 public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
930 PartialContainer.RegisterFieldForInitialization (field, expression);
932 if ((field.ModFlags & Modifiers.STATIC) != 0){
933 if (initialized_static_fields == null) {
934 HasStaticFieldInitializer = true;
935 initialized_static_fields = new List<FieldInitializer> (4);
938 initialized_static_fields.Add (expression);
940 if (initialized_fields == null)
941 initialized_fields = new List<FieldInitializer> (4);
943 initialized_fields.Add (expression);
947 public void ResolveFieldInitializers (BlockContext ec)
949 Debug.Assert (!IsPartialPart);
952 if (initialized_static_fields == null)
955 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
957 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
958 for (i = 0; i < initialized_static_fields.Count; ++i) {
959 FieldInitializer fi = initialized_static_fields [i];
960 ExpressionStatement s = fi.ResolveStatement (ec);
962 s = EmptyExpressionStatement.Instance;
963 } else if (!fi.IsSideEffectFree) {
964 has_complex_initializer |= true;
970 for (i = 0; i < initialized_static_fields.Count; ++i) {
971 FieldInitializer fi = initialized_static_fields [i];
973 // Need special check to not optimize code like this
974 // static int a = b = 5;
977 if (!has_complex_initializer && fi.IsDefaultInitializer)
980 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
986 if (initialized_fields == null)
989 for (int i = 0; i < initialized_fields.Count; ++i) {
990 FieldInitializer fi = initialized_fields [i];
991 ExpressionStatement s = fi.ResolveStatement (ec);
996 // Field is re-initialized to its default value => removed
998 if (fi.IsDefaultInitializer && ec.Module.Compiler.Settings.Optimize)
1001 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
1005 public override string DocComment {
1017 public PendingImplementation PendingImplementations {
1018 get { return pending; }
1021 internal override void GenerateDocComment (DocumentationBuilder builder)
1026 base.GenerateDocComment (builder);
1028 foreach (var member in members)
1029 member.GenerateDocComment (builder);
1032 public TypeSpec GetAttributeCoClass ()
1034 if (OptAttributes == null)
1037 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
1041 return a.GetCoClassAttributeValue ();
1044 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1047 if (OptAttributes != null) {
1048 a = OptAttributes.Search (pa);
1054 return a.GetAttributeUsageAttribute ();
1057 public virtual CompilationSourceFile GetCompilationSourceFile ()
1059 TypeContainer ns = Parent;
1061 var sf = ns as CompilationSourceFile;
1069 public virtual void AddBasesForPart (List<FullNamedExpression> bases)
1075 /// This function computes the Base class and also the
1076 /// list of interfaces that the class or struct @c implements.
1078 /// The return value is an array (might be null) of
1079 /// interfaces implemented (as Types).
1081 /// The @base_class argument is set to the base object or null
1082 /// if this is `System.Object'.
1084 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1087 if (type_bases == null)
1090 int count = type_bases.Count;
1091 TypeSpec[] ifaces = null;
1092 var base_context = new BaseContext (this);
1093 for (int i = 0, j = 0; i < count; i++){
1094 FullNamedExpression fne = type_bases [i];
1096 var fne_resolved = fne.ResolveAsType (base_context);
1097 if (fne_resolved == null)
1100 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1101 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1102 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1103 GetSignatureForError ());
1108 base_type = fne_resolved;
1114 ifaces = new TypeSpec [count - i];
1116 if (fne_resolved.IsInterface) {
1117 for (int ii = 0; ii < j; ++ii) {
1118 if (fne_resolved == ifaces [ii]) {
1119 Report.Error (528, Location, "`{0}' is already listed in interface list",
1120 fne_resolved.GetSignatureForError ());
1125 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1126 Report.Error (61, fne.Location,
1127 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1128 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1131 Report.SymbolRelatedToPreviousError (fne_resolved);
1132 if (Kind != MemberKind.Class) {
1133 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1134 } else if (base_class != null)
1135 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1136 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1138 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1139 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1143 ifaces [j++] = fne_resolved;
1150 // Checks that some operators come in pairs:
1156 // They are matched based on the return type and the argument types
1158 void CheckPairedOperators ()
1160 bool has_equality_or_inequality = false;
1161 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1163 for (int i = 0; i < members.Count; ++i) {
1164 var o_a = members[i] as Operator;
1168 var o_type = o_a.OperatorType;
1169 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1170 has_equality_or_inequality = true;
1172 if (found_matched.Contains (o_type))
1175 var matching_type = o_a.GetMatchingOperator ();
1176 if (matching_type == Operator.OpType.TOP) {
1180 bool pair_found = false;
1181 for (int ii = i + 1; ii < members.Count; ++ii) {
1182 var o_b = members[ii] as Operator;
1183 if (o_b == null || o_b.OperatorType != matching_type)
1186 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1189 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1192 found_matched.Add (matching_type);
1198 Report.Error (216, o_a.Location,
1199 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1200 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1204 if (has_equality_or_inequality) {
1206 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1207 GetSignatureForError ());
1209 if (!HasGetHashCode)
1210 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1211 GetSignatureForError ());
1215 public override void CreateMetadataName (StringBuilder sb)
1217 if (Parent.MemberName != null) {
1218 Parent.CreateMetadataName (sb);
1220 if (sb.Length != 0) {
1225 sb.Append (MemberName.Basename);
1228 bool CreateTypeBuilder ()
1231 // Sets .size to 1 for structs with no instance fields
1233 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null && !(this is StateMachine) ? 1 : 0;
1235 var parent_def = Parent as TypeDefinition;
1236 if (parent_def == null) {
1237 var sb = new StringBuilder ();
1238 CreateMetadataName (sb);
1239 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1241 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (Basename, TypeAttr, null, type_size);
1244 if (DeclaringAssembly.Importer != null)
1245 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1247 spec.SetMetaInfo (TypeBuilder);
1248 spec.MemberCache = new MemberCache (this);
1250 TypeParameters parentAllTypeParameters = null;
1251 if (parent_def != null) {
1252 spec.DeclaringType = Parent.CurrentType;
1253 parent_def.MemberCache.AddMember (spec);
1254 parentAllTypeParameters = parent_def.all_type_parameters;
1257 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1258 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1260 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1262 if (CurrentTypeParameters != null) {
1263 CurrentTypeParameters.Create (spec, CurrentTypeParametersStartIndex, this);
1264 CurrentTypeParameters.Define (all_tp_builders);
1271 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1274 int parent_offset = 0;
1275 if (parentAllTypeParameters != null) {
1276 if (CurrentTypeParameters == null) {
1277 all_type_parameters = parentAllTypeParameters;
1278 return parentAllTypeParameters.GetAllNames ();
1281 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1282 all_type_parameters = new TypeParameters (names.Length);
1283 all_type_parameters.Add (parentAllTypeParameters);
1285 parent_offset = all_type_parameters.Count;
1286 for (int i = 0; i < parent_offset; ++i)
1287 names[i] = all_type_parameters[i].MemberName.Name;
1290 names = new string[CurrentTypeParameters.Count];
1293 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1294 if (all_type_parameters != null)
1295 all_type_parameters.Add (MemberName.TypeParameters[i]);
1297 var name = CurrentTypeParameters[i].MemberName.Name;
1298 names[parent_offset + i] = name;
1299 for (int ii = 0; ii < parent_offset + i; ++ii) {
1300 if (names[ii] != name)
1303 var tp = CurrentTypeParameters[i];
1304 var conflict = all_type_parameters[ii];
1306 tp.WarningParentNameConflict (conflict);
1310 if (all_type_parameters == null)
1311 all_type_parameters = CurrentTypeParameters;
1317 public SourceMethodBuilder CreateMethodSymbolEntry ()
1319 if (Module.DeclaringAssembly.SymbolWriter == null)
1322 var source_file = GetCompilationSourceFile ();
1323 if (source_file == null)
1326 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1330 // Creates a proxy base method call inside this container for hoisted base member calls
1332 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1334 Method proxy_method;
1337 // One proxy per base method is enough
1339 if (hoisted_base_call_proxies == null) {
1340 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1341 proxy_method = null;
1343 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1346 if (proxy_method == null) {
1347 string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1349 MemberName member_name;
1350 TypeArguments targs = null;
1351 TypeSpec return_type = method.ReturnType;
1352 var local_param_types = method.Parameters.Types;
1354 if (method.IsGeneric) {
1356 // Copy all base generic method type parameters info
1358 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1359 var tparams = new TypeParameters ();
1361 targs = new TypeArguments ();
1362 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1363 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1364 var tp = hoisted_tparams[i];
1365 var local_tp = new TypeParameter (tp, null, new MemberName (tp.Name, Location), null);
1366 tparams.Add (local_tp);
1368 targs.Add (new SimpleName (tp.Name, Location));
1369 targs.Arguments[i] = local_tp.Type;
1372 member_name = new MemberName (name, tparams, Location);
1375 // Mutate any method type parameters from original
1376 // to newly created hoisted version
1378 var mutator = new TypeParameterMutator (hoisted_tparams, tparams);
1379 return_type = mutator.Mutate (return_type);
1380 local_param_types = mutator.Mutate (local_param_types);
1382 member_name = new MemberName (name);
1385 var base_parameters = new Parameter[method.Parameters.Count];
1386 for (int i = 0; i < base_parameters.Length; ++i) {
1387 var base_param = method.Parameters.FixedParameters[i];
1388 base_parameters[i] = new Parameter (new TypeExpression (local_param_types [i], Location),
1389 base_param.Name, base_param.ModFlags, null, Location);
1390 base_parameters[i].Resolve (this, i);
1393 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
1394 if (method.Parameters.HasArglist) {
1395 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1396 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1399 // Compiler generated proxy
1400 proxy_method = new Method (this, new TypeExpression (return_type, Location),
1401 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1402 member_name, cloned_params, null);
1404 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1405 IsCompilerGenerated = true
1408 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1409 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1411 mg.SetTypeArguments (rc, targs);
1413 // Get all the method parameters and pass them as arguments
1414 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1415 Statement statement;
1416 if (method.ReturnType.Kind == MemberKind.Void)
1417 statement = new StatementExpression (real_base_call);
1419 statement = new Return (real_base_call, Location);
1421 block.AddStatement (statement);
1422 proxy_method.Block = block;
1424 members.Add (proxy_method);
1425 proxy_method.Define ();
1426 proxy_method.PrepareEmit ();
1428 hoisted_base_call_proxies.Add (method, proxy_method);
1431 return proxy_method.Spec;
1434 protected bool DefineBaseTypes ()
1436 iface_exprs = ResolveBaseTypes (out base_type_expr);
1439 if (IsPartialPart) {
1440 set_base_type = false;
1442 if (base_type_expr != null) {
1443 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1444 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1445 Report.Error (263, Location,
1446 "Partial declarations of `{0}' must not specify different base classes",
1447 GetSignatureForError ());
1449 PartialContainer.base_type_expr = base_type_expr;
1450 PartialContainer.base_type = base_type;
1451 set_base_type = true;
1455 if (iface_exprs != null) {
1456 if (PartialContainer.iface_exprs == null)
1457 PartialContainer.iface_exprs = iface_exprs;
1459 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1460 foreach (var iface_partial in iface_exprs) {
1461 if (ifaces.Contains (iface_partial))
1464 ifaces.Add (iface_partial);
1467 PartialContainer.iface_exprs = ifaces.ToArray ();
1471 PartialContainer.members.AddRange (members);
1472 if (containers != null) {
1473 if (PartialContainer.containers == null)
1474 PartialContainer.containers = new List<TypeContainer> ();
1476 PartialContainer.containers.AddRange (containers);
1479 members_defined = members_defined_ok = true;
1480 caching_flags |= Flags.CloseTypeCreated;
1482 set_base_type = true;
1485 var cycle = CheckRecursiveDefinition (this);
1486 if (cycle != null) {
1487 Report.SymbolRelatedToPreviousError (cycle);
1488 if (this is Interface) {
1489 Report.Error (529, Location,
1490 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1491 GetSignatureForError (), cycle.GetSignatureForError ());
1494 PartialContainer.iface_exprs = null;
1496 Report.Error (146, Location,
1497 "Circular base class dependency involving `{0}' and `{1}'",
1498 GetSignatureForError (), cycle.GetSignatureForError ());
1501 PartialContainer.base_type = null;
1505 if (iface_exprs != null) {
1506 foreach (var iface_type in iface_exprs) {
1507 // Prevents a crash, the interface might not have been resolved: 442144
1508 if (iface_type == null)
1511 if (!spec.AddInterfaceDefined (iface_type))
1514 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1518 if (Kind == MemberKind.Interface) {
1519 spec.BaseType = Compiler.BuiltinTypes.Object;
1523 if (set_base_type) {
1524 if (base_type != null) {
1525 spec.BaseType = base_type;
1527 // Set base type after type creation
1528 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1530 TypeBuilder.SetParent (null);
1537 public override void ExpandBaseInterfaces ()
1540 DoExpandBaseInterfaces ();
1542 base.ExpandBaseInterfaces ();
1545 public void DoExpandBaseInterfaces ()
1547 if ((caching_flags & Flags.InterfacesExpanded) != 0)
1550 caching_flags |= Flags.InterfacesExpanded;
1553 // Expand base interfaces. It cannot be done earlier because all partial
1554 // interface parts need to be defined before the type they are used from
1556 if (iface_exprs != null) {
1557 foreach (var iface in iface_exprs) {
1561 var td = iface.MemberDefinition as TypeDefinition;
1563 td.DoExpandBaseInterfaces ();
1565 if (iface.Interfaces == null)
1568 foreach (var biface in iface.Interfaces) {
1569 if (spec.AddInterfaceDefined (biface)) {
1570 TypeBuilder.AddInterfaceImplementation (biface.GetMetaInfo ());
1577 // Include all base type interfaces too, see ImportTypeBase for details
1579 if (base_type != null) {
1580 var td = base_type.MemberDefinition as TypeDefinition;
1582 td.DoExpandBaseInterfaces ();
1585 // Simply use base interfaces only, they are all expanded which makes
1586 // it easy to handle generic type argument propagation with single
1589 // interface IA<T> : IB<T>
1590 // interface IB<U> : IC<U>
1593 if (base_type.Interfaces != null) {
1594 foreach (var iface in base_type.Interfaces) {
1595 spec.AddInterfaceDefined (iface);
1601 public override void PrepareEmit ()
1603 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1606 foreach (var member in members) {
1607 var pm = member as IParametersMember;
1609 var mc = member as MethodOrOperator;
1614 var p = pm.Parameters;
1618 ((ParametersCompiled) p).ResolveDefaultValues (member);
1621 var c = member as Const;
1626 base.PrepareEmit ();
1630 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1632 public override bool CreateContainer ()
1634 if (TypeBuilder != null)
1640 if (IsPartialPart) {
1641 spec = PartialContainer.spec;
1642 TypeBuilder = PartialContainer.TypeBuilder;
1643 all_tp_builders = PartialContainer.all_tp_builders;
1644 all_type_parameters = PartialContainer.all_type_parameters;
1646 if (!CreateTypeBuilder ()) {
1652 return base.CreateContainer ();
1655 protected override void DoDefineContainer ()
1659 DoResolveTypeParameters ();
1663 // Replaces normal spec with predefined one when compiling corlib
1664 // and this type container defines predefined type
1666 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1668 // When compiling build-in types we start with two
1669 // version of same type. One is of BuiltinTypeSpec and
1670 // second one is ordinary TypeSpec. The unification
1671 // happens at later stage when we know which type
1672 // really matches the builtin type signature. However
1673 // that means TypeSpec create during CreateType of this
1674 // type has to be replaced with builtin one
1676 spec.SetMetaInfo (TypeBuilder);
1677 spec.MemberCache = this.spec.MemberCache;
1678 spec.DeclaringType = this.spec.DeclaringType;
1681 current_type = null;
1684 public override void RemoveContainer (TypeContainer cont)
1686 base.RemoveContainer (cont);
1687 Members.Remove (cont);
1688 Cache.Remove (cont.Basename);
1691 protected virtual bool DoResolveTypeParameters ()
1693 var tparams = CurrentTypeParameters;
1694 if (tparams == null)
1697 var base_context = new BaseContext (this);
1698 for (int i = 0; i < tparams.Count; ++i) {
1699 var tp = tparams[i];
1701 if (!tp.ResolveConstraints (base_context)) {
1707 if (IsPartialPart) {
1708 PartialContainer.CurrentTypeParameters.UpdateConstraints (this);
1714 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1716 if (InTransit != null)
1721 if (base_type != null) {
1722 var ptc = base_type.MemberDefinition as TypeDefinition;
1723 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1727 if (iface_exprs != null) {
1728 foreach (var iface in iface_exprs) {
1729 // the interface might not have been resolved, prevents a crash, see #442144
1732 var ptc = iface.MemberDefinition as Interface;
1733 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1738 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1746 /// Populates our TypeBuilder with fields and methods
1748 public sealed override bool Define ()
1750 if (members_defined)
1751 return members_defined_ok;
1753 members_defined_ok = DoDefineMembers ();
1754 members_defined = true;
1758 return members_defined_ok;
1761 protected virtual bool DoDefineMembers ()
1763 Debug.Assert (!IsPartialPart);
1765 if (iface_exprs != null) {
1766 foreach (var iface_type in iface_exprs) {
1767 if (iface_type == null)
1770 // Ensure the base is always setup
1771 var compiled_iface = iface_type.MemberDefinition as Interface;
1772 if (compiled_iface != null)
1773 compiled_iface.Define ();
1775 ObsoleteAttribute oa = iface_type.GetAttributeObsolete ();
1776 if (oa != null && !IsObsolete)
1777 AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report);
1779 if (iface_type.Arity > 0) {
1780 // TODO: passing `this' is wrong, should be base type iface instead
1781 TypeManager.CheckTypeVariance (iface_type, Variance.Covariant, this);
1783 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1784 Report.Error (1966, Location,
1785 "`{0}': cannot implement a dynamic interface `{1}'",
1786 GetSignatureForError (), iface_type.GetSignatureForError ());
1791 if (iface_type.IsGenericOrParentIsGeneric) {
1792 foreach (var prev_iface in iface_exprs) {
1793 if (prev_iface == iface_type || prev_iface == null)
1796 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1799 Report.Error (695, Location,
1800 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1801 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1806 if (Kind == MemberKind.Interface) {
1807 foreach (var iface in spec.Interfaces) {
1808 MemberCache.AddInterface (iface);
1813 if (base_type != null) {
1815 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1817 if (base_type_expr != null) {
1818 ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
1819 if (obsolete_attr != null && !IsObsolete)
1820 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report);
1822 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1823 Report.Error (698, base_type_expr.Location,
1824 "A generic type cannot derive from `{0}' because it is an attribute class",
1825 base_type.GetSignatureForError ());
1829 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1830 if (baseContainer != null) {
1831 baseContainer.Define ();
1834 // It can trigger define of this type (for generic types only)
1836 if (HasMembersDefined)
1841 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1842 pending = PendingImplementation.GetPendingImplementations (this);
1845 var count = members.Count;
1846 for (int i = 0; i < count; ++i) {
1847 var mc = members[i] as InterfaceMemberBase;
1848 if (mc == null || !mc.IsExplicitImpl)
1853 } catch (Exception e) {
1854 throw new InternalErrorException (mc, e);
1858 for (int i = 0; i < count; ++i) {
1859 var mc = members[i] as InterfaceMemberBase;
1860 if (mc != null && mc.IsExplicitImpl)
1863 if (members[i] is TypeContainer)
1867 members[i].Define ();
1868 } catch (Exception e) {
1869 throw new InternalErrorException (members[i], e);
1874 CheckPairedOperators ();
1877 if (requires_delayed_unmanagedtype_check) {
1878 requires_delayed_unmanagedtype_check = false;
1879 foreach (var member in members) {
1880 var f = member as Field;
1881 if (f != null && f.MemberType != null && f.MemberType.IsPointer)
1882 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
1886 ComputeIndexerName();
1888 if (HasEquals && !HasGetHashCode) {
1889 Report.Warning (659, 3, Location,
1890 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
1893 if (Kind == MemberKind.Interface && iface_exprs != null) {
1894 MemberCache.RemoveHiddenMembers (spec);
1900 void ComputeIndexerName ()
1902 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
1903 if (indexers == null)
1906 string class_indexer_name = null;
1909 // Check normal indexers for consistent name, explicit interface implementation
1910 // indexers are ignored
1912 foreach (var indexer in indexers) {
1914 // FindMembers can return unfiltered full hierarchy names
1916 if (indexer.DeclaringType != spec)
1919 has_normal_indexers = true;
1921 if (class_indexer_name == null) {
1922 indexer_name = class_indexer_name = indexer.Name;
1926 if (indexer.Name != class_indexer_name)
1927 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
1928 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
1932 void EmitIndexerName ()
1934 if (!has_normal_indexers)
1937 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
1941 var encoder = new AttributeEncoder ();
1942 encoder.Encode (GetAttributeDefaultMember ());
1943 encoder.EncodeEmptyNamedArguments ();
1945 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1948 public override void VerifyMembers ()
1951 // Check for internal or private fields that were never assigned
1953 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
1954 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
1955 foreach (var member in members) {
1956 if (member is Event) {
1958 // An event can be assigned from same class only, so we can report
1959 // this warning for all accessibility modes
1962 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
1967 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
1968 if (is_type_exposed)
1971 member.SetIsUsed ();
1974 var f = member as Field;
1978 if (!member.IsUsed) {
1979 if ((member.caching_flags & Flags.IsAssigned) == 0) {
1980 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
1982 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
1983 member.GetSignatureForError ());
1988 if ((f.caching_flags & Flags.IsAssigned) != 0)
1992 // Only report 649 on level 4
1994 if (Compiler.Settings.WarningLevel < 4)
1998 // Don't be pedantic when type requires specific layout
2000 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2003 Constant c = New.Constantify (f.MemberType, f.Location);
2006 value = c.GetValueAsLiteral ();
2007 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
2014 value = " `" + value + "'";
2016 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
2017 f.GetSignatureForError (), value);
2021 base.VerifyMembers ();
2024 public override void Emit ()
2026 if (OptAttributes != null)
2027 OptAttributes.Emit ();
2029 if (!IsCompilerGenerated) {
2031 MemberSpec candidate;
2032 bool overrides = false;
2033 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
2034 if (conflict_symbol == null && candidate == null) {
2035 if ((ModFlags & Modifiers.NEW) != 0)
2036 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
2037 GetSignatureForError ());
2039 if ((ModFlags & Modifiers.NEW) == 0) {
2040 if (candidate == null)
2041 candidate = conflict_symbol;
2043 Report.SymbolRelatedToPreviousError (candidate);
2044 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
2045 GetSignatureForError (), candidate.GetSignatureForError ());
2050 // Run constraints check on all possible generic types
2051 if (base_type != null && base_type_expr != null) {
2052 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
2055 if (iface_exprs != null) {
2056 foreach (var iface_type in iface_exprs) {
2057 if (iface_type == null)
2060 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2065 if (all_tp_builders != null) {
2066 int current_starts_index = CurrentTypeParametersStartIndex;
2067 for (int i = 0; i < all_tp_builders.Length; i++) {
2068 if (i < current_starts_index) {
2069 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2071 var tp = CurrentTypeParameters [i - current_starts_index];
2072 tp.CheckGenericConstraints (!IsObsolete);
2078 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2079 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2082 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2083 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2088 for (int i = 0; i < members.Count; i++)
2092 CheckAttributeClsCompliance ();
2094 if (pending != null)
2095 pending.VerifyPendingMethods ();
2099 void CheckAttributeClsCompliance ()
2101 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2104 foreach (var m in members) {
2105 var c = m as Constructor;
2109 if (c.HasCompliantArgs)
2113 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2116 public sealed override void EmitContainer ()
2118 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2124 public override void CloseContainer ()
2126 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2129 // Close base type container first to avoid TypeLoadException
2130 if (spec.BaseType != null) {
2131 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2132 if (btype != null) {
2133 btype.CloseContainer ();
2135 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2141 caching_flags |= Flags.CloseTypeCreated;
2142 TypeBuilder.CreateType ();
2143 } catch (TypeLoadException) {
2145 // This is fine, the code still created the type
2147 } catch (Exception e) {
2148 throw new InternalErrorException (this, e);
2151 base.CloseContainer ();
2154 initialized_fields = null;
2155 initialized_static_fields = null;
2157 OptAttributes = null;
2161 // Performs the validation on a Method's modifiers (properties have
2162 // the same properties).
2164 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2166 public bool MethodModifiersValid (MemberCore mc)
2168 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2169 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2171 var flags = mc.ModFlags;
2174 // At most one of static, virtual or override
2176 if ((flags & Modifiers.STATIC) != 0){
2177 if ((flags & vao) != 0){
2178 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2179 mc.GetSignatureForError ());
2184 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2185 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2186 mc.GetSignatureForError ());
2191 // If the declaration includes the abstract modifier, then the
2192 // declaration does not include static, virtual or extern
2194 if ((flags & Modifiers.ABSTRACT) != 0){
2195 if ((flags & Modifiers.EXTERN) != 0){
2197 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2201 if ((flags & Modifiers.SEALED) != 0) {
2202 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2206 if ((flags & Modifiers.VIRTUAL) != 0){
2207 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2211 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2212 Report.SymbolRelatedToPreviousError (this);
2213 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2214 mc.GetSignatureForError (), GetSignatureForError ());
2219 if ((flags & Modifiers.PRIVATE) != 0){
2220 if ((flags & vao) != 0){
2221 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2226 if ((flags & Modifiers.SEALED) != 0){
2227 if ((flags & Modifiers.OVERRIDE) == 0){
2228 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2236 protected override bool VerifyClsCompliance ()
2238 if (!base.VerifyClsCompliance ())
2241 // Check all container names for user classes
2242 if (Kind != MemberKind.Delegate)
2243 MemberCache.VerifyClsCompliance (Definition, Report);
2245 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2246 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2247 GetSignatureForError (), BaseType.GetSignatureForError ());
2253 /// Performs checks for an explicit interface implementation. First it
2254 /// checks whether the `interface_type' is a base inteface implementation.
2255 /// Then it checks whether `name' exists in the interface type.
2257 public bool VerifyImplements (InterfaceMemberBase mb)
2259 var ifaces = spec.Interfaces;
2260 if (ifaces != null) {
2261 foreach (TypeSpec t in ifaces){
2262 if (t == mb.InterfaceType)
2267 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2268 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2269 mb.GetSignatureForError (), mb.InterfaceType.GetSignatureForError ());
2274 // Used for visiblity checks to tests whether this definition shares
2275 // base type baseType, it does member-definition search
2277 public bool IsBaseTypeDefinition (TypeSpec baseType)
2279 // RootContext check
2280 if (TypeBuilder == null)
2285 if (type.MemberDefinition == baseType.MemberDefinition)
2288 type = type.BaseType;
2289 } while (type != null);
2294 public override bool IsClsComplianceRequired ()
2297 return PartialContainer.IsClsComplianceRequired ();
2299 return base.IsClsComplianceRequired ();
2302 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2304 return Module.DeclaringAssembly == assembly;
2307 public virtual bool IsUnmanagedType ()
2312 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2314 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2318 // Public function used to locate types.
2320 // Set 'ignore_cs0104' to true if you want to ignore cs0104 errors.
2322 // Returns: Type or null if they type can not be found.
2324 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2326 FullNamedExpression e;
2327 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2333 var tp = CurrentTypeParameters;
2335 TypeParameter tparam = tp.Find (name);
2337 e = new TypeParameterExpr (tparam, Location.Null);
2342 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2344 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2345 e = new TypeExpression (t, Location.Null);
2347 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2351 // TODO MemberCache: How to cache arity stuff ?
2352 if (arity == 0 && mode == LookupMode.Normal)
2358 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2360 // Has any nested type
2361 // Does not work, because base type can have
2362 //if (PartialContainer.Types == null)
2365 var container = PartialContainer.CurrentType;
2366 return MemberCache.FindNestedType (container, name, arity);
2369 public void Mark_HasEquals ()
2371 cached_method |= CachedMethods.Equals;
2374 public void Mark_HasGetHashCode ()
2376 cached_method |= CachedMethods.GetHashCode;
2379 public override void WriteDebugSymbol (MonoSymbolFile file)
2384 foreach (var m in members) {
2385 m.WriteDebugSymbol (file);
2390 /// Method container contains Equals method
2392 public bool HasEquals {
2394 return (cached_method & CachedMethods.Equals) != 0;
2399 /// Method container contains GetHashCode method
2401 public bool HasGetHashCode {
2403 return (cached_method & CachedMethods.GetHashCode) != 0;
2407 public bool HasStaticFieldInitializer {
2409 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2413 cached_method |= CachedMethods.HasStaticFieldInitializer;
2415 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2419 public override string DocCommentHeader {
2420 get { return "T:"; }
2424 public abstract class ClassOrStruct : TypeDefinition
2426 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2428 SecurityType declarative_security;
2430 public ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2431 : base (parent, name, attrs, kind)
2435 protected override TypeAttributes TypeAttr {
2437 TypeAttributes ta = base.TypeAttr;
2438 if (!has_static_constructor)
2439 ta |= TypeAttributes.BeforeFieldInit;
2441 if (Kind == MemberKind.Class) {
2442 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2444 ta |= StaticClassAttribute;
2446 ta |= TypeAttributes.SequentialLayout;
2453 public override void AddNameToContainer (MemberCore symbol, string name)
2455 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2456 if (symbol is TypeParameter) {
2457 Report.Error (694, symbol.Location,
2458 "Type parameter `{0}' has same name as containing type, or method",
2459 symbol.GetSignatureForError ());
2463 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2464 if (imb == null || !imb.IsExplicitImpl) {
2465 Report.SymbolRelatedToPreviousError (this);
2466 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2467 symbol.GetSignatureForError ());
2472 base.AddNameToContainer (symbol, name);
2475 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2477 if (a.IsValidSecurityAttribute ()) {
2478 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2482 if (a.Type == pa.StructLayout) {
2483 PartialContainer.HasStructLayout = true;
2484 if (a.IsExplicitLayoutKind ())
2485 PartialContainer.HasExplicitLayout = true;
2488 if (a.Type == pa.Dynamic) {
2489 a.Error_MisusedDynamicAttribute ();
2493 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2497 /// Defines the default constructors
2499 protected virtual Constructor DefineDefaultConstructor (bool is_static)
2501 // The default instance constructor is public
2502 // If the class is abstract, the default constructor is protected
2503 // The default static constructor is private
2507 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2509 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2512 var c = new Constructor (this, MemberName.Name, mods, null, ParametersCompiled.EmptyReadOnlyParameters, Location);
2513 c.Initializer = new GeneratedBaseInitializer (Location);
2515 AddConstructor (c, true);
2516 c.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location) {
2517 IsCompilerGenerated = true
2523 protected override bool DoDefineMembers ()
2525 CheckProtectedModifier ();
2527 base.DoDefineMembers ();
2532 public override void Emit ()
2534 if (!has_static_constructor && HasStaticFieldInitializer) {
2535 var c = DefineDefaultConstructor (true);
2541 if (declarative_security != null) {
2542 foreach (var de in declarative_security) {
2544 TypeBuilder.__AddDeclarativeSecurity (de);
2546 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2554 public sealed class Class : ClassOrStruct
2556 const Modifiers AllowedModifiers =
2559 Modifiers.PROTECTED |
2560 Modifiers.INTERNAL |
2562 Modifiers.ABSTRACT |
2567 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2568 : base (parent, name, attrs, MemberKind.Class)
2570 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2571 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2572 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2575 public override void Accept (StructuralVisitor visitor)
2577 visitor.Visit (this);
2580 public override void AddBasesForPart (List<FullNamedExpression> bases)
2582 var pmn = MemberName;
2583 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2584 Report.Error (537, Location,
2585 "The class System.Object cannot have a base class or implement an interface.");
2587 base.AddBasesForPart (bases);
2590 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2592 if (a.Type == pa.AttributeUsage) {
2593 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2594 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2598 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2599 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2603 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2604 a.Error_MissingGuidAttribute ();
2608 if (a.Type == pa.Extension) {
2609 a.Error_MisusedExtensionAttribute ();
2613 if (a.Type.IsConditionallyExcluded (this, Location))
2616 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2619 public override AttributeTargets AttributeTargets {
2621 return AttributeTargets.Class;
2625 protected override bool DoDefineMembers ()
2627 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2628 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2631 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2632 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2636 foreach (var m in Members) {
2637 if (m is Operator) {
2638 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2642 if (m is Destructor) {
2643 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2648 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2652 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2655 if (m is Constructor) {
2656 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2660 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2663 if (!PartialContainer.HasInstanceConstructor)
2664 DefineDefaultConstructor (false);
2667 return base.DoDefineMembers ();
2670 public override void Emit ()
2674 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2675 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2677 if (base_type != null && base_type.HasDynamicElement) {
2678 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2682 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2684 var ifaces = base.ResolveBaseTypes (out base_class);
2686 if (base_class == null) {
2687 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2688 base_type = Compiler.BuiltinTypes.Object;
2690 if (base_type.IsGenericParameter){
2691 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2692 GetSignatureForError (), base_type.GetSignatureForError ());
2693 } else if (base_type.IsStatic) {
2694 Report.SymbolRelatedToPreviousError (base_type);
2695 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2696 GetSignatureForError (), base_type.GetSignatureForError ());
2697 } else if (base_type.IsSealed) {
2698 Report.SymbolRelatedToPreviousError (base_type);
2699 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2700 GetSignatureForError (), base_type.GetSignatureForError ());
2701 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2702 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2703 GetSignatureForError (), base_type.GetSignatureForError ());
2706 switch (base_type.BuiltinType) {
2707 case BuiltinTypeSpec.Type.Enum:
2708 case BuiltinTypeSpec.Type.ValueType:
2709 case BuiltinTypeSpec.Type.MulticastDelegate:
2710 case BuiltinTypeSpec.Type.Delegate:
2711 case BuiltinTypeSpec.Type.Array:
2712 if (!(spec is BuiltinTypeSpec)) {
2713 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2714 GetSignatureForError (), base_type.GetSignatureForError ());
2716 base_type = Compiler.BuiltinTypes.Object;
2721 if (!IsAccessibleAs (base_type)) {
2722 Report.SymbolRelatedToPreviousError (base_type);
2723 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2724 base_type.GetSignatureForError (), GetSignatureForError ());
2728 if (PartialContainer.IsStatic && ifaces != null) {
2729 foreach (var t in ifaces)
2730 Report.SymbolRelatedToPreviousError (t);
2731 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2737 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2738 /// Valid only for attribute classes.
2739 public override string[] ConditionalConditions ()
2741 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2744 caching_flags &= ~Flags.Excluded_Undetected;
2746 if (OptAttributes == null)
2749 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2753 string[] conditions = new string[attrs.Length];
2754 for (int i = 0; i < conditions.Length; ++i)
2755 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2757 caching_flags |= Flags.Excluded;
2762 public sealed class Struct : ClassOrStruct
2764 bool is_unmanaged, has_unmanaged_check_done;
2768 // Modifiers allowed in a struct declaration
2770 const Modifiers AllowedModifiers =
2773 Modifiers.PROTECTED |
2774 Modifiers.INTERNAL |
2778 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2779 : base (parent, name, attrs, MemberKind.Struct)
2781 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2782 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2783 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2786 public override AttributeTargets AttributeTargets {
2788 return AttributeTargets.Struct;
2792 public override void Accept (StructuralVisitor visitor)
2794 visitor.Visit (this);
2797 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2799 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2802 // When struct constains fixed fixed and struct layout has explicitly
2803 // set CharSet, its value has to be propagated to compiler generated
2806 if (a.Type == pa.StructLayout) {
2807 var value = a.GetNamedValue ("CharSet");
2811 for (int i = 0; i < Members.Count; ++i) {
2812 FixedField ff = Members [i] as FixedField;
2816 ff.CharSet = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
2821 bool CheckStructCycles ()
2827 foreach (var member in Members) {
2828 var field = member as Field;
2832 TypeSpec ftype = field.Spec.MemberType;
2833 if (!ftype.IsStruct)
2836 if (ftype is BuiltinTypeSpec)
2839 foreach (var targ in ftype.TypeArguments) {
2840 if (!CheckFieldTypeCycle (targ)) {
2841 Report.Error (523, field.Location,
2842 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2843 field.GetSignatureForError (), ftype.GetSignatureForError ());
2849 // Static fields of exactly same type are allowed
2851 if (field.IsStatic && ftype == CurrentType)
2854 if (!CheckFieldTypeCycle (ftype)) {
2855 Report.Error (523, field.Location,
2856 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2857 field.GetSignatureForError (), ftype.GetSignatureForError ());
2866 static bool CheckFieldTypeCycle (TypeSpec ts)
2868 var fts = ts.MemberDefinition as Struct;
2872 return fts.CheckStructCycles ();
2875 public override void Emit ()
2877 CheckStructCycles ();
2882 public override bool IsUnmanagedType ()
2884 if (has_unmanaged_check_done)
2885 return is_unmanaged;
2887 if (requires_delayed_unmanagedtype_check)
2890 var parent_def = Parent.PartialContainer;
2891 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
2892 has_unmanaged_check_done = true;
2896 if (first_nonstatic_field != null) {
2897 requires_delayed_unmanagedtype_check = true;
2899 foreach (var member in Members) {
2900 var f = member as Field;
2907 // It can happen when recursive unmanaged types are defined
2908 // struct S { S* s; }
2909 TypeSpec mt = f.MemberType;
2917 has_unmanaged_check_done = true;
2921 has_unmanaged_check_done = true;
2924 is_unmanaged = true;
2928 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2930 var ifaces = base.ResolveBaseTypes (out base_class);
2931 base_type = Compiler.BuiltinTypes.ValueType;
2935 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
2937 if ((field.ModFlags & Modifiers.STATIC) == 0) {
2938 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
2939 field.GetSignatureForError ());
2942 base.RegisterFieldForInitialization (field, expression);
2950 public sealed class Interface : TypeDefinition {
2953 /// Modifiers allowed in a class declaration
2955 const Modifiers AllowedModifiers =
2958 Modifiers.PROTECTED |
2959 Modifiers.INTERNAL |
2963 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2964 : base (parent, name, attrs, MemberKind.Interface)
2966 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2968 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
2969 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2974 public override AttributeTargets AttributeTargets {
2976 return AttributeTargets.Interface;
2980 protected override TypeAttributes TypeAttr {
2982 const TypeAttributes DefaultTypeAttributes =
2983 TypeAttributes.AutoLayout |
2984 TypeAttributes.Abstract |
2985 TypeAttributes.Interface;
2987 return base.TypeAttr | DefaultTypeAttributes;
2993 public override void Accept (StructuralVisitor visitor)
2995 visitor.Visit (this);
2998 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3000 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3001 a.Error_MissingGuidAttribute ();
3005 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3008 protected override bool VerifyClsCompliance ()
3010 if (!base.VerifyClsCompliance ())
3013 if (iface_exprs != null) {
3014 foreach (var iface in iface_exprs) {
3015 if (iface.IsCLSCompliant ())
3018 Report.SymbolRelatedToPreviousError (iface);
3019 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3020 GetSignatureForError (), iface.GetSignatureForError ());
3028 public abstract class InterfaceMemberBase : MemberBase
3031 // Common modifiers allowed in a class declaration
3033 protected const Modifiers AllowedModifiersClass =
3036 Modifiers.PROTECTED |
3037 Modifiers.INTERNAL |
3042 Modifiers.OVERRIDE |
3043 Modifiers.ABSTRACT |
3048 // Common modifiers allowed in a struct declaration
3050 protected const Modifiers AllowedModifiersStruct =
3053 Modifiers.PROTECTED |
3054 Modifiers.INTERNAL |
3057 Modifiers.OVERRIDE |
3062 // Common modifiers allowed in a interface declaration
3064 protected const Modifiers AllowedModifiersInterface =
3069 // Whether this is an interface member.
3071 public bool IsInterface;
3074 // If true, this is an explicit interface implementation
3076 public readonly bool IsExplicitImpl;
3078 protected bool is_external_implementation;
3081 // The interface type we are explicitly implementing
3083 public TypeSpec InterfaceType;
3086 // The method we're overriding if this is an override method.
3088 protected MethodSpec base_method;
3090 readonly Modifiers explicit_mod_flags;
3091 public MethodAttributes flags;
3093 public InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3094 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3096 IsInterface = parent.Kind == MemberKind.Interface;
3097 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3098 explicit_mod_flags = mod;
3101 public abstract Variance ExpectedMemberTypeVariance { get; }
3103 protected override bool CheckBase ()
3105 if (!base.CheckBase ())
3108 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3109 CheckForDuplications ();
3114 // For System.Object only
3115 if (Parent.BaseType == null)
3118 MemberSpec candidate;
3119 bool overrides = false;
3120 var base_member = FindBaseMember (out candidate, ref overrides);
3122 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3123 if (base_member == null) {
3124 if (candidate == null) {
3125 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3126 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3127 "object.Finalize()");
3129 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3130 GetSignatureForError (), SimpleName.GetMemberType (this));
3133 Report.SymbolRelatedToPreviousError (candidate);
3135 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3136 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3137 else if (this is PropertyBase)
3138 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3139 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3141 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3142 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3149 // Handles ambiguous overrides
3151 if (candidate != null) {
3152 Report.SymbolRelatedToPreviousError (candidate);
3153 Report.SymbolRelatedToPreviousError (base_member);
3155 // Get member definition for error reporting
3156 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3157 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3159 Report.Error (462, Location,
3160 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3161 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3164 if (!CheckOverrideAgainstBase (base_member))
3167 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3169 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3170 Report.SymbolRelatedToPreviousError (base_member);
3171 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3172 GetSignatureForError (), base_member.GetSignatureForError ());
3175 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3176 Report.SymbolRelatedToPreviousError (base_member);
3177 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3178 GetSignatureForError (), base_member.GetSignatureForError ());
3182 base_method = base_member as MethodSpec;
3186 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3187 base_member = candidate;
3189 if (base_member == null) {
3190 if ((ModFlags & Modifiers.NEW) != 0) {
3191 if (base_member == null) {
3192 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3193 GetSignatureForError ());
3197 if ((ModFlags & Modifiers.NEW) == 0) {
3198 ModFlags |= Modifiers.NEW;
3199 if (!IsCompilerGenerated) {
3200 Report.SymbolRelatedToPreviousError (base_member);
3201 if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3202 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",
3203 GetSignatureForError (), base_member.GetSignatureForError ());
3205 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3206 GetSignatureForError (), base_member.GetSignatureForError ());
3211 if (!IsInterface && base_member.IsAbstract && !overrides) {
3212 Report.SymbolRelatedToPreviousError (base_member);
3213 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3214 GetSignatureForError (), base_member.GetSignatureForError ());
3221 protected virtual bool CheckForDuplications ()
3223 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3227 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3228 // that have been defined.
3230 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3234 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3235 Report.SymbolRelatedToPreviousError (base_member);
3236 Report.Error (506, Location,
3237 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3238 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3242 // Now we check that the overriden method is not final
3243 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3244 Report.SymbolRelatedToPreviousError (base_member);
3245 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3246 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3250 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3251 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3252 Report.SymbolRelatedToPreviousError (base_member);
3253 if (this is PropertyBasedMember) {
3254 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3255 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3257 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3258 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3266 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3268 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3269 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3271 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3273 // It must be at least "protected"
3275 if ((thisp & Modifiers.PROTECTED) == 0) {
3280 // when overriding protected internal, the method can be declared
3281 // protected internal only within the same assembly or assembly
3282 // which has InternalsVisibleTo
3284 if ((thisp & Modifiers.INTERNAL) != 0) {
3285 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3289 // protected overriding protected internal inside same assembly
3290 // requires internal modifier as well
3292 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3299 return thisp == base_classp;
3302 public override bool Define ()
3305 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3306 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3308 flags = MethodAttributes.Public |
3309 MethodAttributes.Abstract |
3310 MethodAttributes.HideBySig |
3311 MethodAttributes.NewSlot |
3312 MethodAttributes.Virtual;
3314 Parent.PartialContainer.MethodModifiersValid (this);
3316 flags = ModifiersExtensions.MethodAttr (ModFlags);
3319 if (IsExplicitImpl) {
3320 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3321 if (InterfaceType == null)
3324 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3325 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3326 GetSignatureForError ());
3329 if (!InterfaceType.IsInterface) {
3330 Report.SymbolRelatedToPreviousError (InterfaceType);
3331 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3332 InterfaceType.GetSignatureForError ());
3334 Parent.PartialContainer.VerifyImplements (this);
3337 ModifiersExtensions.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location, Report);
3340 return base.Define ();
3343 protected bool DefineParameters (ParametersCompiled parameters)
3345 if (!parameters.Resolve (this))
3349 for (int i = 0; i < parameters.Count; ++i) {
3350 Parameter p = parameters [i];
3352 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3353 p.Warning_UselessOptionalParameter (Report);
3355 if (p.CheckAccessibility (this))
3358 TypeSpec t = parameters.Types [i];
3359 Report.SymbolRelatedToPreviousError (t);
3360 if (this is Indexer)
3361 Report.Error (55, Location,
3362 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3363 t.GetSignatureForError (), GetSignatureForError ());
3364 else if (this is Operator)
3365 Report.Error (57, Location,
3366 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3367 t.GetSignatureForError (), GetSignatureForError ());
3369 Report.Error (51, Location,
3370 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3371 t.GetSignatureForError (), GetSignatureForError ());
3377 protected override void DoMemberTypeDependentChecks ()
3379 base.DoMemberTypeDependentChecks ();
3381 TypeManager.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3384 public override void Emit()
3386 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3387 // We are more strict than csc and report this as an error because SRE does not allow emit that
3388 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3389 if (this is Constructor) {
3390 Report.Warning (824, 1, Location,
3391 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3393 Report.Warning (626, 1, Location,
3394 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3395 GetSignatureForError ());
3402 public override bool EnableOverloadChecks (MemberCore overload)
3405 // Two members can differ in their explicit interface
3406 // type parameter only
3408 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3409 if (imb != null && imb.IsExplicitImpl) {
3410 if (IsExplicitImpl) {
3411 caching_flags |= Flags.MethodOverloadsExist;
3416 return IsExplicitImpl;
3419 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3421 var base_modifiers = base_member.Modifiers;
3423 // Remove internal modifier from types which are not internally accessible
3424 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3425 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3426 base_modifiers = Modifiers.PROTECTED;
3428 Report.SymbolRelatedToPreviousError (base_member);
3429 Report.Error (507, member.Location,
3430 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3431 member.GetSignatureForError (),
3432 ModifiersExtensions.AccessibilityName (base_modifiers),
3433 base_member.GetSignatureForError ());
3436 protected void Error_StaticReturnType ()
3438 Report.Error (722, Location,
3439 "`{0}': static types cannot be used as return types",
3440 MemberType.GetSignatureForError ());
3444 /// Gets base method and its return type
3446 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3448 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3452 // The "short" name of this property / indexer / event. This is the
3453 // name without the explicit interface.
3455 public string ShortName {
3456 get { return MemberName.Name; }
3460 // Returns full metadata method name
3462 public string GetFullName (MemberName name)
3464 return GetFullName (name.Name);
3467 public string GetFullName (string name)
3469 if (!IsExplicitImpl)
3473 // When dealing with explicit members a full interface type
3474 // name is added to member name to avoid possible name conflicts
3476 // We use CSharpName which gets us full name with benefit of
3477 // replacing predefined names which saves some space and name
3480 return InterfaceType.GetSignatureForError () + "." + name;
3483 public override string GetSignatureForDocumentation ()
3486 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetExplicitNameSignatureForDocumentation () + "#" + ShortName;
3488 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3491 public override bool IsUsed
3493 get { return IsExplicitImpl || base.IsUsed; }
3496 public override void SetConstraints (List<Constraints> constraints_list)
3498 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3499 Report.Error (460, Location,
3500 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3501 GetSignatureForError ());
3504 base.SetConstraints (constraints_list);
3508 public abstract class MemberBase : MemberCore
3510 protected FullNamedExpression type_expr;
3511 protected TypeSpec member_type;
3512 public new TypeDefinition Parent;
3514 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3515 : base (parent, name, attrs)
3517 this.Parent = parent;
3518 this.type_expr = type;
3520 if (name != MemberName.Null)
3521 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3526 public TypeSpec MemberType {
3532 public FullNamedExpression TypeExpression {
3541 // Main member define entry
3543 public override bool Define ()
3545 DoMemberTypeIndependentChecks ();
3548 // Returns false only when type resolution failed
3550 if (!ResolveMemberType ())
3553 DoMemberTypeDependentChecks ();
3558 // Any type_name independent checks
3560 protected virtual void DoMemberTypeIndependentChecks ()
3562 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3563 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3564 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3565 GetSignatureForError (), Parent.GetSignatureForError ());
3570 // Any type_name dependent checks
3572 protected virtual void DoMemberTypeDependentChecks ()
3574 // verify accessibility
3575 if (!IsAccessibleAs (MemberType)) {
3576 Report.SymbolRelatedToPreviousError (MemberType);
3577 if (this is Property)
3578 Report.Error (53, Location,
3579 "Inconsistent accessibility: property type `" +
3580 MemberType.GetSignatureForError () + "' is less " +
3581 "accessible than property `" + GetSignatureForError () + "'");
3582 else if (this is Indexer)
3583 Report.Error (54, Location,
3584 "Inconsistent accessibility: indexer return type `" +
3585 MemberType.GetSignatureForError () + "' is less " +
3586 "accessible than indexer `" + GetSignatureForError () + "'");
3587 else if (this is MethodCore) {
3588 if (this is Operator)
3589 Report.Error (56, Location,
3590 "Inconsistent accessibility: return type `" +
3591 MemberType.GetSignatureForError () + "' is less " +
3592 "accessible than operator `" + GetSignatureForError () + "'");
3594 Report.Error (50, Location,
3595 "Inconsistent accessibility: return type `" +
3596 MemberType.GetSignatureForError () + "' is less " +
3597 "accessible than method `" + GetSignatureForError () + "'");
3599 Report.Error (52, Location,
3600 "Inconsistent accessibility: field type `" +
3601 MemberType.GetSignatureForError () + "' is less " +
3602 "accessible than field `" + GetSignatureForError () + "'");
3607 protected void IsTypePermitted ()
3609 if (MemberType.IsSpecialRuntimeType) {
3610 if (Parent is StateMachine) {
3611 Report.Error (4012, Location,
3612 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3613 MemberType.GetSignatureForError ());
3614 } else if (Parent is HoistedStoreyClass) {
3615 Report.Error (4013, Location,
3616 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3617 MemberType.GetSignatureForError ());
3619 Report.Error (610, Location,
3620 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3625 protected virtual bool CheckBase ()
3627 CheckProtectedModifier ();
3632 public override string GetSignatureForDocumentation ()
3634 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3637 protected virtual bool ResolveMemberType ()
3639 if (member_type != null)
3640 throw new InternalErrorException ("Multi-resolve");
3642 member_type = type_expr.ResolveAsType (this);
3643 return member_type != null;