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)
17 using System.Collections.Generic;
18 using System.Runtime.InteropServices;
19 using System.Security;
20 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;
48 protected List<TypeContainer> containers;
50 TypeDefinition main_container;
52 protected Dictionary<string, MemberCore> defined_names;
54 protected bool is_defined;
56 public int CounterAnonymousMethods { get; set; }
57 public int CounterAnonymousContainers { get; set; }
58 public int CounterSwitchTypes { get; set; }
60 protected TypeContainer (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
61 : base (parent, name, attrs)
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 void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
104 AddTypeContainerMember (c);
107 public virtual void AddPartial (TypeDefinition next_part)
110 (PartialContainer ?? this).defined_names.TryGetValue (next_part.MemberName.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_MODIFIER) == 0 &&
144 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) == 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_MODIFIER) != 0) {
172 existing.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFIER | Modifiers.AccessibilityMask);
173 } else if ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) != 0) {
174 existing.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFIER | 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 existing.AddPartialPart (next_part);
193 AddTypeContainerMember (next_part);
196 public virtual void AddTypeContainer (TypeContainer tc)
198 AddTypeContainerMember (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 protected virtual void AddTypeContainerMember (TypeContainer tc)
218 public virtual void CloseContainer ()
220 if (containers != null) {
221 foreach (TypeContainer tc in containers) {
222 tc.CloseContainer ();
227 public virtual void CreateMetadataName (StringBuilder sb)
229 if (Parent != null && Parent.MemberName != null)
230 Parent.CreateMetadataName (sb);
232 MemberName.CreateMetadataName (sb);
235 public virtual bool CreateContainer ()
237 if (containers != null) {
238 foreach (TypeContainer tc in containers) {
239 tc.CreateContainer ();
246 public override bool Define ()
248 if (containers != null) {
249 foreach (TypeContainer tc in containers) {
254 // Release cache used by parser only
255 if (Module.Evaluator == null) {
256 defined_names = null;
258 defined_names.Clear ();
264 public virtual void PrepareEmit ()
266 if (containers != null) {
267 foreach (var t in containers) {
270 } catch (Exception e) {
271 if (MemberName == MemberName.Null)
274 throw new InternalErrorException (t, e);
280 public virtual bool DefineContainer ()
287 DoDefineContainer ();
289 if (containers != null) {
290 foreach (TypeContainer tc in containers) {
292 tc.DefineContainer ();
293 } catch (Exception e) {
294 if (MemberName == MemberName.Null)
297 throw new InternalErrorException (tc, e);
305 public virtual void ExpandBaseInterfaces ()
307 if (containers != null) {
308 foreach (TypeContainer tc in containers) {
309 tc.ExpandBaseInterfaces ();
314 protected virtual void DefineNamespace ()
316 if (containers != null) {
317 foreach (var tc in containers) {
319 tc.DefineNamespace ();
320 } catch (Exception e) {
321 throw new InternalErrorException (tc, e);
327 protected virtual void DoDefineContainer ()
331 public virtual void EmitContainer ()
333 if (containers != null) {
334 for (int i = 0; i < containers.Count; ++i)
335 containers[i].EmitContainer ();
339 protected void Error_MissingPartialModifier (MemberCore type)
341 Report.Error (260, type.Location,
342 "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
343 type.GetSignatureForError ());
346 public override string GetSignatureForDocumentation ()
348 if (Parent != null && Parent.MemberName != null)
349 return Parent.GetSignatureForDocumentation () + "." + MemberName.GetSignatureForDocumentation ();
351 return MemberName.GetSignatureForDocumentation ();
354 public override string GetSignatureForError ()
356 if (Parent != null && Parent.MemberName != null)
357 return Parent.GetSignatureForError () + "." + MemberName.GetSignatureForError ();
359 return MemberName.GetSignatureForError ();
362 public string GetSignatureForMetadata ()
364 if (Parent is TypeDefinition) {
365 return Parent.GetSignatureForMetadata () + "+" + TypeNameParser.Escape (MemberName.Basename);
368 var sb = new StringBuilder ();
369 CreateMetadataName (sb);
370 return sb.ToString ();
373 public virtual void RemoveContainer (TypeContainer cont)
375 if (containers != null)
376 containers.Remove (cont);
378 var tc = Parent == Module ? Module : this;
379 tc.defined_names.Remove (cont.MemberName.Basename);
382 public virtual void VerifyMembers ()
384 if (containers != null) {
385 foreach (TypeContainer tc in containers)
390 public override void WriteDebugSymbol (MonoSymbolFile file)
392 if (containers != null) {
393 foreach (TypeContainer tc in containers) {
394 tc.WriteDebugSymbol (file);
400 public abstract class TypeDefinition : TypeContainer, ITypeDefinition
403 // Different context is needed when resolving type container base
404 // types. Type names come from the parent scope but type parameter
405 // names from the container scope.
407 public struct BaseContext : IMemberContext
411 public BaseContext (TypeContainer tc)
416 #region IMemberContext Members
418 public CompilerContext Compiler {
419 get { return tc.Compiler; }
422 public TypeSpec CurrentType {
423 get { return tc.PartialContainer.CurrentType; }
426 public TypeParameters CurrentTypeParameters {
427 get { return tc.PartialContainer.CurrentTypeParameters; }
430 public MemberCore CurrentMemberDefinition {
434 public bool IsObsolete {
435 get { return tc.IsObsolete; }
438 public bool IsUnsafe {
439 get { return tc.IsUnsafe; }
442 public bool IsStatic {
443 get { return tc.IsStatic; }
446 public ModuleContainer Module {
447 get { return tc.Module; }
450 public string GetSignatureForError ()
452 return tc.GetSignatureForError ();
455 public ExtensionMethodCandidates LookupExtensionMethod (string name, int arity)
460 public FullNamedExpression LookupNamespaceAlias (string name)
462 return tc.Parent.LookupNamespaceAlias (name);
465 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
468 var tp = CurrentTypeParameters;
470 TypeParameter t = tp.Find (name);
472 return new TypeParameterExpr (t, loc);
476 return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc);
486 GetHashCode = 1 << 1,
487 HasStaticFieldInitializer = 1 << 2
490 readonly List<MemberCore> members;
492 // Holds a list of fields that have initializers
493 protected List<FieldInitializer> initialized_fields;
495 // Holds a list of static fields that have initializers
496 protected List<FieldInitializer> initialized_static_fields;
498 Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
500 Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
503 // Points to the first non-static field added to the container.
505 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
506 // and the first one's as good as any.
508 protected FieldBase first_nonstatic_field;
511 // This one is computed after we can distinguish interfaces
512 // from classes from the arraylist `type_bases'
514 protected TypeSpec base_type;
515 FullNamedExpression base_type_expr; // TODO: It's temporary variable
516 protected TypeSpec[] iface_exprs;
518 protected List<FullNamedExpression> type_bases;
520 // Partial parts for classes only
521 List<TypeDefinition> class_partial_parts;
523 TypeDefinition InTransit;
525 public TypeBuilder TypeBuilder;
526 GenericTypeParameterBuilder[] all_tp_builders;
528 // All recursive type parameters put together sharing same
529 // TypeParameter instances
531 TypeParameters all_type_parameters;
533 public const string DefaultIndexerName = "Item";
535 bool has_normal_indexers;
537 protected bool requires_delayed_unmanagedtype_check;
539 bool members_defined;
540 bool members_defined_ok;
541 protected bool has_static_constructor;
543 private CachedMethods cached_method;
545 protected TypeSpec spec;
546 TypeSpec current_type;
548 public int DynamicSitesCounter;
549 public int AnonymousMethodsCounter;
550 public int MethodGroupsCounter;
552 static readonly string[] attribute_targets = new [] { "type" };
553 static readonly string[] attribute_targets_primary = new [] { "type", "method" };
556 /// The pending methods that need to be implemented
557 // (interfaces or abstract methods)
559 PendingImplementation pending;
561 protected TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
562 : base (parent, name, attrs, kind)
564 PartialContainer = this;
565 members = new List<MemberCore> ();
570 public List<FullNamedExpression> BaseTypeExpressions {
576 public override TypeSpec CurrentType {
578 if (current_type == null) {
579 if (IsGenericOrParentIsGeneric) {
581 // Switch to inflated version as it's used by all expressions
583 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Types;
584 current_type = spec.MakeGenericType (this, targs);
594 public override TypeParameters CurrentTypeParameters {
596 return PartialContainer.MemberName.TypeParameters;
600 int CurrentTypeParametersStartIndex {
602 int total = all_tp_builders.Length;
603 if (CurrentTypeParameters != null) {
604 return total - CurrentTypeParameters.Count;
610 public virtual AssemblyDefinition DeclaringAssembly {
612 return Module.DeclaringAssembly;
616 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
618 return Module.DeclaringAssembly;
622 public TypeSpec Definition {
628 public bool HasMembersDefined {
630 return members_defined;
634 public bool HasInstanceConstructor {
636 return (caching_flags & Flags.HasInstanceConstructor) != 0;
639 caching_flags |= Flags.HasInstanceConstructor;
643 // Indicated whether container has StructLayout attribute set Explicit
644 public bool HasExplicitLayout {
645 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
646 set { caching_flags |= Flags.HasExplicitLayout; }
649 public bool HasOperators {
651 return (caching_flags & Flags.HasUserOperators) != 0;
654 caching_flags |= Flags.HasUserOperators;
658 public bool HasStructLayout {
659 get { return (caching_flags & Flags.HasStructLayout) != 0; }
660 set { caching_flags |= Flags.HasStructLayout; }
663 public TypeSpec[] Interfaces {
669 public bool IsGenericOrParentIsGeneric {
671 return all_type_parameters != null;
675 public bool IsTopLevel {
677 return !(Parent is TypeDefinition);
681 public bool IsPartial {
683 return (ModFlags & Modifiers.PARTIAL) != 0;
687 bool ITypeDefinition.IsTypeForwarder {
693 bool ITypeDefinition.IsCyclicTypeForwarder {
700 // Returns true for secondary partial containers
704 return PartialContainer != this;
708 public MemberCache MemberCache {
710 return spec.MemberCache;
714 public List<MemberCore> Members {
720 string ITypeDefinition.Namespace {
723 while (p.Kind != MemberKind.Namespace)
726 return p.MemberName == null ? null : p.GetSignatureForError ();
730 public ParametersCompiled PrimaryConstructorParameters { get; set; }
732 public Arguments PrimaryConstructorBaseArguments { get; set; }
734 public Location PrimaryConstructorBaseArgumentsStart { get; set; }
736 public TypeParameters TypeParametersAll {
738 return all_type_parameters;
742 public override string[] ValidAttributeTargets {
744 return PrimaryConstructorParameters != null ? attribute_targets_primary : attribute_targets;
750 public override void Accept (StructuralVisitor visitor)
752 visitor.Visit (this);
755 public void AddMember (MemberCore symbol)
757 if (symbol.MemberName.ExplicitInterface != null) {
758 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
759 Report.Error (541, symbol.Location,
760 "`{0}': explicit interface declaration can only be declared in a class or struct",
761 symbol.GetSignatureForError ());
765 AddNameToContainer (symbol, symbol.MemberName.Name);
766 members.Add (symbol);
769 public override void AddTypeContainer (TypeContainer tc)
771 AddNameToContainer (tc, tc.MemberName.Basename);
773 base.AddTypeContainer (tc);
776 protected override void AddTypeContainerMember (TypeContainer tc)
780 if (containers == null)
781 containers = new List<TypeContainer> ();
783 base.AddTypeContainerMember (tc);
787 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
789 public virtual void AddNameToContainer (MemberCore symbol, string name)
791 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
795 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
796 PartialContainer.defined_names.Add (name, symbol);
800 if (symbol.EnableOverloadChecks (mc))
803 InterfaceMemberBase im = mc as InterfaceMemberBase;
804 if (im != null && im.IsExplicitImpl)
807 Report.SymbolRelatedToPreviousError (mc);
808 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
809 Error_MissingPartialModifier (symbol);
813 if (symbol is TypeParameter) {
814 Report.Error (692, symbol.Location,
815 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
817 Report.Error (102, symbol.Location,
818 "The type `{0}' already contains a definition for `{1}'",
819 GetSignatureForError (), name);
825 public void AddConstructor (Constructor c)
827 AddConstructor (c, false);
830 public void AddConstructor (Constructor c, bool isDefault)
832 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
834 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
836 if (is_static && c.ParameterInfo.IsEmpty) {
837 PartialContainer.has_static_constructor = true;
839 PartialContainer.HasInstanceConstructor = true;
845 public bool AddField (FieldBase field)
849 if ((field.ModFlags & Modifiers.STATIC) != 0)
852 var first_field = PartialContainer.first_nonstatic_field;
853 if (first_field == null) {
854 PartialContainer.first_nonstatic_field = field;
858 if (Kind == MemberKind.Struct && first_field.Parent != field.Parent) {
859 Report.SymbolRelatedToPreviousError (first_field.Parent);
860 Report.Warning (282, 3, field.Location,
861 "struct instance field `{0}' found in different declaration from instance field `{1}'",
862 field.GetSignatureForError (), first_field.GetSignatureForError ());
868 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
870 public void AddIndexer (Indexer i)
875 public void AddOperator (Operator op)
877 PartialContainer.HasOperators = true;
881 public void AddPartialPart (TypeDefinition part)
883 if (Kind != MemberKind.Class)
886 if (class_partial_parts == null)
887 class_partial_parts = new List<TypeDefinition> ();
889 class_partial_parts.Add (part);
892 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
894 if (a.Target == AttributeTargets.Method) {
895 foreach (var m in members) {
896 var c = m as Constructor;
900 if (c.IsPrimaryConstructor) {
901 c.ApplyAttributeBuilder (a, ctor, cdata, pa);
906 throw new InternalErrorException ();
909 if (has_normal_indexers && a.Type == pa.DefaultMember) {
910 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
914 if (a.Type == pa.Required) {
915 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
919 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
922 public override AttributeTargets AttributeTargets {
924 throw new NotSupportedException ();
928 public TypeSpec BaseType {
930 return spec.BaseType;
934 protected virtual TypeAttributes TypeAttr {
936 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
940 public int TypeParametersCount {
942 return MemberName.Arity;
946 TypeParameterSpec[] ITypeDefinition.TypeParameters {
948 return PartialContainer.CurrentTypeParameters.Types;
952 public string GetAttributeDefaultMember ()
954 return indexer_name ?? DefaultIndexerName;
957 public bool IsComImport {
959 if (OptAttributes == null)
962 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
966 public void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
969 PartialContainer.RegisterFieldForInitialization (field, expression);
971 if ((field.ModFlags & Modifiers.STATIC) != 0){
972 if (initialized_static_fields == null) {
973 HasStaticFieldInitializer = true;
974 initialized_static_fields = new List<FieldInitializer> (4);
977 initialized_static_fields.Add (expression);
979 if (Kind == MemberKind.Struct) {
980 if (Compiler.Settings.Version != LanguageVersion.Experimental) {
981 Report.Error (573, expression.Location, "'{0}': Structs cannot have instance property or field initializers",
982 GetSignatureForError ());
986 if (initialized_fields == null)
987 initialized_fields = new List<FieldInitializer> (4);
989 initialized_fields.Add (expression);
993 public void ResolveFieldInitializers (BlockContext ec)
995 Debug.Assert (!IsPartialPart);
998 if (initialized_static_fields == null)
1001 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
1003 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
1004 for (i = 0; i < initialized_static_fields.Count; ++i) {
1005 FieldInitializer fi = initialized_static_fields [i];
1006 ExpressionStatement s = fi.ResolveStatement (ec);
1008 s = EmptyExpressionStatement.Instance;
1009 } else if (!fi.IsSideEffectFree) {
1010 has_complex_initializer = true;
1016 for (i = 0; i < initialized_static_fields.Count; ++i) {
1017 FieldInitializer fi = initialized_static_fields [i];
1019 // Need special check to not optimize code like this
1020 // static int a = b = 5;
1021 // static int b = 0;
1023 if (!has_complex_initializer && fi.IsDefaultInitializer)
1026 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1027 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
1033 if (initialized_fields == null)
1036 for (int i = 0; i < initialized_fields.Count; ++i) {
1037 FieldInitializer fi = initialized_fields [i];
1040 // Clone before resolving otherwise when field initializer is needed
1041 // in more than 1 constructor any resolve after the initial one would
1042 // only took the resolved expression which is problem for expressions
1043 // that generate extra expressions or code during Resolve phase
1045 var cloned = fi.Clone (new CloneContext ());
1047 ExpressionStatement s = fi.ResolveStatement (ec);
1049 initialized_fields [i] = new FieldInitializer (fi.Field, ErrorExpression.Instance, Location.Null);
1054 // Field is re-initialized to its default value => removed
1056 if (fi.IsDefaultInitializer && Kind != MemberKind.Struct && ec.Module.Compiler.Settings.Optimize)
1059 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1060 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
1061 initialized_fields [i] = (FieldInitializer) cloned;
1065 public override string DocComment {
1077 public PendingImplementation PendingImplementations {
1078 get { return pending; }
1081 internal override void GenerateDocComment (DocumentationBuilder builder)
1086 base.GenerateDocComment (builder);
1088 foreach (var member in members)
1089 member.GenerateDocComment (builder);
1092 public TypeSpec GetAttributeCoClass ()
1094 if (OptAttributes == null)
1097 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
1101 return a.GetCoClassAttributeValue ();
1104 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1107 if (OptAttributes != null) {
1108 a = OptAttributes.Search (pa);
1114 return a.GetAttributeUsageAttribute ();
1117 public virtual CompilationSourceFile GetCompilationSourceFile ()
1119 TypeContainer ns = Parent;
1121 var sf = ns as CompilationSourceFile;
1129 public virtual void SetBaseTypes (List<FullNamedExpression> baseTypes)
1131 type_bases = baseTypes;
1135 /// This function computes the Base class and also the
1136 /// list of interfaces that the class or struct @c implements.
1138 /// The return value is an array (might be null) of
1139 /// interfaces implemented (as Types).
1141 /// The @base_class argument is set to the base object or null
1142 /// if this is `System.Object'.
1144 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1147 if (type_bases == null)
1150 int count = type_bases.Count;
1151 TypeSpec[] ifaces = null;
1152 var base_context = new BaseContext (this);
1153 for (int i = 0, j = 0; i < count; i++){
1154 FullNamedExpression fne = type_bases [i];
1156 var fne_resolved = fne.ResolveAsType (base_context);
1157 if (fne_resolved == null)
1160 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1161 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1162 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1163 GetSignatureForError ());
1168 base_type = fne_resolved;
1174 ifaces = new TypeSpec [count - i];
1176 if (fne_resolved.IsInterface) {
1177 for (int ii = 0; ii < j; ++ii) {
1178 if (fne_resolved == ifaces [ii]) {
1179 Report.Error (528, Location, "`{0}' is already listed in interface list",
1180 fne_resolved.GetSignatureForError ());
1185 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1186 Report.Error (61, fne.Location,
1187 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1188 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1191 Report.SymbolRelatedToPreviousError (fne_resolved);
1192 if (Kind != MemberKind.Class) {
1193 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1194 } else if (base_class != null)
1195 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1196 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1198 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1199 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1203 ifaces [j++] = fne_resolved;
1210 // Checks that some operators come in pairs:
1216 // They are matched based on the return type and the argument types
1218 void CheckPairedOperators ()
1220 bool has_equality_or_inequality = false;
1221 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1223 for (int i = 0; i < members.Count; ++i) {
1224 var o_a = members[i] as Operator;
1228 var o_type = o_a.OperatorType;
1229 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1230 has_equality_or_inequality = true;
1232 if (found_matched.Contains (o_type))
1235 var matching_type = o_a.GetMatchingOperator ();
1236 if (matching_type == Operator.OpType.TOP) {
1240 bool pair_found = false;
1241 for (int ii = 0; ii < members.Count; ++ii) {
1242 var o_b = members[ii] as Operator;
1243 if (o_b == null || o_b.OperatorType != matching_type)
1246 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1249 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1252 found_matched.Add (matching_type);
1258 Report.Error (216, o_a.Location,
1259 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1260 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1264 if (has_equality_or_inequality) {
1266 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1267 GetSignatureForError ());
1269 if (!HasGetHashCode)
1270 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1271 GetSignatureForError ());
1275 public override void CreateMetadataName (StringBuilder sb)
1277 if (Parent.MemberName != null) {
1278 Parent.CreateMetadataName (sb);
1280 if (sb.Length != 0) {
1285 sb.Append (MemberName.Basename);
1288 bool CreateTypeBuilder ()
1291 // Sets .size to 1 for structs with no instance fields
1293 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null && !(this is StateMachine) ? 1 : 0;
1295 var parent_def = Parent as TypeDefinition;
1296 if (parent_def == null) {
1297 var sb = new StringBuilder ();
1298 CreateMetadataName (sb);
1299 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1301 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (FilterNestedName (MemberName.Basename), TypeAttr, null, type_size);
1304 if (DeclaringAssembly.Importer != null)
1305 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1307 spec.SetMetaInfo (TypeBuilder);
1308 spec.MemberCache = new MemberCache (this);
1310 TypeParameters parentAllTypeParameters = null;
1311 if (parent_def != null) {
1312 spec.DeclaringType = Parent.CurrentType;
1313 parent_def.MemberCache.AddMember (spec);
1314 parentAllTypeParameters = parent_def.all_type_parameters;
1317 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1318 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1320 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1322 if (CurrentTypeParameters != null) {
1323 CurrentTypeParameters.Create (spec, CurrentTypeParametersStartIndex, this);
1324 CurrentTypeParameters.Define (all_tp_builders);
1331 public static string FilterNestedName (string name)
1334 // SRE API does not handle namespaces and types separately but
1335 // determine that from '.' in name. That's problematic because
1336 // dot is valid character for type name. By replacing any '.'
1337 // in name we avoid any ambiguities and never emit metadata
1338 // namespace for nested types
1340 return name.Replace ('.', '_');
1343 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1346 int parent_offset = 0;
1347 if (parentAllTypeParameters != null) {
1348 if (CurrentTypeParameters == null) {
1349 all_type_parameters = parentAllTypeParameters;
1350 return parentAllTypeParameters.GetAllNames ();
1353 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1354 all_type_parameters = new TypeParameters (names.Length);
1355 all_type_parameters.Add (parentAllTypeParameters);
1357 parent_offset = all_type_parameters.Count;
1358 for (int i = 0; i < parent_offset; ++i)
1359 names[i] = all_type_parameters[i].MemberName.Name;
1362 names = new string[CurrentTypeParameters.Count];
1365 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1366 if (all_type_parameters != null)
1367 all_type_parameters.Add (MemberName.TypeParameters[i]);
1369 var name = CurrentTypeParameters[i].MemberName.Name;
1370 names[parent_offset + i] = name;
1371 for (int ii = 0; ii < parent_offset + i; ++ii) {
1372 if (names[ii] != name)
1375 var tp = CurrentTypeParameters[i];
1376 var conflict = all_type_parameters[ii];
1378 tp.WarningParentNameConflict (conflict);
1382 if (all_type_parameters == null)
1383 all_type_parameters = CurrentTypeParameters;
1389 public SourceMethodBuilder CreateMethodSymbolEntry ()
1391 if (Module.DeclaringAssembly.SymbolWriter == null || (ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1394 var source_file = GetCompilationSourceFile ();
1395 if (source_file == null)
1398 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1402 // Creates a proxy base method call inside this container for hoisted base member calls
1404 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1406 Method proxy_method;
1409 // One proxy per base method is enough
1411 if (hoisted_base_call_proxies == null) {
1412 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1413 proxy_method = null;
1415 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1418 if (proxy_method == null) {
1419 string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1421 MemberName member_name;
1422 TypeArguments targs = null;
1423 TypeSpec return_type = method.ReturnType;
1424 var local_param_types = method.Parameters.Types;
1426 if (method.IsGeneric) {
1428 // Copy all base generic method type parameters info
1430 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1431 var tparams = new TypeParameters ();
1433 targs = new TypeArguments ();
1434 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1435 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1436 var tp = hoisted_tparams[i];
1437 var local_tp = new TypeParameter (tp, null, new MemberName (tp.Name, Location), null);
1438 tparams.Add (local_tp);
1440 targs.Add (new SimpleName (tp.Name, Location));
1441 targs.Arguments[i] = local_tp.Type;
1444 member_name = new MemberName (name, tparams, Location);
1447 // Mutate any method type parameters from original
1448 // to newly created hoisted version
1450 var mutator = new TypeParameterMutator (hoisted_tparams, tparams);
1451 return_type = mutator.Mutate (return_type);
1452 local_param_types = mutator.Mutate (local_param_types);
1454 member_name = new MemberName (name);
1457 var base_parameters = new Parameter[method.Parameters.Count];
1458 for (int i = 0; i < base_parameters.Length; ++i) {
1459 var base_param = method.Parameters.FixedParameters[i];
1460 base_parameters[i] = new Parameter (new TypeExpression (local_param_types [i], Location),
1461 base_param.Name, base_param.ModFlags, null, Location);
1462 base_parameters[i].Resolve (this, i);
1465 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
1466 if (method.Parameters.HasArglist) {
1467 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1468 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1471 // Compiler generated proxy
1472 proxy_method = new Method (this, new TypeExpression (return_type, Location),
1473 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1474 member_name, cloned_params, null);
1476 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1477 IsCompilerGenerated = true
1480 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1481 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1483 mg.SetTypeArguments (rc, targs);
1485 // Get all the method parameters and pass them as arguments
1486 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1487 Statement statement;
1488 if (method.ReturnType.Kind == MemberKind.Void)
1489 statement = new StatementExpression (real_base_call);
1491 statement = new Return (real_base_call, Location);
1493 block.AddStatement (statement);
1494 proxy_method.Block = block;
1496 members.Add (proxy_method);
1497 proxy_method.Define ();
1498 proxy_method.PrepareEmit ();
1500 hoisted_base_call_proxies.Add (method, proxy_method);
1503 return proxy_method.Spec;
1506 protected bool DefineBaseTypes ()
1508 if (IsPartialPart && Kind == MemberKind.Class)
1511 return DoDefineBaseType ();
1514 bool DoDefineBaseType ()
1516 iface_exprs = ResolveBaseTypes (out base_type_expr);
1519 if (IsPartialPart) {
1520 set_base_type = false;
1522 if (base_type_expr != null) {
1523 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1524 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1525 Report.Error (263, Location,
1526 "Partial declarations of `{0}' must not specify different base classes",
1527 GetSignatureForError ());
1529 PartialContainer.base_type_expr = base_type_expr;
1530 PartialContainer.base_type = base_type;
1531 set_base_type = true;
1535 if (iface_exprs != null) {
1536 if (PartialContainer.iface_exprs == null)
1537 PartialContainer.iface_exprs = iface_exprs;
1539 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1540 foreach (var iface_partial in iface_exprs) {
1541 if (ifaces.Contains (iface_partial))
1544 ifaces.Add (iface_partial);
1547 PartialContainer.iface_exprs = ifaces.ToArray ();
1551 PartialContainer.members.AddRange (members);
1552 if (containers != null) {
1553 if (PartialContainer.containers == null)
1554 PartialContainer.containers = new List<TypeContainer> ();
1556 PartialContainer.containers.AddRange (containers);
1559 if (PrimaryConstructorParameters != null) {
1560 if (PartialContainer.PrimaryConstructorParameters != null) {
1561 Report.Error (8036, Location, "Only one part of a partial type can declare primary constructor parameters");
1563 PartialContainer.PrimaryConstructorParameters = PrimaryConstructorParameters;
1567 members_defined = members_defined_ok = true;
1568 caching_flags |= Flags.CloseTypeCreated;
1570 set_base_type = true;
1573 var cycle = CheckRecursiveDefinition (this);
1574 if (cycle != null) {
1575 Report.SymbolRelatedToPreviousError (cycle);
1576 if (this is Interface) {
1577 Report.Error (529, Location,
1578 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1579 GetSignatureForError (), cycle.GetSignatureForError ());
1582 PartialContainer.iface_exprs = null;
1584 Report.Error (146, Location,
1585 "Circular base class dependency involving `{0}' and `{1}'",
1586 GetSignatureForError (), cycle.GetSignatureForError ());
1589 PartialContainer.base_type = null;
1593 if (iface_exprs != null) {
1594 if (!PrimaryConstructorBaseArgumentsStart.IsNull) {
1595 Report.Error (8049, PrimaryConstructorBaseArgumentsStart, "Implemented interfaces cannot have arguments");
1598 foreach (var iface_type in iface_exprs) {
1599 // Prevents a crash, the interface might not have been resolved: 442144
1600 if (iface_type == null)
1603 if (!spec.AddInterfaceDefined (iface_type))
1606 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1610 if (Kind == MemberKind.Interface) {
1611 spec.BaseType = Compiler.BuiltinTypes.Object;
1615 if (set_base_type) {
1620 // Base type of partial container has to be resolved before we
1621 // resolve any nested types of the container. We need to know
1622 // partial parts because the base type can be specified in file
1623 // defined after current container
1625 if (class_partial_parts != null) {
1626 foreach (var pp in class_partial_parts) {
1627 if (pp.PrimaryConstructorBaseArguments != null)
1628 PrimaryConstructorBaseArguments = pp.PrimaryConstructorBaseArguments;
1630 pp.DoDefineBaseType ();
1640 if (base_type == null) {
1641 TypeBuilder.SetParent (null);
1645 if (spec.BaseType == base_type)
1648 spec.BaseType = base_type;
1651 spec.UpdateInflatedInstancesBaseType ();
1653 // Set base type after type creation
1654 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1657 public override void ExpandBaseInterfaces ()
1660 DoExpandBaseInterfaces ();
1662 base.ExpandBaseInterfaces ();
1665 public void DoExpandBaseInterfaces ()
1667 if ((caching_flags & Flags.InterfacesExpanded) != 0)
1670 caching_flags |= Flags.InterfacesExpanded;
1673 // Expand base interfaces. It cannot be done earlier because all partial
1674 // interface parts need to be defined before the type they are used from
1676 if (iface_exprs != null) {
1677 foreach (var iface in iface_exprs) {
1681 var td = iface.MemberDefinition as TypeDefinition;
1683 td.DoExpandBaseInterfaces ();
1685 if (iface.Interfaces == null)
1688 foreach (var biface in iface.Interfaces) {
1689 if (spec.AddInterfaceDefined (biface)) {
1690 TypeBuilder.AddInterfaceImplementation (biface.GetMetaInfo ());
1697 // Include all base type interfaces too, see ImportTypeBase for details
1699 if (base_type != null) {
1700 var td = base_type.MemberDefinition as TypeDefinition;
1702 td.DoExpandBaseInterfaces ();
1705 // Simply use base interfaces only, they are all expanded which makes
1706 // it easy to handle generic type argument propagation with single
1709 // interface IA<T> : IB<T>
1710 // interface IB<U> : IC<U>
1713 if (base_type.Interfaces != null) {
1714 foreach (var iface in base_type.Interfaces) {
1715 spec.AddInterfaceDefined (iface);
1721 public override void PrepareEmit ()
1723 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1726 foreach (var member in members) {
1727 var pbm = member as PropertyBasedMember;
1731 var pm = member as IParametersMember;
1733 var mc = member as MethodOrOperator;
1738 var p = pm.Parameters;
1742 ((ParametersCompiled) p).ResolveDefaultValues (member);
1746 var c = member as Const;
1751 base.PrepareEmit ();
1755 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1757 public override bool CreateContainer ()
1759 if (TypeBuilder != null)
1765 if (IsPartialPart) {
1766 spec = PartialContainer.spec;
1767 TypeBuilder = PartialContainer.TypeBuilder;
1768 all_tp_builders = PartialContainer.all_tp_builders;
1769 all_type_parameters = PartialContainer.all_type_parameters;
1771 if (!CreateTypeBuilder ()) {
1777 return base.CreateContainer ();
1780 protected override void DoDefineContainer ()
1784 DoResolveTypeParameters ();
1788 // Replaces normal spec with predefined one when compiling corlib
1789 // and this type container defines predefined type
1791 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1793 // When compiling build-in types we start with two
1794 // version of same type. One is of BuiltinTypeSpec and
1795 // second one is ordinary TypeSpec. The unification
1796 // happens at later stage when we know which type
1797 // really matches the builtin type signature. However
1798 // that means TypeSpec create during CreateType of this
1799 // type has to be replaced with builtin one
1801 spec.SetMetaInfo (TypeBuilder);
1802 spec.MemberCache = this.spec.MemberCache;
1803 spec.DeclaringType = this.spec.DeclaringType;
1806 current_type = null;
1809 public override void RemoveContainer (TypeContainer cont)
1811 base.RemoveContainer (cont);
1812 Members.Remove (cont);
1813 Cache.Remove (cont.MemberName.Basename);
1816 protected virtual bool DoResolveTypeParameters ()
1818 var tparams = MemberName.TypeParameters;
1819 if (tparams == null)
1822 var base_context = new BaseContext (this);
1823 for (int i = 0; i < tparams.Count; ++i) {
1824 var tp = tparams[i];
1826 if (!tp.ResolveConstraints (base_context)) {
1831 if (IsPartialPart) {
1832 var pc_tp = PartialContainer.CurrentTypeParameters [i];
1834 tp.Create (spec, this);
1837 if (tp.OptAttributes != null) {
1838 if (pc_tp.OptAttributes == null)
1839 pc_tp.OptAttributes = tp.OptAttributes;
1841 pc_tp.OptAttributes.Attrs.AddRange (tp.OptAttributes.Attrs);
1846 if (IsPartialPart) {
1847 PartialContainer.CurrentTypeParameters.UpdateConstraints (this);
1853 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1855 if (InTransit != null)
1860 if (base_type != null) {
1861 var ptc = base_type.MemberDefinition as TypeDefinition;
1862 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1866 if (iface_exprs != null) {
1867 foreach (var iface in iface_exprs) {
1868 // the interface might not have been resolved, prevents a crash, see #442144
1871 var ptc = iface.MemberDefinition as Interface;
1872 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1877 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1885 /// Populates our TypeBuilder with fields and methods
1887 public sealed override bool Define ()
1889 if (members_defined)
1890 return members_defined_ok;
1892 members_defined_ok = DoDefineMembers ();
1893 members_defined = true;
1897 return members_defined_ok;
1900 protected virtual bool DoDefineMembers ()
1902 Debug.Assert (!IsPartialPart);
1904 if (iface_exprs != null) {
1905 foreach (var iface_type in iface_exprs) {
1906 if (iface_type == null)
1909 // Ensure the base is always setup
1910 var compiled_iface = iface_type.MemberDefinition as Interface;
1911 if (compiled_iface != null)
1912 compiled_iface.Define ();
1914 ObsoleteAttribute oa = iface_type.GetAttributeObsolete ();
1915 if (oa != null && !IsObsolete)
1916 AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report);
1918 if (iface_type.Arity > 0) {
1919 // TODO: passing `this' is wrong, should be base type iface instead
1920 VarianceDecl.CheckTypeVariance (iface_type, Variance.Covariant, this);
1922 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1923 Report.Error (1966, Location,
1924 "`{0}': cannot implement a dynamic interface `{1}'",
1925 GetSignatureForError (), iface_type.GetSignatureForError ());
1930 if (iface_type.IsGenericOrParentIsGeneric) {
1931 foreach (var prev_iface in iface_exprs) {
1932 if (prev_iface == iface_type || prev_iface == null)
1935 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1938 Report.Error (695, Location,
1939 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1940 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1945 if (Kind == MemberKind.Interface) {
1946 foreach (var iface in spec.Interfaces) {
1947 MemberCache.AddInterface (iface);
1952 if (base_type != null) {
1954 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1956 if (base_type_expr != null) {
1957 ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
1958 if (obsolete_attr != null && !IsObsolete)
1959 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report);
1961 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1962 Report.Error (698, base_type_expr.Location,
1963 "A generic type cannot derive from `{0}' because it is an attribute class",
1964 base_type.GetSignatureForError ());
1968 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1969 if (baseContainer != null) {
1970 baseContainer.Define ();
1973 // It can trigger define of this type (for generic types only)
1975 if (HasMembersDefined)
1980 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1981 pending = PendingImplementation.GetPendingImplementations (this);
1984 var count = members.Count;
1985 for (int i = 0; i < count; ++i) {
1986 var mc = members[i] as InterfaceMemberBase;
1987 if (mc == null || !mc.IsExplicitImpl)
1992 } catch (Exception e) {
1993 throw new InternalErrorException (mc, e);
1997 for (int i = 0; i < count; ++i) {
1998 var mc = members[i] as InterfaceMemberBase;
1999 if (mc != null && mc.IsExplicitImpl)
2002 if (members[i] is TypeContainer)
2006 members[i].Define ();
2007 } catch (Exception e) {
2008 throw new InternalErrorException (members[i], e);
2013 CheckPairedOperators ();
2016 if (requires_delayed_unmanagedtype_check) {
2017 requires_delayed_unmanagedtype_check = false;
2018 foreach (var member in members) {
2019 var f = member as Field;
2020 if (f != null && f.MemberType != null && f.MemberType.IsPointer)
2021 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
2025 ComputeIndexerName();
2027 if (HasEquals && !HasGetHashCode) {
2028 Report.Warning (659, 3, Location,
2029 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
2032 if (Kind == MemberKind.Interface && iface_exprs != null) {
2033 MemberCache.RemoveHiddenMembers (spec);
2039 void ComputeIndexerName ()
2041 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
2042 if (indexers == null)
2045 string class_indexer_name = null;
2048 // Check normal indexers for consistent name, explicit interface implementation
2049 // indexers are ignored
2051 foreach (var indexer in indexers) {
2053 // FindMembers can return unfiltered full hierarchy names
2055 if (indexer.DeclaringType != spec)
2058 has_normal_indexers = true;
2060 if (class_indexer_name == null) {
2061 indexer_name = class_indexer_name = indexer.Name;
2065 if (indexer.Name != class_indexer_name)
2066 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
2067 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
2071 void EmitIndexerName ()
2073 if (!has_normal_indexers)
2076 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
2080 var encoder = new AttributeEncoder ();
2081 encoder.Encode (GetAttributeDefaultMember ());
2082 encoder.EncodeEmptyNamedArguments ();
2084 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2087 public override void VerifyMembers ()
2090 // Check for internal or private fields that were never assigned
2092 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
2093 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
2094 foreach (var member in members) {
2095 if (member is Event) {
2097 // An event can be assigned from same class only, report
2098 // this warning for all accessibility modes
2100 if (!member.IsUsed && !PartialContainer.HasStructLayout)
2101 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
2106 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
2107 if (is_type_exposed)
2110 member.SetIsUsed ();
2113 var f = member as Field;
2117 if (!member.IsUsed) {
2118 if (!PartialContainer.HasStructLayout) {
2119 if ((member.caching_flags & Flags.IsAssigned) == 0) {
2120 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
2122 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
2123 member.GetSignatureForError ());
2130 if ((f.caching_flags & Flags.IsAssigned) != 0)
2134 // Only report 649 on level 4
2136 if (Compiler.Settings.WarningLevel < 4)
2140 // Don't be pedantic when type requires specific layout
2142 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2145 Constant c = New.Constantify (f.MemberType, f.Location);
2148 value = c.GetValueAsLiteral ();
2149 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
2156 value = " `" + value + "'";
2158 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
2159 f.GetSignatureForError (), value);
2163 base.VerifyMembers ();
2166 public override void Emit ()
2168 if (OptAttributes != null)
2169 OptAttributes.Emit ();
2171 if (!IsCompilerGenerated) {
2173 MemberSpec candidate;
2174 bool overrides = false;
2175 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
2176 if (conflict_symbol == null && candidate == null) {
2177 if ((ModFlags & Modifiers.NEW) != 0)
2178 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
2179 GetSignatureForError ());
2181 if ((ModFlags & Modifiers.NEW) == 0) {
2182 if (candidate == null)
2183 candidate = conflict_symbol;
2185 Report.SymbolRelatedToPreviousError (candidate);
2186 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
2187 GetSignatureForError (), candidate.GetSignatureForError ());
2192 // Run constraints check on all possible generic types
2193 if (base_type != null && base_type_expr != null) {
2194 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
2197 if (iface_exprs != null) {
2198 foreach (var iface_type in iface_exprs) {
2199 if (iface_type == null)
2202 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2207 if (all_tp_builders != null) {
2208 int current_starts_index = CurrentTypeParametersStartIndex;
2209 for (int i = 0; i < all_tp_builders.Length; i++) {
2210 if (i < current_starts_index) {
2211 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2213 var tp = CurrentTypeParameters [i - current_starts_index];
2214 tp.CheckGenericConstraints (!IsObsolete);
2220 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2221 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2224 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2225 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2230 for (int i = 0; i < members.Count; i++) {
2232 if ((m.caching_flags & Flags.CloseTypeCreated) != 0)
2239 CheckAttributeClsCompliance ();
2241 if (pending != null)
2242 pending.VerifyPendingMethods ();
2246 void CheckAttributeClsCompliance ()
2248 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2251 foreach (var m in members) {
2252 var c = m as Constructor;
2256 if (c.HasCompliantArgs)
2260 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2263 public sealed override void EmitContainer ()
2265 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2271 public override void CloseContainer ()
2273 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2276 // Close base type container first to avoid TypeLoadException
2277 if (spec.BaseType != null) {
2278 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2279 if (btype != null) {
2280 btype.CloseContainer ();
2282 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2288 caching_flags |= Flags.CloseTypeCreated;
2289 TypeBuilder.CreateType ();
2290 } catch (TypeLoadException) {
2292 // This is fine, the code still created the type
2294 } catch (Exception e) {
2295 throw new InternalErrorException (this, e);
2298 base.CloseContainer ();
2301 initialized_fields = null;
2302 initialized_static_fields = null;
2304 OptAttributes = null;
2308 // Performs the validation on a Method's modifiers (properties have
2309 // the same properties).
2311 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2313 public bool MethodModifiersValid (MemberCore mc)
2315 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2316 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2318 var flags = mc.ModFlags;
2321 // At most one of static, virtual or override
2323 if ((flags & Modifiers.STATIC) != 0){
2324 if ((flags & vao) != 0){
2325 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2326 mc.GetSignatureForError ());
2331 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2332 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2333 mc.GetSignatureForError ());
2338 // If the declaration includes the abstract modifier, then the
2339 // declaration does not include static, virtual or extern
2341 if ((flags & Modifiers.ABSTRACT) != 0){
2342 if ((flags & Modifiers.EXTERN) != 0){
2344 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2348 if ((flags & Modifiers.SEALED) != 0) {
2349 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2353 if ((flags & Modifiers.VIRTUAL) != 0){
2354 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2358 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2359 Report.SymbolRelatedToPreviousError (this);
2360 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2361 mc.GetSignatureForError (), GetSignatureForError ());
2366 if ((flags & Modifiers.PRIVATE) != 0){
2367 if ((flags & vao) != 0){
2368 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2373 if ((flags & Modifiers.SEALED) != 0){
2374 if ((flags & Modifiers.OVERRIDE) == 0){
2375 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2383 protected override bool VerifyClsCompliance ()
2385 if (!base.VerifyClsCompliance ())
2388 // Check all container names for user classes
2389 if (Kind != MemberKind.Delegate)
2390 MemberCache.VerifyClsCompliance (Definition, Report);
2392 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2393 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2394 GetSignatureForError (), BaseType.GetSignatureForError ());
2400 /// Performs checks for an explicit interface implementation. First it
2401 /// checks whether the `interface_type' is a base inteface implementation.
2402 /// Then it checks whether `name' exists in the interface type.
2404 public bool VerifyImplements (InterfaceMemberBase mb)
2406 var ifaces = PartialContainer.Interfaces;
2407 if (ifaces != null) {
2408 foreach (TypeSpec t in ifaces){
2409 if (t == mb.InterfaceType)
2412 var expanded_base = t.Interfaces;
2413 if (expanded_base == null)
2416 foreach (var bt in expanded_base) {
2417 if (bt == mb.InterfaceType)
2423 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2424 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2425 mb.GetSignatureForError (), mb.InterfaceType.GetSignatureForError ());
2430 // Used for visiblity checks to tests whether this definition shares
2431 // base type baseType, it does member-definition search
2433 public bool IsBaseTypeDefinition (TypeSpec baseType)
2435 // RootContext check
2436 if (TypeBuilder == null)
2441 if (type.MemberDefinition == baseType.MemberDefinition)
2444 type = type.BaseType;
2445 } while (type != null);
2450 public override bool IsClsComplianceRequired ()
2453 return PartialContainer.IsClsComplianceRequired ();
2455 return base.IsClsComplianceRequired ();
2458 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2460 return Module.DeclaringAssembly == assembly;
2463 public virtual bool IsUnmanagedType ()
2468 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2470 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2474 // Public function used to locate types.
2476 // Returns: Type or null if they type can not be found.
2478 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2480 FullNamedExpression e;
2481 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2487 var tp = CurrentTypeParameters;
2489 TypeParameter tparam = tp.Find (name);
2491 e = new TypeParameterExpr (tparam, Location.Null);
2496 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2498 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2499 e = new TypeExpression (t, Location.Null);
2501 var errors = Compiler.Report.Errors;
2502 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2504 // TODO: LookupNamespaceOrType does more than just lookup. The result
2505 // cannot be cached or the error reporting won't happen
2506 if (errors != Compiler.Report.Errors)
2511 // TODO MemberCache: How to cache arity stuff ?
2512 if (arity == 0 && mode == LookupMode.Normal)
2518 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2520 // Has any nested type
2521 // Does not work, because base type can have
2522 //if (PartialContainer.Types == null)
2525 var container = PartialContainer.CurrentType;
2526 return MemberCache.FindNestedType (container, name, arity);
2529 public void Mark_HasEquals ()
2531 cached_method |= CachedMethods.Equals;
2534 public void Mark_HasGetHashCode ()
2536 cached_method |= CachedMethods.GetHashCode;
2539 public override void WriteDebugSymbol (MonoSymbolFile file)
2544 foreach (var m in members) {
2545 m.WriteDebugSymbol (file);
2550 /// Method container contains Equals method
2552 public bool HasEquals {
2554 return (cached_method & CachedMethods.Equals) != 0;
2559 /// Method container contains GetHashCode method
2561 public bool HasGetHashCode {
2563 return (cached_method & CachedMethods.GetHashCode) != 0;
2567 public bool HasStaticFieldInitializer {
2569 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2573 cached_method |= CachedMethods.HasStaticFieldInitializer;
2575 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2579 public override string DocCommentHeader {
2580 get { return "T:"; }
2584 public abstract class ClassOrStruct : TypeDefinition
2586 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2588 SecurityType declarative_security;
2589 protected Constructor generated_primary_constructor;
2591 protected ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2592 : base (parent, name, attrs, kind)
2596 public ToplevelBlock PrimaryConstructorBlock { get; set; }
2598 protected override TypeAttributes TypeAttr {
2600 TypeAttributes ta = base.TypeAttr;
2601 if (!has_static_constructor)
2602 ta |= TypeAttributes.BeforeFieldInit;
2604 if (Kind == MemberKind.Class) {
2605 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2607 ta |= StaticClassAttribute;
2609 ta |= TypeAttributes.SequentialLayout;
2616 public override void AddNameToContainer (MemberCore symbol, string name)
2618 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2619 if (symbol is TypeParameter) {
2620 Report.Error (694, symbol.Location,
2621 "Type parameter `{0}' has same name as containing type, or method",
2622 symbol.GetSignatureForError ());
2626 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2627 if (imb == null || !imb.IsExplicitImpl) {
2628 Report.SymbolRelatedToPreviousError (this);
2629 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2630 symbol.GetSignatureForError ());
2635 base.AddNameToContainer (symbol, name);
2638 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2640 if (a.IsValidSecurityAttribute ()) {
2641 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2645 if (a.Type == pa.StructLayout) {
2646 PartialContainer.HasStructLayout = true;
2647 if (a.IsExplicitLayoutKind ())
2648 PartialContainer.HasExplicitLayout = true;
2651 if (a.Type == pa.Dynamic) {
2652 a.Error_MisusedDynamicAttribute ();
2656 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2660 /// Defines the default constructors
2662 protected virtual Constructor DefineDefaultConstructor (bool is_static)
2664 // The default instance constructor is public
2665 // If the class is abstract, the default constructor is protected
2666 // The default static constructor is private
2669 ParametersCompiled parameters = null;
2671 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2672 parameters = ParametersCompiled.EmptyReadOnlyParameters;
2674 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2675 parameters = PrimaryConstructorParameters ?? ParametersCompiled.EmptyReadOnlyParameters;
2678 var c = new Constructor (this, MemberName.Name, mods, null, parameters, Location);
2679 if (Kind == MemberKind.Class)
2680 c.Initializer = new GeneratedBaseInitializer (Location, PrimaryConstructorBaseArguments);
2682 if (PrimaryConstructorParameters != null && !is_static) {
2683 c.IsPrimaryConstructor = true;
2684 c.caching_flags |= Flags.MethodOverloadsExist;
2687 AddConstructor (c, true);
2688 if (PrimaryConstructorBlock == null) {
2689 c.Block = new ToplevelBlock (Compiler, parameters, Location) {
2690 IsCompilerGenerated = true
2693 c.Block = PrimaryConstructorBlock;
2699 protected override bool DoDefineMembers ()
2701 CheckProtectedModifier ();
2703 if (PrimaryConstructorParameters != null) {
2705 foreach (Parameter p in PrimaryConstructorParameters.FixedParameters) {
2706 if (p.Name == MemberName.Name) {
2707 Report.Error (8039, p.Location, "Primary constructor of type `{0}' has parameter of same name as containing type",
2708 GetSignatureForError ());
2711 if (CurrentTypeParameters != null) {
2712 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
2713 var tp = CurrentTypeParameters [i];
2714 if (p.Name == tp.Name) {
2715 Report.Error (8038, p.Location, "Primary constructor of type `{0}' has parameter of same name as type parameter `{1}'",
2716 GetSignatureForError (), p.GetSignatureForError ());
2723 base.DoDefineMembers ();
2728 public override void Emit ()
2730 if (!has_static_constructor && HasStaticFieldInitializer) {
2731 var c = DefineDefaultConstructor (true);
2737 if (declarative_security != null) {
2738 foreach (var de in declarative_security) {
2740 TypeBuilder.__AddDeclarativeSecurity (de);
2742 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2750 public sealed class Class : ClassOrStruct
2752 const Modifiers AllowedModifiers =
2755 Modifiers.PROTECTED |
2756 Modifiers.INTERNAL |
2758 Modifiers.ABSTRACT |
2763 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2764 : base (parent, name, attrs, MemberKind.Class)
2766 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2767 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2768 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2771 public override void Accept (StructuralVisitor visitor)
2773 visitor.Visit (this);
2776 public override void SetBaseTypes (List<FullNamedExpression> baseTypes)
2778 var pmn = MemberName;
2779 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2780 Report.Error (537, Location,
2781 "The class System.Object cannot have a base class or implement an interface.");
2783 base.SetBaseTypes (baseTypes);
2786 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2788 if (a.Type == pa.AttributeUsage) {
2789 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2790 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2794 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2795 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2799 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2800 a.Error_MissingGuidAttribute ();
2804 if (a.Type == pa.Extension) {
2805 a.Error_MisusedExtensionAttribute ();
2809 if (a.Type.IsConditionallyExcluded (this))
2812 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2815 public override AttributeTargets AttributeTargets {
2817 return AttributeTargets.Class;
2821 protected override bool DoDefineMembers ()
2823 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2824 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2827 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2828 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2832 if (PrimaryConstructorParameters != null) {
2833 Report.Error (-800, Location, "`{0}': Static classes cannot have primary constructor", GetSignatureForError ());
2834 PrimaryConstructorParameters = null;
2837 foreach (var m in Members) {
2838 if (m is Operator) {
2839 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2843 if (m is Destructor) {
2844 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2849 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2853 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2856 if (m is Constructor) {
2857 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2861 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2864 if (!PartialContainer.HasInstanceConstructor || PrimaryConstructorParameters != null)
2865 generated_primary_constructor = DefineDefaultConstructor (false);
2868 return base.DoDefineMembers ();
2871 public override void Emit ()
2875 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2876 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2878 if (base_type != null && base_type.HasDynamicElement) {
2879 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2883 public override void GetCompletionStartingWith (string prefix, List<string> results)
2885 base.GetCompletionStartingWith (prefix, results);
2888 while (bt != null) {
2889 results.AddRange (MemberCache.GetCompletitionMembers (this, bt, prefix).Where (l => l.IsStatic).Select (l => l.Name));
2894 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2896 var ifaces = base.ResolveBaseTypes (out base_class);
2898 if (base_class == null) {
2899 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2900 base_type = Compiler.BuiltinTypes.Object;
2902 if (base_type.IsGenericParameter){
2903 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2904 GetSignatureForError (), base_type.GetSignatureForError ());
2905 } else if (base_type.IsStatic) {
2906 Report.SymbolRelatedToPreviousError (base_type);
2907 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2908 GetSignatureForError (), base_type.GetSignatureForError ());
2909 } else if (base_type.IsSealed) {
2910 Report.SymbolRelatedToPreviousError (base_type);
2911 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2912 GetSignatureForError (), base_type.GetSignatureForError ());
2913 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2914 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2915 GetSignatureForError (), base_type.GetSignatureForError ());
2918 switch (base_type.BuiltinType) {
2919 case BuiltinTypeSpec.Type.Enum:
2920 case BuiltinTypeSpec.Type.ValueType:
2921 case BuiltinTypeSpec.Type.MulticastDelegate:
2922 case BuiltinTypeSpec.Type.Delegate:
2923 case BuiltinTypeSpec.Type.Array:
2924 if (!(spec is BuiltinTypeSpec)) {
2925 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2926 GetSignatureForError (), base_type.GetSignatureForError ());
2928 base_type = Compiler.BuiltinTypes.Object;
2933 if (!IsAccessibleAs (base_type)) {
2934 Report.SymbolRelatedToPreviousError (base_type);
2935 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2936 base_type.GetSignatureForError (), GetSignatureForError ());
2940 if (PartialContainer.IsStatic && ifaces != null) {
2941 foreach (var t in ifaces)
2942 Report.SymbolRelatedToPreviousError (t);
2943 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2949 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2950 /// Valid only for attribute classes.
2951 public override string[] ConditionalConditions ()
2953 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2956 caching_flags &= ~Flags.Excluded_Undetected;
2958 if (OptAttributes == null)
2961 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2965 string[] conditions = new string[attrs.Length];
2966 for (int i = 0; i < conditions.Length; ++i)
2967 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2969 caching_flags |= Flags.Excluded;
2974 public sealed class Struct : ClassOrStruct
2976 bool is_unmanaged, has_unmanaged_check_done;
2980 // Modifiers allowed in a struct declaration
2982 const Modifiers AllowedModifiers =
2985 Modifiers.PROTECTED |
2986 Modifiers.INTERNAL |
2990 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2991 : base (parent, name, attrs, MemberKind.Struct)
2993 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2994 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2995 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2998 public override AttributeTargets AttributeTargets {
3000 return AttributeTargets.Struct;
3004 public override void Accept (StructuralVisitor visitor)
3006 visitor.Visit (this);
3009 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3011 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3014 // When struct constains fixed fixed and struct layout has explicitly
3015 // set CharSet, its value has to be propagated to compiler generated
3018 if (a.Type == pa.StructLayout) {
3019 var value = a.GetNamedValue ("CharSet");
3023 for (int i = 0; i < Members.Count; ++i) {
3024 FixedField ff = Members [i] as FixedField;
3028 ff.CharSet = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
3033 bool CheckStructCycles ()
3039 foreach (var member in Members) {
3040 var field = member as Field;
3044 TypeSpec ftype = field.Spec.MemberType;
3045 if (!ftype.IsStruct)
3048 if (ftype is BuiltinTypeSpec)
3051 foreach (var targ in ftype.TypeArguments) {
3052 if (!CheckFieldTypeCycle (targ)) {
3053 Report.Error (523, field.Location,
3054 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3055 field.GetSignatureForError (), ftype.GetSignatureForError ());
3061 // Static fields of exactly same type are allowed
3063 if (field.IsStatic && ftype == CurrentType)
3066 if (!CheckFieldTypeCycle (ftype)) {
3067 Report.Error (523, field.Location,
3068 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3069 field.GetSignatureForError (), ftype.GetSignatureForError ());
3078 static bool CheckFieldTypeCycle (TypeSpec ts)
3080 var fts = ts.MemberDefinition as Struct;
3084 return fts.CheckStructCycles ();
3087 protected override bool DoDefineMembers ()
3089 var res = base.DoDefineMembers ();
3091 if (PrimaryConstructorParameters != null || (initialized_fields != null && !HasUserDefaultConstructor ())) {
3092 generated_primary_constructor = DefineDefaultConstructor (false);
3093 generated_primary_constructor.Define ();
3099 public override void Emit ()
3101 CheckStructCycles ();
3106 bool HasUserDefaultConstructor ()
3108 foreach (var m in PartialContainer.Members) {
3109 var c = m as Constructor;
3113 if (!c.IsStatic && c.ParameterInfo.IsEmpty)
3120 public override bool IsUnmanagedType ()
3122 if (has_unmanaged_check_done)
3123 return is_unmanaged;
3125 if (requires_delayed_unmanagedtype_check)
3128 var parent_def = Parent.PartialContainer;
3129 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
3130 has_unmanaged_check_done = true;
3134 if (first_nonstatic_field != null) {
3135 requires_delayed_unmanagedtype_check = true;
3137 foreach (var member in Members) {
3138 var f = member as Field;
3145 // It can happen when recursive unmanaged types are defined
3146 // struct S { S* s; }
3147 TypeSpec mt = f.MemberType;
3155 has_unmanaged_check_done = true;
3159 has_unmanaged_check_done = true;
3162 is_unmanaged = true;
3166 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
3168 var ifaces = base.ResolveBaseTypes (out base_class);
3169 base_type = Compiler.BuiltinTypes.ValueType;
3177 public sealed class Interface : TypeDefinition {
3180 /// Modifiers allowed in a class declaration
3182 const Modifiers AllowedModifiers =
3185 Modifiers.PROTECTED |
3186 Modifiers.INTERNAL |
3190 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
3191 : base (parent, name, attrs, MemberKind.Interface)
3193 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3195 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
3196 spec = new TypeSpec (Kind, null, this, null, ModFlags);
3201 public override AttributeTargets AttributeTargets {
3203 return AttributeTargets.Interface;
3207 protected override TypeAttributes TypeAttr {
3209 const TypeAttributes DefaultTypeAttributes =
3210 TypeAttributes.AutoLayout |
3211 TypeAttributes.Abstract |
3212 TypeAttributes.Interface;
3214 return base.TypeAttr | DefaultTypeAttributes;
3220 public override void Accept (StructuralVisitor visitor)
3222 visitor.Visit (this);
3225 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3227 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3228 a.Error_MissingGuidAttribute ();
3232 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3235 protected override bool VerifyClsCompliance ()
3237 if (!base.VerifyClsCompliance ())
3240 if (iface_exprs != null) {
3241 foreach (var iface in iface_exprs) {
3242 if (iface.IsCLSCompliant ())
3245 Report.SymbolRelatedToPreviousError (iface);
3246 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3247 GetSignatureForError (), iface.GetSignatureForError ());
3255 public abstract class InterfaceMemberBase : MemberBase
3258 // Common modifiers allowed in a class declaration
3260 protected const Modifiers AllowedModifiersClass =
3263 Modifiers.PROTECTED |
3264 Modifiers.INTERNAL |
3269 Modifiers.OVERRIDE |
3270 Modifiers.ABSTRACT |
3275 // Common modifiers allowed in a struct declaration
3277 protected const Modifiers AllowedModifiersStruct =
3280 Modifiers.PROTECTED |
3281 Modifiers.INTERNAL |
3284 Modifiers.OVERRIDE |
3289 // Common modifiers allowed in a interface declaration
3291 protected const Modifiers AllowedModifiersInterface =
3296 // Whether this is an interface member.
3298 public bool IsInterface;
3301 // If true, this is an explicit interface implementation
3303 public readonly bool IsExplicitImpl;
3305 protected bool is_external_implementation;
3308 // The interface type we are explicitly implementing
3310 public TypeSpec InterfaceType;
3313 // The method we're overriding if this is an override method.
3315 protected MethodSpec base_method;
3317 readonly Modifiers explicit_mod_flags;
3318 public MethodAttributes flags;
3320 protected InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3321 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3323 IsInterface = parent.Kind == MemberKind.Interface;
3324 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3325 explicit_mod_flags = mod;
3328 public abstract Variance ExpectedMemberTypeVariance { get; }
3330 protected override bool CheckBase ()
3332 if (!base.CheckBase ())
3335 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3336 CheckForDuplications ();
3341 // For System.Object only
3342 if (Parent.BaseType == null)
3345 MemberSpec candidate;
3346 bool overrides = false;
3347 var base_member = FindBaseMember (out candidate, ref overrides);
3349 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3350 if (base_member == null) {
3351 if (candidate == null) {
3352 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3353 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3354 "object.Finalize()");
3356 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3357 GetSignatureForError (), SimpleName.GetMemberType (this));
3360 Report.SymbolRelatedToPreviousError (candidate);
3362 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3363 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3364 else if (this is PropertyBase)
3365 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3366 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3368 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3369 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3376 // Handles ambiguous overrides
3378 if (candidate != null) {
3379 Report.SymbolRelatedToPreviousError (candidate);
3380 Report.SymbolRelatedToPreviousError (base_member);
3382 // Get member definition for error reporting
3383 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3384 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3386 Report.Error (462, Location,
3387 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3388 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3391 if (!CheckOverrideAgainstBase (base_member))
3394 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3396 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3397 Report.SymbolRelatedToPreviousError (base_member);
3398 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3399 GetSignatureForError (), base_member.GetSignatureForError ());
3402 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3403 Report.SymbolRelatedToPreviousError (base_member);
3404 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3405 GetSignatureForError (), base_member.GetSignatureForError ());
3409 base_method = base_member as MethodSpec;
3413 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3414 base_member = candidate;
3416 if (base_member == null) {
3417 if ((ModFlags & Modifiers.NEW) != 0) {
3418 if (base_member == null) {
3419 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3420 GetSignatureForError ());
3424 if ((ModFlags & Modifiers.NEW) == 0) {
3425 ModFlags |= Modifiers.NEW;
3426 if (!IsCompilerGenerated) {
3427 Report.SymbolRelatedToPreviousError (base_member);
3428 if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3429 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",
3430 GetSignatureForError (), base_member.GetSignatureForError ());
3432 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3433 GetSignatureForError (), base_member.GetSignatureForError ());
3438 if (!IsInterface && base_member.IsAbstract && !overrides && !IsStatic) {
3439 Report.SymbolRelatedToPreviousError (base_member);
3440 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3441 GetSignatureForError (), base_member.GetSignatureForError ());
3448 protected virtual bool CheckForDuplications ()
3450 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3454 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3455 // that have been defined.
3457 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3461 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3462 Report.SymbolRelatedToPreviousError (base_member);
3463 Report.Error (506, Location,
3464 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3465 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3469 // Now we check that the overriden method is not final
3470 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3471 Report.SymbolRelatedToPreviousError (base_member);
3472 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3473 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3477 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3478 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3479 Report.SymbolRelatedToPreviousError (base_member);
3480 if (this is PropertyBasedMember) {
3481 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3482 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3484 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3485 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3493 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3495 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3496 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3498 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3500 // It must be at least "protected"
3502 if ((thisp & Modifiers.PROTECTED) == 0) {
3507 // when overriding protected internal, the method can be declared
3508 // protected internal only within the same assembly or assembly
3509 // which has InternalsVisibleTo
3511 if ((thisp & Modifiers.INTERNAL) != 0) {
3512 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3516 // protected overriding protected internal inside same assembly
3517 // requires internal modifier as well
3519 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3526 return thisp == base_classp;
3529 public override bool Define ()
3532 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3533 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3535 flags = MethodAttributes.Public |
3536 MethodAttributes.Abstract |
3537 MethodAttributes.HideBySig |
3538 MethodAttributes.NewSlot |
3539 MethodAttributes.Virtual;
3541 Parent.PartialContainer.MethodModifiersValid (this);
3543 flags = ModifiersExtensions.MethodAttr (ModFlags);
3546 if (IsExplicitImpl) {
3547 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3548 if (InterfaceType == null)
3551 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3552 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3553 GetSignatureForError ());
3556 if (!InterfaceType.IsInterface) {
3557 Report.SymbolRelatedToPreviousError (InterfaceType);
3558 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3559 InterfaceType.GetSignatureForError ());
3561 Parent.PartialContainer.VerifyImplements (this);
3564 Modifiers allowed_explicit = Modifiers.AllowedExplicitImplFlags;
3566 allowed_explicit |= Modifiers.ASYNC;
3568 ModifiersExtensions.Check (allowed_explicit, explicit_mod_flags, 0, Location, Report);
3571 return base.Define ();
3574 protected bool DefineParameters (ParametersCompiled parameters)
3576 if (!parameters.Resolve (this))
3580 for (int i = 0; i < parameters.Count; ++i) {
3581 Parameter p = parameters [i];
3583 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3584 p.Warning_UselessOptionalParameter (Report);
3586 if (p.CheckAccessibility (this))
3589 TypeSpec t = parameters.Types [i];
3590 Report.SymbolRelatedToPreviousError (t);
3591 if (this is Indexer)
3592 Report.Error (55, Location,
3593 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3594 t.GetSignatureForError (), GetSignatureForError ());
3595 else if (this is Operator)
3596 Report.Error (57, Location,
3597 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3598 t.GetSignatureForError (), GetSignatureForError ());
3600 Report.Error (51, Location,
3601 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3602 t.GetSignatureForError (), GetSignatureForError ());
3608 protected override void DoMemberTypeDependentChecks ()
3610 base.DoMemberTypeDependentChecks ();
3612 VarianceDecl.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3615 public override void Emit()
3617 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3618 // We are more strict than csc and report this as an error because SRE does not allow emit that
3619 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3620 if (this is Constructor) {
3621 Report.Warning (824, 1, Location,
3622 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3624 Report.Warning (626, 1, Location,
3625 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3626 GetSignatureForError ());
3633 public override bool EnableOverloadChecks (MemberCore overload)
3636 // Two members can differ in their explicit interface
3637 // type parameter only
3639 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3640 if (imb != null && imb.IsExplicitImpl) {
3641 if (IsExplicitImpl) {
3642 caching_flags |= Flags.MethodOverloadsExist;
3647 return IsExplicitImpl;
3650 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3652 var base_modifiers = base_member.Modifiers;
3654 // Remove internal modifier from types which are not internally accessible
3655 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3656 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3657 base_modifiers = Modifiers.PROTECTED;
3659 Report.SymbolRelatedToPreviousError (base_member);
3660 Report.Error (507, member.Location,
3661 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3662 member.GetSignatureForError (),
3663 ModifiersExtensions.AccessibilityName (base_modifiers),
3664 base_member.GetSignatureForError ());
3667 protected void Error_StaticReturnType ()
3669 Report.Error (722, Location,
3670 "`{0}': static types cannot be used as return types",
3671 MemberType.GetSignatureForError ());
3675 /// Gets base method and its return type
3677 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3679 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3683 // The "short" name of this property / indexer / event. This is the
3684 // name without the explicit interface.
3686 public string ShortName {
3687 get { return MemberName.Name; }
3691 // Returns full metadata method name
3693 public string GetFullName (MemberName name)
3695 return GetFullName (name.Name);
3698 public string GetFullName (string name)
3700 if (!IsExplicitImpl)
3704 // When dealing with explicit members a full interface type
3705 // name is added to member name to avoid possible name conflicts
3707 // We use CSharpName which gets us full name with benefit of
3708 // replacing predefined names which saves some space and name
3711 return InterfaceType.GetSignatureForError () + "." + name;
3714 public override string GetSignatureForDocumentation ()
3717 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetExplicitNameSignatureForDocumentation () + "#" + ShortName;
3719 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3722 public override bool IsUsed
3724 get { return IsExplicitImpl || base.IsUsed; }
3727 public override void SetConstraints (List<Constraints> constraints_list)
3729 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3730 Report.Error (460, Location,
3731 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3732 GetSignatureForError ());
3735 base.SetConstraints (constraints_list);
3739 public abstract class MemberBase : MemberCore
3741 protected FullNamedExpression type_expr;
3742 protected TypeSpec member_type;
3743 public new TypeDefinition Parent;
3745 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3746 : base (parent, name, attrs)
3748 this.Parent = parent;
3749 this.type_expr = type;
3751 if (name != MemberName.Null)
3752 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3757 public TypeSpec MemberType {
3763 public FullNamedExpression TypeExpression {
3772 // Main member define entry
3774 public override bool Define ()
3776 DoMemberTypeIndependentChecks ();
3779 // Returns false only when type resolution failed
3781 if (!ResolveMemberType ())
3784 DoMemberTypeDependentChecks ();
3789 // Any type_name independent checks
3791 protected virtual void DoMemberTypeIndependentChecks ()
3793 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3794 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3795 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3796 GetSignatureForError (), Parent.GetSignatureForError ());
3801 // Any type_name dependent checks
3803 protected virtual void DoMemberTypeDependentChecks ()
3805 // verify accessibility
3806 if (!IsAccessibleAs (MemberType)) {
3807 Report.SymbolRelatedToPreviousError (MemberType);
3808 if (this is Property)
3809 Report.Error (53, Location,
3810 "Inconsistent accessibility: property type `" +
3811 MemberType.GetSignatureForError () + "' is less " +
3812 "accessible than property `" + GetSignatureForError () + "'");
3813 else if (this is Indexer)
3814 Report.Error (54, Location,
3815 "Inconsistent accessibility: indexer return type `" +
3816 MemberType.GetSignatureForError () + "' is less " +
3817 "accessible than indexer `" + GetSignatureForError () + "'");
3818 else if (this is MethodCore) {
3819 if (this is Operator)
3820 Report.Error (56, Location,
3821 "Inconsistent accessibility: return type `" +
3822 MemberType.GetSignatureForError () + "' is less " +
3823 "accessible than operator `" + GetSignatureForError () + "'");
3825 Report.Error (50, Location,
3826 "Inconsistent accessibility: return type `" +
3827 MemberType.GetSignatureForError () + "' is less " +
3828 "accessible than method `" + GetSignatureForError () + "'");
3829 } else if (this is Event) {
3830 Report.Error (7025, Location,
3831 "Inconsistent accessibility: event type `{0}' is less accessible than event `{1}'",
3832 MemberType.GetSignatureForError (), GetSignatureForError ());
3834 Report.Error (52, Location,
3835 "Inconsistent accessibility: field type `" +
3836 MemberType.GetSignatureForError () + "' is less " +
3837 "accessible than field `" + GetSignatureForError () + "'");
3842 protected void IsTypePermitted ()
3844 if (MemberType.IsSpecialRuntimeType) {
3845 if (Parent is StateMachine) {
3846 Report.Error (4012, Location,
3847 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3848 MemberType.GetSignatureForError ());
3849 } else if (Parent is HoistedStoreyClass) {
3850 Report.Error (4013, Location,
3851 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3852 MemberType.GetSignatureForError ());
3854 Report.Error (610, Location,
3855 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3860 protected virtual bool CheckBase ()
3862 CheckProtectedModifier ();
3867 public override string GetSignatureForDocumentation ()
3869 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3872 protected virtual bool ResolveMemberType ()
3874 if (member_type != null)
3875 throw new InternalErrorException ("Multi-resolve");
3877 member_type = type_expr.ResolveAsType (this);
3878 return member_type != null;