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;
22 using System.Diagnostics;
23 using Mono.CompilerServices.SymbolWriter;
26 using XmlElement = System.Object;
30 using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
31 using IKVM.Reflection;
32 using IKVM.Reflection.Emit;
34 using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
35 using System.Reflection;
36 using System.Reflection.Emit;
42 // General types container, used as a base class for all constructs which can hold types
44 public abstract class TypeContainer : MemberCore
46 public readonly MemberKind Kind;
47 public readonly string Basename;
49 protected List<TypeContainer> containers;
51 TypeDefinition main_container;
53 protected Dictionary<string, MemberCore> defined_names;
55 protected bool is_defined;
57 public TypeContainer (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
58 : base (parent, name, attrs)
62 this.Basename = name.Basename;
64 defined_names = new Dictionary<string, MemberCore> ();
67 public override TypeSpec CurrentType {
73 public Dictionary<string, MemberCore> DefinedNames {
79 public TypeDefinition PartialContainer {
81 return main_container;
84 main_container = value;
88 public IList<TypeContainer> Containers {
95 // Any unattached attributes during parsing get added here. User
98 public Attributes UnattachedAttributes {
102 public virtual void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
107 public virtual void AddPartial (TypeDefinition next_part)
110 (PartialContainer ?? this).defined_names.TryGetValue (next_part.Basename, out mc);
112 AddPartial (next_part, mc as TypeDefinition);
115 protected void AddPartial (TypeDefinition next_part, TypeDefinition existing)
117 next_part.ModFlags |= Modifiers.PARTIAL;
119 if (existing == null) {
120 AddTypeContainer (next_part);
124 if ((existing.ModFlags & Modifiers.PARTIAL) == 0) {
125 if (existing.Kind != next_part.Kind) {
126 AddTypeContainer (next_part);
128 Report.SymbolRelatedToPreviousError (next_part);
129 Error_MissingPartialModifier (existing);
135 if (existing.Kind != next_part.Kind) {
136 Report.SymbolRelatedToPreviousError (existing);
137 Report.Error (261, next_part.Location,
138 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
139 next_part.GetSignatureForError ());
142 if ((existing.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) &&
143 ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 &&
144 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
145 Report.SymbolRelatedToPreviousError (existing);
146 Report.Error (262, next_part.Location,
147 "Partial declarations of `{0}' have conflicting accessibility modifiers",
148 next_part.GetSignatureForError ());
151 var tc_names = existing.CurrentTypeParameters;
152 if (tc_names != null) {
153 for (int i = 0; i < tc_names.Count; ++i) {
154 var tp = next_part.MemberName.TypeParameters[i];
155 if (tc_names[i].MemberName.Name != tp.MemberName.Name) {
156 Report.SymbolRelatedToPreviousError (existing.Location, "");
157 Report.Error (264, next_part.Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
158 next_part.GetSignatureForError ());
162 if (tc_names[i].Variance != tp.Variance) {
163 Report.SymbolRelatedToPreviousError (existing.Location, "");
164 Report.Error (1067, next_part.Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers",
165 next_part.GetSignatureForError ());
171 if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
172 existing.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
173 } else if ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
174 existing.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
175 existing.ModFlags |= next_part.ModFlags;
177 existing.ModFlags |= next_part.ModFlags;
180 existing.Definition.Modifiers = existing.ModFlags;
182 if (next_part.attributes != null) {
183 if (existing.attributes == null)
184 existing.attributes = next_part.attributes;
186 existing.attributes.AddAttributes (next_part.attributes.Attrs);
189 next_part.PartialContainer = existing;
191 if (containers == null)
192 containers = new List<TypeContainer> ();
194 containers.Add (next_part);
197 public virtual void AddTypeContainer (TypeContainer tc)
201 var tparams = tc.MemberName.TypeParameters;
202 if (tparams != null && tc.PartialContainer != null) {
203 var td = (TypeDefinition) tc;
204 for (int i = 0; i < tparams.Count; ++i) {
206 if (tp.MemberName == null)
209 td.AddNameToContainer (tp, tp.Name);
214 public virtual void CloseContainer ()
216 if (containers != null) {
217 foreach (TypeContainer tc in containers) {
218 tc.CloseContainer ();
223 public virtual void CreateMetadataName (StringBuilder sb)
225 if (Parent != null && Parent.MemberName != null)
226 Parent.CreateMetadataName (sb);
228 MemberName.CreateMetadataName (sb);
231 public virtual bool CreateContainer ()
233 if (containers != null) {
234 foreach (TypeContainer tc in containers) {
235 tc.CreateContainer ();
242 public override bool Define ()
244 if (containers != null) {
245 foreach (TypeContainer tc in containers) {
250 // Release cache used by parser only
251 if (Module.Evaluator == null) {
252 defined_names = null;
254 defined_names.Clear ();
260 public virtual void PrepareEmit ()
262 if (containers != null) {
263 foreach (var t in containers) {
266 } catch (Exception e) {
267 if (MemberName == MemberName.Null)
270 throw new InternalErrorException (t, e);
276 public virtual bool DefineContainer ()
283 DoDefineContainer ();
285 if (containers != null) {
286 foreach (TypeContainer tc in containers) {
288 tc.DefineContainer ();
289 } catch (Exception e) {
290 if (MemberName == MemberName.Null)
293 throw new InternalErrorException (tc, e);
301 protected virtual void DefineNamespace ()
303 if (containers != null) {
304 foreach (var tc in containers) {
306 tc.DefineNamespace ();
307 } catch (Exception e) {
308 throw new InternalErrorException (tc, e);
314 protected virtual void DoDefineContainer ()
318 public virtual void EmitContainer ()
320 if (containers != null) {
321 for (int i = 0; i < containers.Count; ++i)
322 containers[i].EmitContainer ();
326 protected void Error_MissingPartialModifier (MemberCore type)
328 Report.Error (260, type.Location,
329 "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
330 type.GetSignatureForError ());
333 public override string GetSignatureForDocumentation ()
335 if (Parent != null && Parent.MemberName != null)
336 return Parent.GetSignatureForDocumentation () + "." + MemberName.GetSignatureForDocumentation ();
338 return MemberName.GetSignatureForDocumentation ();
341 public override string GetSignatureForError ()
343 if (Parent != null && Parent.MemberName != null)
344 return Parent.GetSignatureForError () + "." + MemberName.GetSignatureForError ();
346 return MemberName.GetSignatureForError ();
349 public string GetSignatureForMetadata ()
352 if (Parent is TypeDefinition) {
353 return Parent.GetSignatureForMetadata () + "+" + TypeNameParser.Escape (MemberName.Basename);
356 var sb = new StringBuilder ();
357 CreateMetadataName (sb);
358 return sb.ToString ();
360 throw new NotImplementedException ();
364 public virtual void RemoveContainer (TypeContainer cont)
366 if (containers != null)
367 containers.Remove (cont);
369 var tc = Parent == Module ? Module : this;
370 tc.defined_names.Remove (cont.Basename);
373 public virtual void VerifyMembers ()
375 if (containers != null) {
376 foreach (TypeContainer tc in containers)
381 public override void WriteDebugSymbol (MonoSymbolFile file)
383 if (containers != null) {
384 foreach (TypeContainer tc in containers) {
385 tc.WriteDebugSymbol (file);
391 public abstract class TypeDefinition : TypeContainer, ITypeDefinition
394 // Different context is needed when resolving type container base
395 // types. Type names come from the parent scope but type parameter
396 // names from the container scope.
398 public struct BaseContext : IMemberContext
402 public BaseContext (TypeContainer tc)
407 #region IMemberContext Members
409 public CompilerContext Compiler {
410 get { return tc.Compiler; }
413 public TypeSpec CurrentType {
414 get { return tc.Parent.CurrentType; }
417 public TypeParameters CurrentTypeParameters {
418 get { return tc.PartialContainer.CurrentTypeParameters; }
421 public MemberCore CurrentMemberDefinition {
425 public bool IsObsolete {
426 get { return tc.IsObsolete; }
429 public bool IsUnsafe {
430 get { return tc.IsUnsafe; }
433 public bool IsStatic {
434 get { return tc.IsStatic; }
437 public ModuleContainer Module {
438 get { return tc.Module; }
441 public string GetSignatureForError ()
443 return tc.GetSignatureForError ();
446 public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
451 public FullNamedExpression LookupNamespaceAlias (string name)
453 return tc.Parent.LookupNamespaceAlias (name);
456 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
459 var tp = CurrentTypeParameters;
461 TypeParameter t = tp.Find (name);
463 return new TypeParameterExpr (t, loc);
467 return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc);
477 GetHashCode = 1 << 1,
478 HasStaticFieldInitializer = 1 << 2
481 readonly List<MemberCore> members;
483 // Holds a list of fields that have initializers
484 protected List<FieldInitializer> initialized_fields;
486 // Holds a list of static fields that have initializers
487 protected List<FieldInitializer> initialized_static_fields;
489 Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
491 Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
494 // Points to the first non-static field added to the container.
496 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
497 // and the first one's as good as any.
499 protected FieldBase first_nonstatic_field;
502 // This one is computed after we can distinguish interfaces
503 // from classes from the arraylist `type_bases'
505 protected TypeSpec base_type;
506 FullNamedExpression base_type_expr; // TODO: It's temporary variable
507 protected TypeSpec[] iface_exprs;
509 protected List<FullNamedExpression> type_bases;
511 TypeDefinition InTransit;
513 public TypeBuilder TypeBuilder;
514 GenericTypeParameterBuilder[] all_tp_builders;
516 // All recursive type parameters put together sharing same
517 // TypeParameter instances
519 TypeParameters all_type_parameters;
521 public const string DefaultIndexerName = "Item";
523 bool has_normal_indexers;
525 protected bool requires_delayed_unmanagedtype_check;
527 bool members_defined;
528 bool members_defined_ok;
529 protected bool has_static_constructor;
531 private CachedMethods cached_method;
533 protected TypeSpec spec;
534 TypeSpec current_type;
536 public int DynamicSitesCounter;
537 public int AnonymousMethodsCounter;
539 static readonly string[] attribute_targets = new string[] { "type" };
542 /// The pending methods that need to be implemented
543 // (interfaces or abstract methods)
545 PendingImplementation pending;
547 public TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
548 : base (parent, name, attrs, kind)
550 PartialContainer = this;
551 members = new List<MemberCore> ();
556 public List<FullNamedExpression> BaseTypeExpressions {
562 public override TypeSpec CurrentType {
564 if (current_type == null) {
565 if (IsGenericOrParentIsGeneric) {
567 // Switch to inflated version as it's used by all expressions
569 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Types;
570 current_type = spec.MakeGenericType (this, targs);
580 public override TypeParameters CurrentTypeParameters {
582 return PartialContainer.MemberName.TypeParameters;
586 int CurrentTypeParametersStartIndex {
588 int total = all_tp_builders.Length;
589 if (CurrentTypeParameters != null) {
590 return total - CurrentTypeParameters.Count;
596 public virtual AssemblyDefinition DeclaringAssembly {
598 return Module.DeclaringAssembly;
602 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
604 return Module.DeclaringAssembly;
608 public TypeSpec Definition {
614 public bool HasMembersDefined {
616 return members_defined;
620 public bool HasInstanceConstructor {
622 return (caching_flags & Flags.HasInstanceConstructor) != 0;
625 caching_flags |= Flags.HasInstanceConstructor;
629 // Indicated whether container has StructLayout attribute set Explicit
630 public bool HasExplicitLayout {
631 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
632 set { caching_flags |= Flags.HasExplicitLayout; }
635 public bool HasOperators {
637 return (caching_flags & Flags.HasUserOperators) != 0;
640 caching_flags |= Flags.HasUserOperators;
644 public bool HasStructLayout {
645 get { return (caching_flags & Flags.HasStructLayout) != 0; }
646 set { caching_flags |= Flags.HasStructLayout; }
649 public TypeSpec[] Interfaces {
655 public bool IsGenericOrParentIsGeneric {
657 return all_type_parameters != null;
661 public bool IsTopLevel {
663 return !(Parent is TypeDefinition);
667 public bool IsPartial {
669 return (ModFlags & Modifiers.PARTIAL) != 0;
674 // Returns true for secondary partial containers
678 return PartialContainer != this;
682 public MemberCache MemberCache {
684 return spec.MemberCache;
688 public List<MemberCore> Members {
694 string ITypeDefinition.Namespace {
697 while (p.Kind != MemberKind.Namespace)
700 return p.MemberName == null ? null : p.GetSignatureForError ();
704 public TypeParameters TypeParametersAll {
706 return all_type_parameters;
710 public override string[] ValidAttributeTargets {
712 return attribute_targets;
718 public override void Accept (StructuralVisitor visitor)
720 visitor.Visit (this);
723 public void AddMember (MemberCore symbol)
725 if (symbol.MemberName.ExplicitInterface != null) {
726 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
727 Report.Error (541, symbol.Location,
728 "`{0}': explicit interface declaration can only be declared in a class or struct",
729 symbol.GetSignatureForError ());
733 AddNameToContainer (symbol, symbol.MemberName.Basename);
734 members.Add (symbol);
737 public override void AddTypeContainer (TypeContainer tc)
739 AddNameToContainer (tc, tc.Basename);
741 if (containers == null)
742 containers = new List<TypeContainer> ();
745 base.AddTypeContainer (tc);
748 public override void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
752 if (containers == null)
753 containers = new List<TypeContainer> ();
755 base.AddCompilerGeneratedClass (c);
759 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
761 public virtual void AddNameToContainer (MemberCore symbol, string name)
763 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
767 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
768 PartialContainer.defined_names.Add (name, symbol);
772 if (symbol.EnableOverloadChecks (mc))
775 InterfaceMemberBase im = mc as InterfaceMemberBase;
776 if (im != null && im.IsExplicitImpl)
779 Report.SymbolRelatedToPreviousError (mc);
780 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
781 Error_MissingPartialModifier (symbol);
785 if (symbol is TypeParameter) {
786 Report.Error (692, symbol.Location,
787 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
789 Report.Error (102, symbol.Location,
790 "The type `{0}' already contains a definition for `{1}'",
791 GetSignatureForError (), name);
797 public void AddConstructor (Constructor c)
799 AddConstructor (c, false);
802 public void AddConstructor (Constructor c, bool isDefault)
804 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
806 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
808 if (is_static && c.ParameterInfo.IsEmpty) {
809 PartialContainer.has_static_constructor = true;
811 PartialContainer.HasInstanceConstructor = true;
817 public bool AddField (FieldBase field)
821 if ((field.ModFlags & Modifiers.STATIC) != 0)
824 var first_field = PartialContainer.first_nonstatic_field;
825 if (first_field == null) {
826 PartialContainer.first_nonstatic_field = field;
830 if (Kind == MemberKind.Struct && first_field.Parent != field.Parent) {
831 Report.SymbolRelatedToPreviousError (first_field.Parent);
832 Report.Warning (282, 3, field.Location,
833 "struct instance field `{0}' found in different declaration from instance field `{1}'",
834 field.GetSignatureForError (), first_field.GetSignatureForError ());
840 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
842 public void AddIndexer (Indexer i)
847 public void AddOperator (Operator op)
849 PartialContainer.HasOperators = true;
853 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
855 if (has_normal_indexers && a.Type == pa.DefaultMember) {
856 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
860 if (a.Type == pa.Required) {
861 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
865 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
868 public override AttributeTargets AttributeTargets {
870 throw new NotSupportedException ();
874 public TypeSpec BaseType {
876 return spec.BaseType;
880 protected virtual TypeAttributes TypeAttr {
882 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
886 public int TypeParametersCount {
888 return MemberName.Arity;
892 TypeParameterSpec[] ITypeDefinition.TypeParameters {
894 return PartialContainer.CurrentTypeParameters.Types;
898 public string GetAttributeDefaultMember ()
900 return indexer_name ?? DefaultIndexerName;
903 public bool IsComImport {
905 if (OptAttributes == null)
908 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
912 public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
915 PartialContainer.RegisterFieldForInitialization (field, expression);
917 if ((field.ModFlags & Modifiers.STATIC) != 0){
918 if (initialized_static_fields == null) {
919 HasStaticFieldInitializer = true;
920 initialized_static_fields = new List<FieldInitializer> (4);
923 initialized_static_fields.Add (expression);
925 if (initialized_fields == null)
926 initialized_fields = new List<FieldInitializer> (4);
928 initialized_fields.Add (expression);
932 public void ResolveFieldInitializers (BlockContext ec)
934 Debug.Assert (!IsPartialPart);
937 if (initialized_static_fields == null)
940 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
942 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
943 for (i = 0; i < initialized_static_fields.Count; ++i) {
944 FieldInitializer fi = initialized_static_fields [i];
945 ExpressionStatement s = fi.ResolveStatement (ec);
947 s = EmptyExpressionStatement.Instance;
948 } else if (!fi.IsSideEffectFree) {
949 has_complex_initializer |= true;
955 for (i = 0; i < initialized_static_fields.Count; ++i) {
956 FieldInitializer fi = initialized_static_fields [i];
958 // Need special check to not optimize code like this
959 // static int a = b = 5;
962 if (!has_complex_initializer && fi.IsDefaultInitializer)
965 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
971 if (initialized_fields == null)
974 for (int i = 0; i < initialized_fields.Count; ++i) {
975 FieldInitializer fi = initialized_fields [i];
976 ExpressionStatement s = fi.ResolveStatement (ec);
981 // Field is re-initialized to its default value => removed
983 if (fi.IsDefaultInitializer && ec.Module.Compiler.Settings.Optimize)
986 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
990 public override string DocComment {
1002 public PendingImplementation PendingImplementations {
1003 get { return pending; }
1006 internal override void GenerateDocComment (DocumentationBuilder builder)
1011 base.GenerateDocComment (builder);
1013 foreach (var member in members)
1014 member.GenerateDocComment (builder);
1017 public TypeSpec GetAttributeCoClass ()
1019 if (OptAttributes == null)
1022 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
1026 return a.GetCoClassAttributeValue ();
1029 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1032 if (OptAttributes != null) {
1033 a = OptAttributes.Search (pa);
1039 return a.GetAttributeUsageAttribute ();
1042 public virtual CompilationSourceFile GetCompilationSourceFile ()
1044 TypeContainer ns = Parent;
1046 var sf = ns as CompilationSourceFile;
1054 public virtual void AddBasesForPart (List<FullNamedExpression> bases)
1060 /// This function computes the Base class and also the
1061 /// list of interfaces that the class or struct @c implements.
1063 /// The return value is an array (might be null) of
1064 /// interfaces implemented (as Types).
1066 /// The @base_class argument is set to the base object or null
1067 /// if this is `System.Object'.
1069 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1072 if (type_bases == null)
1075 int count = type_bases.Count;
1076 TypeSpec[] ifaces = null;
1077 var base_context = new BaseContext (this);
1078 for (int i = 0, j = 0; i < count; i++){
1079 FullNamedExpression fne = type_bases [i];
1081 var fne_resolved = fne.ResolveAsType (base_context);
1082 if (fne_resolved == null)
1085 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1086 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1087 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1088 GetSignatureForError ());
1093 base_type = fne_resolved;
1099 ifaces = new TypeSpec [count - i];
1101 if (fne_resolved.IsInterface) {
1102 for (int ii = 0; ii < j; ++ii) {
1103 if (fne_resolved == ifaces [ii]) {
1104 Report.Error (528, Location, "`{0}' is already listed in interface list",
1105 fne_resolved.GetSignatureForError ());
1110 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1111 Report.Error (61, fne.Location,
1112 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1113 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1116 Report.SymbolRelatedToPreviousError (fne_resolved);
1117 if (Kind != MemberKind.Class) {
1118 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1119 } else if (base_class != null)
1120 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1121 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1123 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1124 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1128 ifaces [j++] = fne_resolved;
1135 // Checks that some operators come in pairs:
1141 // They are matched based on the return type and the argument types
1143 void CheckPairedOperators ()
1145 bool has_equality_or_inequality = false;
1146 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1148 for (int i = 0; i < members.Count; ++i) {
1149 var o_a = members[i] as Operator;
1153 var o_type = o_a.OperatorType;
1154 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1155 has_equality_or_inequality = true;
1157 if (found_matched.Contains (o_type))
1160 var matching_type = o_a.GetMatchingOperator ();
1161 if (matching_type == Operator.OpType.TOP) {
1165 bool pair_found = false;
1166 for (int ii = i + 1; ii < members.Count; ++ii) {
1167 var o_b = members[ii] as Operator;
1168 if (o_b == null || o_b.OperatorType != matching_type)
1171 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1174 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1177 found_matched.Add (matching_type);
1183 Report.Error (216, o_a.Location,
1184 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1185 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1189 if (has_equality_or_inequality) {
1191 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1192 GetSignatureForError ());
1194 if (!HasGetHashCode)
1195 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1196 GetSignatureForError ());
1200 public override void CreateMetadataName (StringBuilder sb)
1202 if (Parent.MemberName != null) {
1203 Parent.CreateMetadataName (sb);
1205 if (sb.Length != 0) {
1210 sb.Append (MemberName.Basename);
1213 bool CreateTypeBuilder ()
1216 // Sets .size to 1 for structs with no instance fields
1218 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null && !(this is StateMachine) ? 1 : 0;
1220 var parent_def = Parent as TypeDefinition;
1221 if (parent_def == null) {
1222 var sb = new StringBuilder ();
1223 CreateMetadataName (sb);
1224 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1226 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (Basename, TypeAttr, null, type_size);
1229 if (DeclaringAssembly.Importer != null)
1230 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1232 spec.SetMetaInfo (TypeBuilder);
1233 spec.MemberCache = new MemberCache (this);
1235 TypeParameters parentAllTypeParameters = null;
1236 if (parent_def != null) {
1237 spec.DeclaringType = Parent.CurrentType;
1238 parent_def.MemberCache.AddMember (spec);
1239 parentAllTypeParameters = parent_def.all_type_parameters;
1242 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1243 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1245 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1247 if (CurrentTypeParameters != null)
1248 CurrentTypeParameters.Define (all_tp_builders, spec, CurrentTypeParametersStartIndex, this);
1254 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1257 int parent_offset = 0;
1258 if (parentAllTypeParameters != null) {
1259 if (CurrentTypeParameters == null) {
1260 all_type_parameters = parentAllTypeParameters;
1261 return parentAllTypeParameters.GetAllNames ();
1264 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1265 all_type_parameters = new TypeParameters (names.Length);
1266 all_type_parameters.Add (parentAllTypeParameters);
1268 parent_offset = all_type_parameters.Count;
1269 for (int i = 0; i < parent_offset; ++i)
1270 names[i] = all_type_parameters[i].MemberName.Name;
1273 names = new string[CurrentTypeParameters.Count];
1276 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1277 if (all_type_parameters != null)
1278 all_type_parameters.Add (MemberName.TypeParameters[i]);
1280 var name = CurrentTypeParameters[i].MemberName.Name;
1281 names[parent_offset + i] = name;
1282 for (int ii = 0; ii < parent_offset + i; ++ii) {
1283 if (names[ii] != name)
1286 var tp = CurrentTypeParameters[i];
1287 var conflict = all_type_parameters[ii];
1289 tp.WarningParentNameConflict (conflict);
1293 if (all_type_parameters == null)
1294 all_type_parameters = CurrentTypeParameters;
1300 public SourceMethodBuilder CreateMethodSymbolEntry ()
1302 if (Module.DeclaringAssembly.SymbolWriter == null)
1305 var source_file = GetCompilationSourceFile ();
1306 if (source_file == null)
1309 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1313 // Creates a proxy base method call inside this container for hoisted base member calls
1315 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1317 Method proxy_method;
1320 // One proxy per base method is enough
1322 if (hoisted_base_call_proxies == null) {
1323 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1324 proxy_method = null;
1326 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1329 if (proxy_method == null) {
1330 string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1331 var base_parameters = new Parameter[method.Parameters.Count];
1332 for (int i = 0; i < base_parameters.Length; ++i) {
1333 var base_param = method.Parameters.FixedParameters[i];
1334 base_parameters[i] = new Parameter (new TypeExpression (method.Parameters.Types[i], Location),
1335 base_param.Name, base_param.ModFlags, null, Location);
1336 base_parameters[i].Resolve (this, i);
1339 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
1340 if (method.Parameters.HasArglist) {
1341 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1342 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1345 MemberName member_name;
1346 TypeArguments targs = null;
1347 if (method.IsGeneric) {
1349 // Copy all base generic method type parameters info
1351 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1352 var tparams = new TypeParameters ();
1354 targs = new TypeArguments ();
1355 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1356 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1357 var tp = hoisted_tparams[i];
1358 tparams.Add (new TypeParameter (tp, null, new MemberName (tp.Name, Location), null));
1360 targs.Add (new SimpleName (tp.Name, Location));
1361 targs.Arguments[i] = tp;
1364 member_name = new MemberName (name, tparams, Location);
1366 member_name = new MemberName (name);
1369 // Compiler generated proxy
1370 proxy_method = new Method (this, new TypeExpression (method.ReturnType, Location),
1371 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1372 member_name, cloned_params, null);
1374 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1375 IsCompilerGenerated = true
1378 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1379 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1381 mg.SetTypeArguments (rc, targs);
1383 // Get all the method parameters and pass them as arguments
1384 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1385 Statement statement;
1386 if (method.ReturnType.Kind == MemberKind.Void)
1387 statement = new StatementExpression (real_base_call);
1389 statement = new Return (real_base_call, Location);
1391 block.AddStatement (statement);
1392 proxy_method.Block = block;
1394 members.Add (proxy_method);
1395 proxy_method.Define ();
1397 hoisted_base_call_proxies.Add (method, proxy_method);
1400 return proxy_method.Spec;
1403 protected bool DefineBaseTypes ()
1405 iface_exprs = ResolveBaseTypes (out base_type_expr);
1408 if (IsPartialPart) {
1409 set_base_type = false;
1411 if (base_type_expr != null) {
1412 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1413 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1414 Report.Error (263, Location,
1415 "Partial declarations of `{0}' must not specify different base classes",
1416 GetSignatureForError ());
1418 PartialContainer.base_type_expr = base_type_expr;
1419 PartialContainer.base_type = base_type;
1420 set_base_type = true;
1424 if (iface_exprs != null) {
1425 if (PartialContainer.iface_exprs == null)
1426 PartialContainer.iface_exprs = iface_exprs;
1428 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1429 foreach (var iface_partial in iface_exprs) {
1430 if (ifaces.Contains (iface_partial))
1433 ifaces.Add (iface_partial);
1436 PartialContainer.iface_exprs = ifaces.ToArray ();
1440 PartialContainer.members.AddRange (members);
1441 if (containers != null) {
1442 if (PartialContainer.containers == null)
1443 PartialContainer.containers = new List<TypeContainer> ();
1445 PartialContainer.containers.AddRange (containers);
1448 members_defined = members_defined_ok = true;
1449 caching_flags |= Flags.CloseTypeCreated;
1451 set_base_type = true;
1454 var cycle = CheckRecursiveDefinition (this);
1455 if (cycle != null) {
1456 Report.SymbolRelatedToPreviousError (cycle);
1457 if (this is Interface) {
1458 Report.Error (529, Location,
1459 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1460 GetSignatureForError (), cycle.GetSignatureForError ());
1464 Report.Error (146, Location,
1465 "Circular base class dependency involving `{0}' and `{1}'",
1466 GetSignatureForError (), cycle.GetSignatureForError ());
1472 if (iface_exprs != null) {
1473 foreach (var iface_type in iface_exprs) {
1474 // Prevents a crash, the interface might not have been resolved: 442144
1475 if (iface_type == null)
1478 if (!spec.AddInterfaceDefined (iface_type))
1481 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1483 // Ensure the base is always setup
1484 var compiled_iface = iface_type.MemberDefinition as Interface;
1485 if (compiled_iface != null) {
1486 // TODO: Need DefineBaseType only
1487 compiled_iface.DefineContainer ();
1490 if (iface_type.Interfaces != null) {
1491 var base_ifaces = new List<TypeSpec> (iface_type.Interfaces);
1492 for (int i = 0; i < base_ifaces.Count; ++i) {
1493 var ii_iface_type = base_ifaces[i];
1494 if (spec.AddInterfaceDefined (ii_iface_type)) {
1495 TypeBuilder.AddInterfaceImplementation (ii_iface_type.GetMetaInfo ());
1497 if (ii_iface_type.Interfaces != null)
1498 base_ifaces.AddRange (ii_iface_type.Interfaces);
1505 if (Kind == MemberKind.Interface) {
1506 spec.BaseType = Compiler.BuiltinTypes.Object;
1510 if (set_base_type) {
1511 if (base_type != null) {
1512 spec.BaseType = base_type;
1514 // Set base type after type creation
1515 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1517 TypeBuilder.SetParent (null);
1524 public override void PrepareEmit ()
1526 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1529 foreach (var member in members) {
1530 var pm = member as IParametersMember;
1533 var p = pm.Parameters;
1537 ((ParametersCompiled) p).ResolveDefaultValues (member);
1540 var c = member as Const;
1545 base.PrepareEmit ();
1549 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1551 public override bool CreateContainer ()
1553 if (TypeBuilder != null)
1559 if (IsPartialPart) {
1560 spec = PartialContainer.spec;
1561 TypeBuilder = PartialContainer.TypeBuilder;
1562 all_tp_builders = PartialContainer.all_tp_builders;
1563 all_type_parameters = PartialContainer.all_type_parameters;
1565 if (!CreateTypeBuilder ()) {
1571 return base.CreateContainer ();
1574 protected override void DoDefineContainer ()
1578 DoResolveTypeParameters ();
1582 // Replaces normal spec with predefined one when compiling corlib
1583 // and this type container defines predefined type
1585 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1587 // When compiling build-in types we start with two
1588 // version of same type. One is of BuiltinTypeSpec and
1589 // second one is ordinary TypeSpec. The unification
1590 // happens at later stage when we know which type
1591 // really matches the builtin type signature. However
1592 // that means TypeSpec create during CreateType of this
1593 // type has to be replaced with builtin one
1595 spec.SetMetaInfo (TypeBuilder);
1596 spec.MemberCache = this.spec.MemberCache;
1597 spec.DeclaringType = this.spec.DeclaringType;
1600 current_type = null;
1603 void UpdateTypeParameterConstraints (TypeDefinition part)
1605 for (int i = 0; i < CurrentTypeParameters.Count; i++) {
1606 if (CurrentTypeParameters[i].AddPartialConstraints (part, part.MemberName.TypeParameters[i]))
1609 Report.SymbolRelatedToPreviousError (Location, "");
1610 Report.Error (265, part.Location,
1611 "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'",
1612 GetSignatureForError (), CurrentTypeParameters[i].GetSignatureForError ());
1616 public override void RemoveContainer (TypeContainer cont)
1618 base.RemoveContainer (cont);
1619 Members.Remove (cont);
1620 Cache.Remove (cont.Basename);
1623 protected virtual bool DoResolveTypeParameters ()
1625 var tparams = CurrentTypeParameters;
1626 if (tparams == null)
1629 var base_context = new BaseContext (this);
1630 for (int i = 0; i < tparams.Count; ++i) {
1631 var tp = tparams[i];
1633 if (!tp.ResolveConstraints (base_context)) {
1639 if (IsPartialPart) {
1640 PartialContainer.UpdateTypeParameterConstraints (this);
1646 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1648 if (InTransit != null)
1653 if (base_type != null) {
1654 var ptc = base_type.MemberDefinition as TypeDefinition;
1655 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1659 if (iface_exprs != null) {
1660 foreach (var iface in iface_exprs) {
1661 // the interface might not have been resolved, prevents a crash, see #442144
1664 var ptc = iface.MemberDefinition as Interface;
1665 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1670 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1678 /// Populates our TypeBuilder with fields and methods
1680 public sealed override bool Define ()
1682 if (members_defined)
1683 return members_defined_ok;
1685 members_defined_ok = DoDefineMembers ();
1686 members_defined = true;
1690 return members_defined_ok;
1693 protected virtual bool DoDefineMembers ()
1695 Debug.Assert (!IsPartialPart);
1697 if (iface_exprs != null) {
1698 foreach (var iface_type in iface_exprs) {
1699 if (iface_type == null)
1702 // Ensure the base is always setup
1703 var compiled_iface = iface_type.MemberDefinition as Interface;
1704 if (compiled_iface != null)
1705 compiled_iface.Define ();
1707 if (Kind == MemberKind.Interface)
1708 MemberCache.AddInterface (iface_type);
1710 ObsoleteAttribute oa = iface_type.GetAttributeObsolete ();
1711 if (oa != null && !IsObsolete)
1712 AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report);
1714 if (iface_type.Arity > 0) {
1715 // TODO: passing `this' is wrong, should be base type iface instead
1716 TypeManager.CheckTypeVariance (iface_type, Variance.Covariant, this);
1718 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1719 Report.Error (1966, Location,
1720 "`{0}': cannot implement a dynamic interface `{1}'",
1721 GetSignatureForError (), iface_type.GetSignatureForError ());
1726 if (iface_type.IsGenericOrParentIsGeneric) {
1727 if (spec.Interfaces != null) {
1728 foreach (var prev_iface in iface_exprs) {
1729 if (prev_iface == iface_type)
1732 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1735 Report.Error (695, Location,
1736 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1737 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1744 if (base_type != null) {
1746 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1748 if (base_type_expr != null) {
1749 ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
1750 if (obsolete_attr != null && !IsObsolete)
1751 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report);
1753 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1754 Report.Error (698, base_type_expr.Location,
1755 "A generic type cannot derive from `{0}' because it is an attribute class",
1756 base_type.GetSignatureForError ());
1760 if (base_type.Interfaces != null) {
1761 foreach (var iface in base_type.Interfaces)
1762 spec.AddInterface (iface);
1765 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1766 if (baseContainer != null) {
1767 baseContainer.Define ();
1770 // It can trigger define of this type (for generic types only)
1772 if (HasMembersDefined)
1777 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1778 pending = PendingImplementation.GetPendingImplementations (this);
1781 var count = members.Count;
1782 for (int i = 0; i < count; ++i) {
1783 var mc = members[i] as InterfaceMemberBase;
1784 if (mc == null || !mc.IsExplicitImpl)
1789 } catch (Exception e) {
1790 throw new InternalErrorException (mc, e);
1794 for (int i = 0; i < count; ++i) {
1795 var mc = members[i] as InterfaceMemberBase;
1796 if (mc != null && mc.IsExplicitImpl)
1799 if (members[i] is TypeContainer)
1803 members[i].Define ();
1804 } catch (Exception e) {
1805 throw new InternalErrorException (members[i], e);
1810 CheckPairedOperators ();
1813 if (requires_delayed_unmanagedtype_check) {
1814 requires_delayed_unmanagedtype_check = false;
1815 foreach (var member in members) {
1816 var f = member as Field;
1817 if (f != null && f.MemberType != null && f.MemberType.IsPointer)
1818 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
1822 ComputeIndexerName();
1824 if (HasEquals && !HasGetHashCode) {
1825 Report.Warning (659, 3, Location,
1826 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
1829 if (Kind == MemberKind.Interface && iface_exprs != null) {
1830 MemberCache.RemoveHiddenMembers (spec);
1836 void ComputeIndexerName ()
1838 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
1839 if (indexers == null)
1842 string class_indexer_name = null;
1845 // Check normal indexers for consistent name, explicit interface implementation
1846 // indexers are ignored
1848 foreach (var indexer in indexers) {
1850 // FindMembers can return unfiltered full hierarchy names
1852 if (indexer.DeclaringType != spec)
1855 has_normal_indexers = true;
1857 if (class_indexer_name == null) {
1858 indexer_name = class_indexer_name = indexer.Name;
1862 if (indexer.Name != class_indexer_name)
1863 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
1864 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
1868 void EmitIndexerName ()
1870 if (!has_normal_indexers)
1873 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
1877 var encoder = new AttributeEncoder ();
1878 encoder.Encode (GetAttributeDefaultMember ());
1879 encoder.EncodeEmptyNamedArguments ();
1881 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1884 public override void VerifyMembers ()
1887 // Check for internal or private fields that were never assigned
1889 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
1890 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
1891 foreach (var member in members) {
1892 if (member is Event) {
1894 // An event can be assigned from same class only, so we can report
1895 // this warning for all accessibility modes
1898 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
1903 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
1904 if (is_type_exposed)
1907 member.SetIsUsed ();
1910 var f = member as Field;
1914 if (!member.IsUsed) {
1915 if ((member.caching_flags & Flags.IsAssigned) == 0) {
1916 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
1918 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
1919 member.GetSignatureForError ());
1924 if ((f.caching_flags & Flags.IsAssigned) != 0)
1928 // Only report 649 on level 4
1930 if (Compiler.Settings.WarningLevel < 4)
1934 // Don't be pedantic when type requires specific layout
1936 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
1939 Constant c = New.Constantify (f.MemberType, f.Location);
1942 value = c.GetValueAsLiteral ();
1943 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
1950 value = " `" + value + "'";
1952 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
1953 f.GetSignatureForError (), value);
1957 base.VerifyMembers ();
1960 public override void Emit ()
1962 if (OptAttributes != null)
1963 OptAttributes.Emit ();
1965 if (!IsCompilerGenerated) {
1967 MemberSpec candidate;
1968 bool overrides = false;
1969 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
1970 if (conflict_symbol == null && candidate == null) {
1971 if ((ModFlags & Modifiers.NEW) != 0)
1972 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
1973 GetSignatureForError ());
1975 if ((ModFlags & Modifiers.NEW) == 0) {
1976 if (candidate == null)
1977 candidate = conflict_symbol;
1979 Report.SymbolRelatedToPreviousError (candidate);
1980 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
1981 GetSignatureForError (), candidate.GetSignatureForError ());
1986 // Run constraints check on all possible generic types
1987 if (base_type != null && base_type_expr != null) {
1988 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
1991 if (iface_exprs != null) {
1992 foreach (var iface_type in iface_exprs) {
1993 if (iface_type == null)
1996 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2001 if (all_tp_builders != null) {
2002 int current_starts_index = CurrentTypeParametersStartIndex;
2003 for (int i = 0; i < all_tp_builders.Length; i++) {
2004 if (i < current_starts_index) {
2005 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2007 var tp = CurrentTypeParameters [i - current_starts_index];
2008 tp.CheckGenericConstraints (!IsObsolete);
2014 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2015 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2018 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2019 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2024 for (int i = 0; i < members.Count; i++)
2028 CheckAttributeClsCompliance ();
2030 if (pending != null)
2031 pending.VerifyPendingMethods ();
2035 void CheckAttributeClsCompliance ()
2037 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2040 foreach (var m in members) {
2041 var c = m as Constructor;
2045 if (c.HasCompliantArgs)
2049 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2052 public sealed override void EmitContainer ()
2054 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2060 public override void CloseContainer ()
2062 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2065 // Close base type container first to avoid TypeLoadException
2066 if (spec.BaseType != null) {
2067 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2068 if (btype != null) {
2069 btype.CloseContainer ();
2071 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2077 caching_flags |= Flags.CloseTypeCreated;
2078 TypeBuilder.CreateType ();
2079 } catch (TypeLoadException) {
2081 // This is fine, the code still created the type
2083 } catch (Exception e) {
2084 throw new InternalErrorException (this, e);
2087 base.CloseContainer ();
2090 initialized_fields = null;
2091 initialized_static_fields = null;
2093 OptAttributes = null;
2097 // Performs the validation on a Method's modifiers (properties have
2098 // the same properties).
2100 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2102 public bool MethodModifiersValid (MemberCore mc)
2104 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2105 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2107 var flags = mc.ModFlags;
2110 // At most one of static, virtual or override
2112 if ((flags & Modifiers.STATIC) != 0){
2113 if ((flags & vao) != 0){
2114 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2115 mc.GetSignatureForError ());
2120 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2121 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2122 mc.GetSignatureForError ());
2127 // If the declaration includes the abstract modifier, then the
2128 // declaration does not include static, virtual or extern
2130 if ((flags & Modifiers.ABSTRACT) != 0){
2131 if ((flags & Modifiers.EXTERN) != 0){
2133 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2137 if ((flags & Modifiers.SEALED) != 0) {
2138 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2142 if ((flags & Modifiers.VIRTUAL) != 0){
2143 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2147 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2148 Report.SymbolRelatedToPreviousError (this);
2149 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2150 mc.GetSignatureForError (), GetSignatureForError ());
2155 if ((flags & Modifiers.PRIVATE) != 0){
2156 if ((flags & vao) != 0){
2157 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2162 if ((flags & Modifiers.SEALED) != 0){
2163 if ((flags & Modifiers.OVERRIDE) == 0){
2164 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2172 protected override bool VerifyClsCompliance ()
2174 if (!base.VerifyClsCompliance ())
2177 // Check all container names for user classes
2178 if (Kind != MemberKind.Delegate)
2179 MemberCache.VerifyClsCompliance (Definition, Report);
2181 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2182 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2183 GetSignatureForError (), BaseType.GetSignatureForError ());
2189 /// Performs checks for an explicit interface implementation. First it
2190 /// checks whether the `interface_type' is a base inteface implementation.
2191 /// Then it checks whether `name' exists in the interface type.
2193 public bool VerifyImplements (InterfaceMemberBase mb)
2195 var ifaces = spec.Interfaces;
2196 if (ifaces != null) {
2197 foreach (TypeSpec t in ifaces){
2198 if (t == mb.InterfaceType)
2203 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2204 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2205 mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType));
2210 // Used for visiblity checks to tests whether this definition shares
2211 // base type baseType, it does member-definition search
2213 public bool IsBaseTypeDefinition (TypeSpec baseType)
2215 // RootContext check
2216 if (TypeBuilder == null)
2221 if (type.MemberDefinition == baseType.MemberDefinition)
2224 type = type.BaseType;
2225 } while (type != null);
2230 public override bool IsClsComplianceRequired ()
2233 return PartialContainer.IsClsComplianceRequired ();
2235 return base.IsClsComplianceRequired ();
2238 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2240 return Module.DeclaringAssembly == assembly;
2243 public virtual bool IsUnmanagedType ()
2248 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2250 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2254 // Public function used to locate types.
2256 // Set 'ignore_cs0104' to true if you want to ignore cs0104 errors.
2258 // Returns: Type or null if they type can not be found.
2260 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2262 FullNamedExpression e;
2263 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2269 var tp = CurrentTypeParameters;
2271 TypeParameter tparam = tp.Find (name);
2273 e = new TypeParameterExpr (tparam, Location.Null);
2278 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2280 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2281 e = new TypeExpression (t, Location.Null);
2283 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2287 // TODO MemberCache: How to cache arity stuff ?
2288 if (arity == 0 && mode == LookupMode.Normal)
2294 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2296 // Has any nested type
2297 // Does not work, because base type can have
2298 //if (PartialContainer.Types == null)
2301 var container = PartialContainer.CurrentType;
2302 return MemberCache.FindNestedType (container, name, arity);
2305 public void Mark_HasEquals ()
2307 cached_method |= CachedMethods.Equals;
2310 public void Mark_HasGetHashCode ()
2312 cached_method |= CachedMethods.GetHashCode;
2315 public override void WriteDebugSymbol (MonoSymbolFile file)
2320 foreach (var m in members) {
2321 m.WriteDebugSymbol (file);
2326 /// Method container contains Equals method
2328 public bool HasEquals {
2330 return (cached_method & CachedMethods.Equals) != 0;
2335 /// Method container contains GetHashCode method
2337 public bool HasGetHashCode {
2339 return (cached_method & CachedMethods.GetHashCode) != 0;
2343 public bool HasStaticFieldInitializer {
2345 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2349 cached_method |= CachedMethods.HasStaticFieldInitializer;
2351 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2355 public override string DocCommentHeader {
2356 get { return "T:"; }
2360 public abstract class ClassOrStruct : TypeDefinition
2362 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2364 SecurityType declarative_security;
2366 public ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2367 : base (parent, name, attrs, kind)
2371 protected override TypeAttributes TypeAttr {
2373 TypeAttributes ta = base.TypeAttr;
2374 if (!has_static_constructor)
2375 ta |= TypeAttributes.BeforeFieldInit;
2377 if (Kind == MemberKind.Class) {
2378 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2380 ta |= StaticClassAttribute;
2382 ta |= TypeAttributes.SequentialLayout;
2389 public override void AddNameToContainer (MemberCore symbol, string name)
2391 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2392 if (symbol is TypeParameter) {
2393 Report.Error (694, symbol.Location,
2394 "Type parameter `{0}' has same name as containing type, or method",
2395 symbol.GetSignatureForError ());
2399 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2400 if (imb == null || !imb.IsExplicitImpl) {
2401 Report.SymbolRelatedToPreviousError (this);
2402 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2403 symbol.GetSignatureForError ());
2408 base.AddNameToContainer (symbol, name);
2411 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2413 if (a.IsValidSecurityAttribute ()) {
2414 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2418 if (a.Type == pa.StructLayout) {
2419 PartialContainer.HasStructLayout = true;
2420 if (a.IsExplicitLayoutKind ())
2421 PartialContainer.HasExplicitLayout = true;
2424 if (a.Type == pa.Dynamic) {
2425 a.Error_MisusedDynamicAttribute ();
2429 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2433 /// Defines the default constructors
2435 protected Constructor DefineDefaultConstructor (bool is_static)
2437 // The default instance constructor is public
2438 // If the class is abstract, the default constructor is protected
2439 // The default static constructor is private
2443 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2445 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2448 var c = new Constructor (this, MemberName.Name, mods, null, ParametersCompiled.EmptyReadOnlyParameters, Location);
2449 c.Initializer = new GeneratedBaseInitializer (Location);
2451 AddConstructor (c, true);
2452 c.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location) {
2453 IsCompilerGenerated = true
2459 protected override bool DoDefineMembers ()
2461 CheckProtectedModifier ();
2463 base.DoDefineMembers ();
2468 public override void Emit ()
2470 if (!has_static_constructor && HasStaticFieldInitializer) {
2471 var c = DefineDefaultConstructor (true);
2477 if (declarative_security != null) {
2478 foreach (var de in declarative_security) {
2480 TypeBuilder.__AddDeclarativeSecurity (de);
2482 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2490 public sealed class Class : ClassOrStruct
2492 const Modifiers AllowedModifiers =
2495 Modifiers.PROTECTED |
2496 Modifiers.INTERNAL |
2498 Modifiers.ABSTRACT |
2503 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2504 : base (parent, name, attrs, MemberKind.Class)
2506 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2507 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2508 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2511 public override void Accept (StructuralVisitor visitor)
2513 visitor.Visit (this);
2516 public override void AddBasesForPart (List<FullNamedExpression> bases)
2518 var pmn = MemberName;
2519 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2520 Report.Error (537, Location,
2521 "The class System.Object cannot have a base class or implement an interface.");
2523 base.AddBasesForPart (bases);
2526 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2528 if (a.Type == pa.AttributeUsage) {
2529 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2530 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2534 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2535 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2539 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2540 a.Error_MissingGuidAttribute ();
2544 if (a.Type == pa.Extension) {
2545 a.Error_MisusedExtensionAttribute ();
2549 if (a.Type.IsConditionallyExcluded (this, Location))
2552 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2555 public override AttributeTargets AttributeTargets {
2557 return AttributeTargets.Class;
2561 protected override bool DoDefineMembers ()
2563 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2564 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2567 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2568 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2572 foreach (var m in Members) {
2573 if (m is Operator) {
2574 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2578 if (m is Destructor) {
2579 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2584 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2588 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2591 if (m is Constructor) {
2592 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2596 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2599 if (!PartialContainer.HasInstanceConstructor)
2600 DefineDefaultConstructor (false);
2603 return base.DoDefineMembers ();
2606 public override void Emit ()
2610 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2611 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2613 if (base_type != null && base_type.HasDynamicElement) {
2614 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2618 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2620 var ifaces = base.ResolveBaseTypes (out base_class);
2622 if (base_class == null) {
2623 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2624 base_type = Compiler.BuiltinTypes.Object;
2626 if (base_type.IsGenericParameter){
2627 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2628 GetSignatureForError (), base_type.GetSignatureForError ());
2629 } else if (base_type.IsStatic) {
2630 Report.SymbolRelatedToPreviousError (base_type);
2631 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2632 GetSignatureForError (), base_type.GetSignatureForError ());
2633 } else if (base_type.IsSealed) {
2634 Report.SymbolRelatedToPreviousError (base_type);
2635 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2636 GetSignatureForError (), base_type.GetSignatureForError ());
2637 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2638 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2639 GetSignatureForError (), base_type.GetSignatureForError ());
2642 switch (base_type.BuiltinType) {
2643 case BuiltinTypeSpec.Type.Enum:
2644 case BuiltinTypeSpec.Type.ValueType:
2645 case BuiltinTypeSpec.Type.MulticastDelegate:
2646 case BuiltinTypeSpec.Type.Delegate:
2647 case BuiltinTypeSpec.Type.Array:
2648 if (!(spec is BuiltinTypeSpec)) {
2649 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2650 GetSignatureForError (), base_type.GetSignatureForError ());
2652 base_type = Compiler.BuiltinTypes.Object;
2657 if (!IsAccessibleAs (base_type)) {
2658 Report.SymbolRelatedToPreviousError (base_type);
2659 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2660 base_type.GetSignatureForError (), GetSignatureForError ());
2664 if (PartialContainer.IsStatic && ifaces != null) {
2665 foreach (var t in ifaces)
2666 Report.SymbolRelatedToPreviousError (t);
2667 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2673 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2674 /// Valid only for attribute classes.
2675 public override string[] ConditionalConditions ()
2677 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2680 caching_flags &= ~Flags.Excluded_Undetected;
2682 if (OptAttributes == null)
2685 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2689 string[] conditions = new string[attrs.Length];
2690 for (int i = 0; i < conditions.Length; ++i)
2691 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2693 caching_flags |= Flags.Excluded;
2698 public sealed class Struct : ClassOrStruct
2700 bool is_unmanaged, has_unmanaged_check_done;
2704 // Modifiers allowed in a struct declaration
2706 const Modifiers AllowedModifiers =
2709 Modifiers.PROTECTED |
2710 Modifiers.INTERNAL |
2714 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2715 : base (parent, name, attrs, MemberKind.Struct)
2717 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2718 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2719 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2722 public override AttributeTargets AttributeTargets {
2724 return AttributeTargets.Struct;
2728 public override void Accept (StructuralVisitor visitor)
2730 visitor.Visit (this);
2733 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2735 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2738 // When struct constains fixed fixed and struct layout has explicitly
2739 // set CharSet, its value has to be propagated to compiler generated
2742 if (a.Type == pa.StructLayout) {
2743 var value = a.GetNamedValue ("CharSet");
2747 for (int i = 0; i < Members.Count; ++i) {
2748 FixedField ff = Members [i] as FixedField;
2752 ff.CharSet = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
2757 bool CheckStructCycles ()
2763 foreach (var member in Members) {
2764 var field = member as Field;
2768 TypeSpec ftype = field.Spec.MemberType;
2769 if (!ftype.IsStruct)
2772 if (ftype is BuiltinTypeSpec)
2775 foreach (var targ in ftype.TypeArguments) {
2776 if (!CheckFieldTypeCycle (targ)) {
2777 Report.Error (523, field.Location,
2778 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2779 field.GetSignatureForError (), ftype.GetSignatureForError ());
2785 // Static fields of exactly same type are allowed
2787 if (field.IsStatic && ftype == CurrentType)
2790 if (!CheckFieldTypeCycle (ftype)) {
2791 Report.Error (523, field.Location,
2792 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2793 field.GetSignatureForError (), ftype.GetSignatureForError ());
2802 static bool CheckFieldTypeCycle (TypeSpec ts)
2804 var fts = ts.MemberDefinition as Struct;
2808 return fts.CheckStructCycles ();
2811 public override void Emit ()
2813 CheckStructCycles ();
2818 public override bool IsUnmanagedType ()
2820 if (has_unmanaged_check_done)
2821 return is_unmanaged;
2823 if (requires_delayed_unmanagedtype_check)
2826 var parent_def = Parent.PartialContainer;
2827 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
2828 has_unmanaged_check_done = true;
2832 if (first_nonstatic_field != null) {
2833 requires_delayed_unmanagedtype_check = true;
2835 foreach (var member in Members) {
2836 var f = member as Field;
2843 // It can happen when recursive unmanaged types are defined
2844 // struct S { S* s; }
2845 TypeSpec mt = f.MemberType;
2853 has_unmanaged_check_done = true;
2857 has_unmanaged_check_done = true;
2860 is_unmanaged = true;
2864 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2866 var ifaces = base.ResolveBaseTypes (out base_class);
2867 base_type = Compiler.BuiltinTypes.ValueType;
2871 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
2873 if ((field.ModFlags & Modifiers.STATIC) == 0) {
2874 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
2875 field.GetSignatureForError ());
2878 base.RegisterFieldForInitialization (field, expression);
2886 public sealed class Interface : TypeDefinition {
2889 /// Modifiers allowed in a class declaration
2891 const Modifiers AllowedModifiers =
2894 Modifiers.PROTECTED |
2895 Modifiers.INTERNAL |
2899 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2900 : base (parent, name, attrs, MemberKind.Interface)
2902 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2904 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
2905 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2910 public override AttributeTargets AttributeTargets {
2912 return AttributeTargets.Interface;
2916 protected override TypeAttributes TypeAttr {
2918 const TypeAttributes DefaultTypeAttributes =
2919 TypeAttributes.AutoLayout |
2920 TypeAttributes.Abstract |
2921 TypeAttributes.Interface;
2923 return base.TypeAttr | DefaultTypeAttributes;
2929 public override void Accept (StructuralVisitor visitor)
2931 visitor.Visit (this);
2934 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2936 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2937 a.Error_MissingGuidAttribute ();
2941 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2944 protected override bool VerifyClsCompliance ()
2946 if (!base.VerifyClsCompliance ())
2949 if (iface_exprs != null) {
2950 foreach (var iface in iface_exprs) {
2951 if (iface.IsCLSCompliant ())
2954 Report.SymbolRelatedToPreviousError (iface);
2955 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
2956 GetSignatureForError (), TypeManager.CSharpName (iface));
2964 public abstract class InterfaceMemberBase : MemberBase
2967 // Common modifiers allowed in a class declaration
2969 protected const Modifiers AllowedModifiersClass =
2972 Modifiers.PROTECTED |
2973 Modifiers.INTERNAL |
2978 Modifiers.OVERRIDE |
2979 Modifiers.ABSTRACT |
2984 // Common modifiers allowed in a struct declaration
2986 protected const Modifiers AllowedModifiersStruct =
2989 Modifiers.PROTECTED |
2990 Modifiers.INTERNAL |
2993 Modifiers.OVERRIDE |
2998 // Common modifiers allowed in a interface declaration
3000 protected const Modifiers AllowedModifiersInterface =
3005 // Whether this is an interface member.
3007 public bool IsInterface;
3010 // If true, this is an explicit interface implementation
3012 public readonly bool IsExplicitImpl;
3014 protected bool is_external_implementation;
3017 // The interface type we are explicitly implementing
3019 public TypeSpec InterfaceType;
3022 // The method we're overriding if this is an override method.
3024 protected MethodSpec base_method;
3026 readonly Modifiers explicit_mod_flags;
3027 public MethodAttributes flags;
3029 public InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3030 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3032 IsInterface = parent.Kind == MemberKind.Interface;
3033 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3034 explicit_mod_flags = mod;
3037 public abstract Variance ExpectedMemberTypeVariance { get; }
3039 protected override bool CheckBase ()
3041 if (!base.CheckBase ())
3044 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3045 CheckForDuplications ();
3050 // For System.Object only
3051 if (Parent.BaseType == null)
3054 MemberSpec candidate;
3055 bool overrides = false;
3056 var base_member = FindBaseMember (out candidate, ref overrides);
3058 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3059 if (base_member == null) {
3060 if (candidate == null) {
3061 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3062 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3063 "object.Finalize()");
3065 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3066 GetSignatureForError (), SimpleName.GetMemberType (this));
3069 Report.SymbolRelatedToPreviousError (candidate);
3071 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3072 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3073 else if (this is PropertyBase)
3074 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3075 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3077 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3078 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3085 // Handles ambiguous overrides
3087 if (candidate != null) {
3088 Report.SymbolRelatedToPreviousError (candidate);
3089 Report.SymbolRelatedToPreviousError (base_member);
3091 // Get member definition for error reporting
3092 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3093 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3095 Report.Error (462, Location,
3096 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3097 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3100 if (!CheckOverrideAgainstBase (base_member))
3103 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3105 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3106 Report.SymbolRelatedToPreviousError (base_member);
3107 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3108 GetSignatureForError (), base_member.GetSignatureForError ());
3111 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3112 Report.SymbolRelatedToPreviousError (base_member);
3113 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3114 GetSignatureForError (), base_member.GetSignatureForError ());
3118 base_method = base_member as MethodSpec;
3122 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3123 base_member = candidate;
3125 if (base_member == null) {
3126 if ((ModFlags & Modifiers.NEW) != 0) {
3127 if (base_member == null) {
3128 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3129 GetSignatureForError ());
3133 if ((ModFlags & Modifiers.NEW) == 0) {
3134 ModFlags |= Modifiers.NEW;
3135 if (!IsCompilerGenerated) {
3136 Report.SymbolRelatedToPreviousError (base_member);
3137 if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3138 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",
3139 GetSignatureForError (), base_member.GetSignatureForError ());
3141 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3142 GetSignatureForError (), base_member.GetSignatureForError ());
3147 if (!IsInterface && base_member.IsAbstract && !overrides) {
3148 Report.SymbolRelatedToPreviousError (base_member);
3149 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3150 GetSignatureForError (), base_member.GetSignatureForError ());
3157 protected virtual bool CheckForDuplications ()
3159 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3163 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3164 // that have been defined.
3166 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3170 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3171 Report.SymbolRelatedToPreviousError (base_member);
3172 Report.Error (506, Location,
3173 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3174 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3178 // Now we check that the overriden method is not final
3179 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3180 Report.SymbolRelatedToPreviousError (base_member);
3181 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3182 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3186 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3187 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3188 Report.SymbolRelatedToPreviousError (base_member);
3189 if (this is PropertyBasedMember) {
3190 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3191 GetSignatureForError (), TypeManager.CSharpName (base_member_type), TypeManager.CSharpSignature (base_member));
3193 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3194 GetSignatureForError (), TypeManager.CSharpName (base_member_type), TypeManager.CSharpSignature (base_member));
3202 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3204 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3205 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3207 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3209 // It must be at least "protected"
3211 if ((thisp & Modifiers.PROTECTED) == 0) {
3216 // when overriding protected internal, the method can be declared
3217 // protected internal only within the same assembly or assembly
3218 // which has InternalsVisibleTo
3220 if ((thisp & Modifiers.INTERNAL) != 0) {
3221 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3225 // protected overriding protected internal inside same assembly
3226 // requires internal modifier as well
3228 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3235 return thisp == base_classp;
3238 public override bool Define ()
3241 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3242 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3244 flags = MethodAttributes.Public |
3245 MethodAttributes.Abstract |
3246 MethodAttributes.HideBySig |
3247 MethodAttributes.NewSlot |
3248 MethodAttributes.Virtual;
3250 Parent.PartialContainer.MethodModifiersValid (this);
3252 flags = ModifiersExtensions.MethodAttr (ModFlags);
3255 if (IsExplicitImpl) {
3256 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3257 if (InterfaceType == null)
3260 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3261 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3262 GetSignatureForError ());
3265 if (!InterfaceType.IsInterface) {
3266 Report.SymbolRelatedToPreviousError (InterfaceType);
3267 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3268 TypeManager.CSharpName (InterfaceType));
3270 Parent.PartialContainer.VerifyImplements (this);
3273 ModifiersExtensions.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location, Report);
3276 return base.Define ();
3279 protected bool DefineParameters (ParametersCompiled parameters)
3281 if (!parameters.Resolve (this))
3285 for (int i = 0; i < parameters.Count; ++i) {
3286 Parameter p = parameters [i];
3288 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3289 p.Warning_UselessOptionalParameter (Report);
3291 if (p.CheckAccessibility (this))
3294 TypeSpec t = parameters.Types [i];
3295 Report.SymbolRelatedToPreviousError (t);
3296 if (this is Indexer)
3297 Report.Error (55, Location,
3298 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3299 TypeManager.CSharpName (t), GetSignatureForError ());
3300 else if (this is Operator)
3301 Report.Error (57, Location,
3302 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3303 TypeManager.CSharpName (t), GetSignatureForError ());
3305 Report.Error (51, Location,
3306 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3307 TypeManager.CSharpName (t), GetSignatureForError ());
3313 protected override void DoMemberTypeDependentChecks ()
3315 base.DoMemberTypeDependentChecks ();
3317 TypeManager.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3320 public override void Emit()
3322 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3323 // We are more strict than csc and report this as an error because SRE does not allow emit that
3324 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3325 if (this is Constructor) {
3326 Report.Warning (824, 1, Location,
3327 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3329 Report.Warning (626, 1, Location,
3330 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3331 GetSignatureForError ());
3338 public override bool EnableOverloadChecks (MemberCore overload)
3341 // Two members can differ in their explicit interface
3342 // type parameter only
3344 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3345 if (imb != null && imb.IsExplicitImpl) {
3346 if (IsExplicitImpl) {
3347 caching_flags |= Flags.MethodOverloadsExist;
3352 return IsExplicitImpl;
3355 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3357 var base_modifiers = base_member.Modifiers;
3359 // Remove internal modifier from types which are not internally accessible
3360 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3361 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3362 base_modifiers = Modifiers.PROTECTED;
3364 Report.SymbolRelatedToPreviousError (base_member);
3365 Report.Error (507, member.Location,
3366 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3367 member.GetSignatureForError (),
3368 ModifiersExtensions.AccessibilityName (base_modifiers),
3369 base_member.GetSignatureForError ());
3372 protected void Error_StaticReturnType ()
3374 Report.Error (722, Location,
3375 "`{0}': static types cannot be used as return types",
3376 MemberType.GetSignatureForError ());
3380 /// Gets base method and its return type
3382 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3384 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3388 // The "short" name of this property / indexer / event. This is the
3389 // name without the explicit interface.
3391 public string ShortName {
3392 get { return MemberName.Name; }
3396 // Returns full metadata method name
3398 public string GetFullName (MemberName name)
3400 return GetFullName (name.Name);
3403 public string GetFullName (string name)
3405 if (!IsExplicitImpl)
3409 // When dealing with explicit members a full interface type
3410 // name is added to member name to avoid possible name conflicts
3412 // We use CSharpName which gets us full name with benefit of
3413 // replacing predefined names which saves some space and name
3416 return TypeManager.CSharpName (InterfaceType) + "." + name;
3419 public override string GetSignatureForDocumentation ()
3422 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetExplicitNameSignatureForDocumentation () + "#" + ShortName;
3424 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3427 public override bool IsUsed
3429 get { return IsExplicitImpl || base.IsUsed; }
3432 public override void SetConstraints (List<Constraints> constraints_list)
3434 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3435 Report.Error (460, Location,
3436 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3437 GetSignatureForError ());
3440 base.SetConstraints (constraints_list);
3444 public abstract class MemberBase : MemberCore
3446 protected FullNamedExpression type_expr;
3447 protected TypeSpec member_type;
3448 public new TypeDefinition Parent;
3450 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3451 : base (parent, name, attrs)
3453 this.Parent = parent;
3454 this.type_expr = type;
3455 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3460 public TypeSpec MemberType {
3466 public FullNamedExpression TypeExpression {
3475 // Main member define entry
3477 public override bool Define ()
3479 DoMemberTypeIndependentChecks ();
3482 // Returns false only when type resolution failed
3484 if (!ResolveMemberType ())
3487 DoMemberTypeDependentChecks ();
3492 // Any type_name independent checks
3494 protected virtual void DoMemberTypeIndependentChecks ()
3496 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3497 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3498 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3499 GetSignatureForError (), Parent.GetSignatureForError ());
3504 // Any type_name dependent checks
3506 protected virtual void DoMemberTypeDependentChecks ()
3508 // verify accessibility
3509 if (!IsAccessibleAs (MemberType)) {
3510 Report.SymbolRelatedToPreviousError (MemberType);
3511 if (this is Property)
3512 Report.Error (53, Location,
3513 "Inconsistent accessibility: property type `" +
3514 TypeManager.CSharpName (MemberType) + "' is less " +
3515 "accessible than property `" + GetSignatureForError () + "'");
3516 else if (this is Indexer)
3517 Report.Error (54, Location,
3518 "Inconsistent accessibility: indexer return type `" +
3519 TypeManager.CSharpName (MemberType) + "' is less " +
3520 "accessible than indexer `" + GetSignatureForError () + "'");
3521 else if (this is MethodCore) {
3522 if (this is Operator)
3523 Report.Error (56, Location,
3524 "Inconsistent accessibility: return type `" +
3525 TypeManager.CSharpName (MemberType) + "' is less " +
3526 "accessible than operator `" + GetSignatureForError () + "'");
3528 Report.Error (50, Location,
3529 "Inconsistent accessibility: return type `" +
3530 TypeManager.CSharpName (MemberType) + "' is less " +
3531 "accessible than method `" + GetSignatureForError () + "'");
3533 Report.Error (52, Location,
3534 "Inconsistent accessibility: field type `" +
3535 TypeManager.CSharpName (MemberType) + "' is less " +
3536 "accessible than field `" + GetSignatureForError () + "'");
3541 protected void IsTypePermitted ()
3543 if (MemberType.IsSpecialRuntimeType) {
3544 if (Parent is StateMachine) {
3545 Report.Error (4012, Location,
3546 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3547 MemberType.GetSignatureForError ());
3548 } else if (Parent is HoistedStoreyClass) {
3549 Report.Error (4013, Location,
3550 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3551 MemberType.GetSignatureForError ());
3553 Report.Error (610, Location,
3554 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3559 protected virtual bool CheckBase ()
3561 CheckProtectedModifier ();
3566 public override string GetSignatureForDocumentation ()
3568 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3571 protected virtual bool ResolveMemberType ()
3573 if (member_type != null)
3574 throw new InternalErrorException ("Multi-resolve");
3576 member_type = type_expr.ResolveAsType (this);
3577 return member_type != null;