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 (TypeSpec extensionType, 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 virtual 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 (initialized_fields == null)
980 initialized_fields = new List<FieldInitializer> (4);
982 initialized_fields.Add (expression);
986 public void ResolveFieldInitializers (BlockContext ec)
988 Debug.Assert (!IsPartialPart);
991 if (initialized_static_fields == null)
994 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
996 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
997 for (i = 0; i < initialized_static_fields.Count; ++i) {
998 FieldInitializer fi = initialized_static_fields [i];
999 ExpressionStatement s = fi.ResolveStatement (ec);
1001 s = EmptyExpressionStatement.Instance;
1002 } else if (!fi.IsSideEffectFree) {
1003 has_complex_initializer = true;
1009 for (i = 0; i < initialized_static_fields.Count; ++i) {
1010 FieldInitializer fi = initialized_static_fields [i];
1012 // Need special check to not optimize code like this
1013 // static int a = b = 5;
1014 // static int b = 0;
1016 if (!has_complex_initializer && fi.IsDefaultInitializer)
1019 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1020 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
1026 if (initialized_fields == null)
1029 for (int i = 0; i < initialized_fields.Count; ++i) {
1030 FieldInitializer fi = initialized_fields [i];
1033 // Clone before resolving otherwise when field initializer is needed
1034 // in more than 1 constructor any resolve after the initial one would
1035 // only took the resolved expression which is problem for expressions
1036 // that generate extra expressions or code during Resolve phase
1038 var cloned = fi.Clone (new CloneContext ());
1040 ExpressionStatement s = fi.ResolveStatement (ec);
1042 initialized_fields [i] = new FieldInitializer (fi.Field, ErrorExpression.Instance, Location.Null);
1047 // Field is re-initialized to its default value => removed
1049 if (fi.IsDefaultInitializer && ec.Module.Compiler.Settings.Optimize)
1052 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1053 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
1054 initialized_fields [i] = (FieldInitializer) cloned;
1058 public override string DocComment {
1070 public PendingImplementation PendingImplementations {
1071 get { return pending; }
1074 internal override void GenerateDocComment (DocumentationBuilder builder)
1079 base.GenerateDocComment (builder);
1081 foreach (var member in members)
1082 member.GenerateDocComment (builder);
1085 public TypeSpec GetAttributeCoClass ()
1087 if (OptAttributes == null)
1090 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
1094 return a.GetCoClassAttributeValue ();
1097 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1100 if (OptAttributes != null) {
1101 a = OptAttributes.Search (pa);
1107 return a.GetAttributeUsageAttribute ();
1110 public virtual CompilationSourceFile GetCompilationSourceFile ()
1112 TypeContainer ns = Parent;
1114 var sf = ns as CompilationSourceFile;
1122 public virtual void SetBaseTypes (List<FullNamedExpression> baseTypes)
1124 type_bases = baseTypes;
1128 /// This function computes the Base class and also the
1129 /// list of interfaces that the class or struct @c implements.
1131 /// The return value is an array (might be null) of
1132 /// interfaces implemented (as Types).
1134 /// The @base_class argument is set to the base object or null
1135 /// if this is `System.Object'.
1137 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1140 if (type_bases == null)
1143 int count = type_bases.Count;
1144 TypeSpec[] ifaces = null;
1145 var base_context = new BaseContext (this);
1146 for (int i = 0, j = 0; i < count; i++){
1147 FullNamedExpression fne = type_bases [i];
1149 var fne_resolved = fne.ResolveAsType (base_context);
1150 if (fne_resolved == null)
1153 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1154 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1155 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1156 GetSignatureForError ());
1161 base_type = fne_resolved;
1167 ifaces = new TypeSpec [count - i];
1169 if (fne_resolved.IsInterface) {
1170 for (int ii = 0; ii < j; ++ii) {
1171 if (fne_resolved == ifaces [ii]) {
1172 Report.Error (528, Location, "`{0}' is already listed in interface list",
1173 fne_resolved.GetSignatureForError ());
1178 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1179 Report.Error (61, fne.Location,
1180 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1181 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1184 Report.SymbolRelatedToPreviousError (fne_resolved);
1185 if (Kind != MemberKind.Class) {
1186 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1187 } else if (base_class != null)
1188 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1189 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1191 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1192 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1196 ifaces [j++] = fne_resolved;
1203 // Checks that some operators come in pairs:
1209 // They are matched based on the return type and the argument types
1211 void CheckPairedOperators ()
1213 bool has_equality_or_inequality = false;
1214 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1216 for (int i = 0; i < members.Count; ++i) {
1217 var o_a = members[i] as Operator;
1221 var o_type = o_a.OperatorType;
1222 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1223 has_equality_or_inequality = true;
1225 if (found_matched.Contains (o_type))
1228 var matching_type = o_a.GetMatchingOperator ();
1229 if (matching_type == Operator.OpType.TOP) {
1233 bool pair_found = false;
1234 for (int ii = 0; ii < members.Count; ++ii) {
1235 var o_b = members[ii] as Operator;
1236 if (o_b == null || o_b.OperatorType != matching_type)
1239 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1242 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1245 found_matched.Add (matching_type);
1251 Report.Error (216, o_a.Location,
1252 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1253 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1257 if (has_equality_or_inequality) {
1259 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1260 GetSignatureForError ());
1262 if (!HasGetHashCode)
1263 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1264 GetSignatureForError ());
1268 public override void CreateMetadataName (StringBuilder sb)
1270 if (Parent.MemberName != null) {
1271 Parent.CreateMetadataName (sb);
1273 if (sb.Length != 0) {
1278 sb.Append (MemberName.Basename);
1281 bool CreateTypeBuilder ()
1284 // Sets .size to 1 for structs with no instance fields
1286 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null && !(this is StateMachine) ? 1 : 0;
1288 var parent_def = Parent as TypeDefinition;
1289 if (parent_def == null) {
1290 var sb = new StringBuilder ();
1291 CreateMetadataName (sb);
1292 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1294 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (MemberName.Basename, TypeAttr, null, type_size);
1297 if (DeclaringAssembly.Importer != null)
1298 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1300 spec.SetMetaInfo (TypeBuilder);
1301 spec.MemberCache = new MemberCache (this);
1303 TypeParameters parentAllTypeParameters = null;
1304 if (parent_def != null) {
1305 spec.DeclaringType = Parent.CurrentType;
1306 parent_def.MemberCache.AddMember (spec);
1307 parentAllTypeParameters = parent_def.all_type_parameters;
1310 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1311 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1313 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1315 if (CurrentTypeParameters != null) {
1316 CurrentTypeParameters.Create (spec, CurrentTypeParametersStartIndex, this);
1317 CurrentTypeParameters.Define (all_tp_builders);
1324 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1327 int parent_offset = 0;
1328 if (parentAllTypeParameters != null) {
1329 if (CurrentTypeParameters == null) {
1330 all_type_parameters = parentAllTypeParameters;
1331 return parentAllTypeParameters.GetAllNames ();
1334 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1335 all_type_parameters = new TypeParameters (names.Length);
1336 all_type_parameters.Add (parentAllTypeParameters);
1338 parent_offset = all_type_parameters.Count;
1339 for (int i = 0; i < parent_offset; ++i)
1340 names[i] = all_type_parameters[i].MemberName.Name;
1343 names = new string[CurrentTypeParameters.Count];
1346 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1347 if (all_type_parameters != null)
1348 all_type_parameters.Add (MemberName.TypeParameters[i]);
1350 var name = CurrentTypeParameters[i].MemberName.Name;
1351 names[parent_offset + i] = name;
1352 for (int ii = 0; ii < parent_offset + i; ++ii) {
1353 if (names[ii] != name)
1356 var tp = CurrentTypeParameters[i];
1357 var conflict = all_type_parameters[ii];
1359 tp.WarningParentNameConflict (conflict);
1363 if (all_type_parameters == null)
1364 all_type_parameters = CurrentTypeParameters;
1370 public SourceMethodBuilder CreateMethodSymbolEntry ()
1372 if (Module.DeclaringAssembly.SymbolWriter == null || (ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1375 var source_file = GetCompilationSourceFile ();
1376 if (source_file == null)
1379 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1383 // Creates a proxy base method call inside this container for hoisted base member calls
1385 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1387 Method proxy_method;
1390 // One proxy per base method is enough
1392 if (hoisted_base_call_proxies == null) {
1393 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1394 proxy_method = null;
1396 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1399 if (proxy_method == null) {
1400 string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1402 MemberName member_name;
1403 TypeArguments targs = null;
1404 TypeSpec return_type = method.ReturnType;
1405 var local_param_types = method.Parameters.Types;
1407 if (method.IsGeneric) {
1409 // Copy all base generic method type parameters info
1411 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1412 var tparams = new TypeParameters ();
1414 targs = new TypeArguments ();
1415 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1416 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1417 var tp = hoisted_tparams[i];
1418 var local_tp = new TypeParameter (tp, null, new MemberName (tp.Name, Location), null);
1419 tparams.Add (local_tp);
1421 targs.Add (new SimpleName (tp.Name, Location));
1422 targs.Arguments[i] = local_tp.Type;
1425 member_name = new MemberName (name, tparams, Location);
1428 // Mutate any method type parameters from original
1429 // to newly created hoisted version
1431 var mutator = new TypeParameterMutator (hoisted_tparams, tparams);
1432 return_type = mutator.Mutate (return_type);
1433 local_param_types = mutator.Mutate (local_param_types);
1435 member_name = new MemberName (name);
1438 var base_parameters = new Parameter[method.Parameters.Count];
1439 for (int i = 0; i < base_parameters.Length; ++i) {
1440 var base_param = method.Parameters.FixedParameters[i];
1441 base_parameters[i] = new Parameter (new TypeExpression (local_param_types [i], Location),
1442 base_param.Name, base_param.ModFlags, null, Location);
1443 base_parameters[i].Resolve (this, i);
1446 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
1447 if (method.Parameters.HasArglist) {
1448 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1449 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1452 // Compiler generated proxy
1453 proxy_method = new Method (this, new TypeExpression (return_type, Location),
1454 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1455 member_name, cloned_params, null);
1457 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1458 IsCompilerGenerated = true
1461 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1462 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1464 mg.SetTypeArguments (rc, targs);
1466 // Get all the method parameters and pass them as arguments
1467 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1468 Statement statement;
1469 if (method.ReturnType.Kind == MemberKind.Void)
1470 statement = new StatementExpression (real_base_call);
1472 statement = new Return (real_base_call, Location);
1474 block.AddStatement (statement);
1475 proxy_method.Block = block;
1477 members.Add (proxy_method);
1478 proxy_method.Define ();
1479 proxy_method.PrepareEmit ();
1481 hoisted_base_call_proxies.Add (method, proxy_method);
1484 return proxy_method.Spec;
1487 protected bool DefineBaseTypes ()
1489 if (IsPartialPart && Kind == MemberKind.Class)
1492 return DoDefineBaseType ();
1495 bool DoDefineBaseType ()
1497 iface_exprs = ResolveBaseTypes (out base_type_expr);
1500 if (IsPartialPart) {
1501 set_base_type = false;
1503 if (base_type_expr != null) {
1504 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1505 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1506 Report.Error (263, Location,
1507 "Partial declarations of `{0}' must not specify different base classes",
1508 GetSignatureForError ());
1510 PartialContainer.base_type_expr = base_type_expr;
1511 PartialContainer.base_type = base_type;
1512 set_base_type = true;
1516 if (iface_exprs != null) {
1517 if (PartialContainer.iface_exprs == null)
1518 PartialContainer.iface_exprs = iface_exprs;
1520 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1521 foreach (var iface_partial in iface_exprs) {
1522 if (ifaces.Contains (iface_partial))
1525 ifaces.Add (iface_partial);
1528 PartialContainer.iface_exprs = ifaces.ToArray ();
1532 PartialContainer.members.AddRange (members);
1533 if (containers != null) {
1534 if (PartialContainer.containers == null)
1535 PartialContainer.containers = new List<TypeContainer> ();
1537 PartialContainer.containers.AddRange (containers);
1540 if (PrimaryConstructorParameters != null) {
1541 if (PartialContainer.PrimaryConstructorParameters != null) {
1542 Report.Error (8036, Location, "Only one part of a partial type can declare primary constructor parameters");
1544 PartialContainer.PrimaryConstructorParameters = PrimaryConstructorParameters;
1548 members_defined = members_defined_ok = true;
1549 caching_flags |= Flags.CloseTypeCreated;
1551 set_base_type = true;
1554 var cycle = CheckRecursiveDefinition (this);
1555 if (cycle != null) {
1556 Report.SymbolRelatedToPreviousError (cycle);
1557 if (this is Interface) {
1558 Report.Error (529, Location,
1559 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1560 GetSignatureForError (), cycle.GetSignatureForError ());
1563 PartialContainer.iface_exprs = null;
1565 Report.Error (146, Location,
1566 "Circular base class dependency involving `{0}' and `{1}'",
1567 GetSignatureForError (), cycle.GetSignatureForError ());
1570 PartialContainer.base_type = null;
1574 if (iface_exprs != null) {
1575 if (!PrimaryConstructorBaseArgumentsStart.IsNull) {
1576 Report.Error (8049, PrimaryConstructorBaseArgumentsStart, "Implemented interfaces cannot have arguments");
1579 foreach (var iface_type in iface_exprs) {
1580 // Prevents a crash, the interface might not have been resolved: 442144
1581 if (iface_type == null)
1584 if (!spec.AddInterfaceDefined (iface_type))
1587 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1591 if (Kind == MemberKind.Interface) {
1592 spec.BaseType = Compiler.BuiltinTypes.Object;
1596 if (set_base_type) {
1601 // Base type of partial container has to be resolved before we
1602 // resolve any nested types of the container. We need to know
1603 // partial parts because the base type can be specified in file
1604 // defined after current container
1606 if (class_partial_parts != null) {
1607 foreach (var pp in class_partial_parts) {
1608 if (pp.PrimaryConstructorBaseArguments != null)
1609 PrimaryConstructorBaseArguments = pp.PrimaryConstructorBaseArguments;
1611 pp.DoDefineBaseType ();
1621 if (base_type == null) {
1622 TypeBuilder.SetParent (null);
1626 if (spec.BaseType == base_type)
1629 spec.BaseType = base_type;
1632 spec.UpdateInflatedInstancesBaseType ();
1634 // Set base type after type creation
1635 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1638 public override void ExpandBaseInterfaces ()
1641 DoExpandBaseInterfaces ();
1643 base.ExpandBaseInterfaces ();
1646 public void DoExpandBaseInterfaces ()
1648 if ((caching_flags & Flags.InterfacesExpanded) != 0)
1651 caching_flags |= Flags.InterfacesExpanded;
1654 // Expand base interfaces. It cannot be done earlier because all partial
1655 // interface parts need to be defined before the type they are used from
1657 if (iface_exprs != null) {
1658 foreach (var iface in iface_exprs) {
1662 var td = iface.MemberDefinition as TypeDefinition;
1664 td.DoExpandBaseInterfaces ();
1666 if (iface.Interfaces == null)
1669 foreach (var biface in iface.Interfaces) {
1670 if (spec.AddInterfaceDefined (biface)) {
1671 TypeBuilder.AddInterfaceImplementation (biface.GetMetaInfo ());
1678 // Include all base type interfaces too, see ImportTypeBase for details
1680 if (base_type != null) {
1681 var td = base_type.MemberDefinition as TypeDefinition;
1683 td.DoExpandBaseInterfaces ();
1686 // Simply use base interfaces only, they are all expanded which makes
1687 // it easy to handle generic type argument propagation with single
1690 // interface IA<T> : IB<T>
1691 // interface IB<U> : IC<U>
1694 if (base_type.Interfaces != null) {
1695 foreach (var iface in base_type.Interfaces) {
1696 spec.AddInterfaceDefined (iface);
1702 public override void PrepareEmit ()
1704 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1707 foreach (var member in members) {
1708 var pbm = member as PropertyBasedMember;
1712 var pm = member as IParametersMember;
1714 var mc = member as MethodOrOperator;
1719 var p = pm.Parameters;
1723 ((ParametersCompiled) p).ResolveDefaultValues (member);
1727 var c = member as Const;
1732 base.PrepareEmit ();
1736 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1738 public override bool CreateContainer ()
1740 if (TypeBuilder != null)
1746 if (IsPartialPart) {
1747 spec = PartialContainer.spec;
1748 TypeBuilder = PartialContainer.TypeBuilder;
1749 all_tp_builders = PartialContainer.all_tp_builders;
1750 all_type_parameters = PartialContainer.all_type_parameters;
1752 if (!CreateTypeBuilder ()) {
1758 return base.CreateContainer ();
1761 protected override void DoDefineContainer ()
1765 DoResolveTypeParameters ();
1769 // Replaces normal spec with predefined one when compiling corlib
1770 // and this type container defines predefined type
1772 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1774 // When compiling build-in types we start with two
1775 // version of same type. One is of BuiltinTypeSpec and
1776 // second one is ordinary TypeSpec. The unification
1777 // happens at later stage when we know which type
1778 // really matches the builtin type signature. However
1779 // that means TypeSpec create during CreateType of this
1780 // type has to be replaced with builtin one
1782 spec.SetMetaInfo (TypeBuilder);
1783 spec.MemberCache = this.spec.MemberCache;
1784 spec.DeclaringType = this.spec.DeclaringType;
1787 current_type = null;
1790 public override void RemoveContainer (TypeContainer cont)
1792 base.RemoveContainer (cont);
1793 Members.Remove (cont);
1794 Cache.Remove (cont.MemberName.Basename);
1797 protected virtual bool DoResolveTypeParameters ()
1799 var tparams = MemberName.TypeParameters;
1800 if (tparams == null)
1803 var base_context = new BaseContext (this);
1804 for (int i = 0; i < tparams.Count; ++i) {
1805 var tp = tparams[i];
1807 if (!tp.ResolveConstraints (base_context)) {
1812 if (IsPartialPart) {
1813 var pc_tp = PartialContainer.CurrentTypeParameters [i];
1815 tp.Create (spec, this);
1818 if (tp.OptAttributes != null) {
1819 if (pc_tp.OptAttributes == null)
1820 pc_tp.OptAttributes = tp.OptAttributes;
1822 pc_tp.OptAttributes.Attrs.AddRange (tp.OptAttributes.Attrs);
1827 if (IsPartialPart) {
1828 PartialContainer.CurrentTypeParameters.UpdateConstraints (this);
1834 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1836 if (InTransit != null)
1841 if (base_type != null) {
1842 var ptc = base_type.MemberDefinition as TypeDefinition;
1843 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1847 if (iface_exprs != null) {
1848 foreach (var iface in iface_exprs) {
1849 // the interface might not have been resolved, prevents a crash, see #442144
1852 var ptc = iface.MemberDefinition as Interface;
1853 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1858 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1866 /// Populates our TypeBuilder with fields and methods
1868 public sealed override bool Define ()
1870 if (members_defined)
1871 return members_defined_ok;
1873 members_defined_ok = DoDefineMembers ();
1874 members_defined = true;
1878 return members_defined_ok;
1881 protected virtual bool DoDefineMembers ()
1883 Debug.Assert (!IsPartialPart);
1885 if (iface_exprs != null) {
1886 foreach (var iface_type in iface_exprs) {
1887 if (iface_type == null)
1890 // Ensure the base is always setup
1891 var compiled_iface = iface_type.MemberDefinition as Interface;
1892 if (compiled_iface != null)
1893 compiled_iface.Define ();
1895 ObsoleteAttribute oa = iface_type.GetAttributeObsolete ();
1896 if (oa != null && !IsObsolete)
1897 AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report);
1899 if (iface_type.Arity > 0) {
1900 // TODO: passing `this' is wrong, should be base type iface instead
1901 VarianceDecl.CheckTypeVariance (iface_type, Variance.Covariant, this);
1903 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1904 Report.Error (1966, Location,
1905 "`{0}': cannot implement a dynamic interface `{1}'",
1906 GetSignatureForError (), iface_type.GetSignatureForError ());
1911 if (iface_type.IsGenericOrParentIsGeneric) {
1912 foreach (var prev_iface in iface_exprs) {
1913 if (prev_iface == iface_type || prev_iface == null)
1916 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1919 Report.Error (695, Location,
1920 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1921 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1926 if (Kind == MemberKind.Interface) {
1927 foreach (var iface in spec.Interfaces) {
1928 MemberCache.AddInterface (iface);
1933 if (base_type != null) {
1935 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1937 if (base_type_expr != null) {
1938 ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
1939 if (obsolete_attr != null && !IsObsolete)
1940 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report);
1942 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1943 Report.Error (698, base_type_expr.Location,
1944 "A generic type cannot derive from `{0}' because it is an attribute class",
1945 base_type.GetSignatureForError ());
1949 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1950 if (baseContainer != null) {
1951 baseContainer.Define ();
1954 // It can trigger define of this type (for generic types only)
1956 if (HasMembersDefined)
1961 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1962 pending = PendingImplementation.GetPendingImplementations (this);
1965 var count = members.Count;
1966 for (int i = 0; i < count; ++i) {
1967 var mc = members[i] as InterfaceMemberBase;
1968 if (mc == null || !mc.IsExplicitImpl)
1973 } catch (Exception e) {
1974 throw new InternalErrorException (mc, e);
1978 for (int i = 0; i < count; ++i) {
1979 var mc = members[i] as InterfaceMemberBase;
1980 if (mc != null && mc.IsExplicitImpl)
1983 if (members[i] is TypeContainer)
1987 members[i].Define ();
1988 } catch (Exception e) {
1989 throw new InternalErrorException (members[i], e);
1994 CheckPairedOperators ();
1997 if (requires_delayed_unmanagedtype_check) {
1998 requires_delayed_unmanagedtype_check = false;
1999 foreach (var member in members) {
2000 var f = member as Field;
2001 if (f != null && f.MemberType != null && f.MemberType.IsPointer)
2002 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
2006 ComputeIndexerName();
2008 if (HasEquals && !HasGetHashCode) {
2009 Report.Warning (659, 3, Location,
2010 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
2013 if (Kind == MemberKind.Interface && iface_exprs != null) {
2014 MemberCache.RemoveHiddenMembers (spec);
2020 void ComputeIndexerName ()
2022 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
2023 if (indexers == null)
2026 string class_indexer_name = null;
2029 // Check normal indexers for consistent name, explicit interface implementation
2030 // indexers are ignored
2032 foreach (var indexer in indexers) {
2034 // FindMembers can return unfiltered full hierarchy names
2036 if (indexer.DeclaringType != spec)
2039 has_normal_indexers = true;
2041 if (class_indexer_name == null) {
2042 indexer_name = class_indexer_name = indexer.Name;
2046 if (indexer.Name != class_indexer_name)
2047 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
2048 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
2052 void EmitIndexerName ()
2054 if (!has_normal_indexers)
2057 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
2061 var encoder = new AttributeEncoder ();
2062 encoder.Encode (GetAttributeDefaultMember ());
2063 encoder.EncodeEmptyNamedArguments ();
2065 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2068 public override void VerifyMembers ()
2071 // Check for internal or private fields that were never assigned
2073 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
2074 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
2075 foreach (var member in members) {
2076 if (member is Event) {
2078 // An event can be assigned from same class only, report
2079 // this warning for all accessibility modes
2081 if (!member.IsUsed && !PartialContainer.HasStructLayout)
2082 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
2087 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
2088 if (is_type_exposed)
2091 member.SetIsUsed ();
2094 var f = member as Field;
2098 if (!member.IsUsed) {
2099 if (!PartialContainer.HasStructLayout) {
2100 if ((member.caching_flags & Flags.IsAssigned) == 0) {
2101 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
2103 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
2104 member.GetSignatureForError ());
2111 if ((f.caching_flags & Flags.IsAssigned) != 0)
2115 // Only report 649 on level 4
2117 if (Compiler.Settings.WarningLevel < 4)
2121 // Don't be pedantic when type requires specific layout
2123 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2126 Constant c = New.Constantify (f.MemberType, f.Location);
2129 value = c.GetValueAsLiteral ();
2130 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
2137 value = " `" + value + "'";
2139 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
2140 f.GetSignatureForError (), value);
2144 base.VerifyMembers ();
2147 public override void Emit ()
2149 if (OptAttributes != null)
2150 OptAttributes.Emit ();
2152 if (!IsCompilerGenerated) {
2154 MemberSpec candidate;
2155 bool overrides = false;
2156 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
2157 if (conflict_symbol == null && candidate == null) {
2158 if ((ModFlags & Modifiers.NEW) != 0)
2159 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
2160 GetSignatureForError ());
2162 if ((ModFlags & Modifiers.NEW) == 0) {
2163 if (candidate == null)
2164 candidate = conflict_symbol;
2166 Report.SymbolRelatedToPreviousError (candidate);
2167 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
2168 GetSignatureForError (), candidate.GetSignatureForError ());
2173 // Run constraints check on all possible generic types
2174 if (base_type != null && base_type_expr != null) {
2175 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
2178 if (iface_exprs != null) {
2179 foreach (var iface_type in iface_exprs) {
2180 if (iface_type == null)
2183 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2188 if (all_tp_builders != null) {
2189 int current_starts_index = CurrentTypeParametersStartIndex;
2190 for (int i = 0; i < all_tp_builders.Length; i++) {
2191 if (i < current_starts_index) {
2192 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2194 var tp = CurrentTypeParameters [i - current_starts_index];
2195 tp.CheckGenericConstraints (!IsObsolete);
2201 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2202 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2205 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2206 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2211 for (int i = 0; i < members.Count; i++) {
2213 if ((m.caching_flags & Flags.CloseTypeCreated) != 0)
2220 CheckAttributeClsCompliance ();
2222 if (pending != null)
2223 pending.VerifyPendingMethods ();
2227 void CheckAttributeClsCompliance ()
2229 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2232 foreach (var m in members) {
2233 var c = m as Constructor;
2237 if (c.HasCompliantArgs)
2241 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2244 public sealed override void EmitContainer ()
2246 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2252 public override void CloseContainer ()
2254 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2257 // Close base type container first to avoid TypeLoadException
2258 if (spec.BaseType != null) {
2259 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2260 if (btype != null) {
2261 btype.CloseContainer ();
2263 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2269 caching_flags |= Flags.CloseTypeCreated;
2270 TypeBuilder.CreateType ();
2271 } catch (TypeLoadException) {
2273 // This is fine, the code still created the type
2275 } catch (Exception e) {
2276 throw new InternalErrorException (this, e);
2279 base.CloseContainer ();
2282 initialized_fields = null;
2283 initialized_static_fields = null;
2285 OptAttributes = null;
2289 // Performs the validation on a Method's modifiers (properties have
2290 // the same properties).
2292 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2294 public bool MethodModifiersValid (MemberCore mc)
2296 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2297 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2299 var flags = mc.ModFlags;
2302 // At most one of static, virtual or override
2304 if ((flags & Modifiers.STATIC) != 0){
2305 if ((flags & vao) != 0){
2306 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2307 mc.GetSignatureForError ());
2312 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2313 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2314 mc.GetSignatureForError ());
2319 // If the declaration includes the abstract modifier, then the
2320 // declaration does not include static, virtual or extern
2322 if ((flags & Modifiers.ABSTRACT) != 0){
2323 if ((flags & Modifiers.EXTERN) != 0){
2325 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2329 if ((flags & Modifiers.SEALED) != 0) {
2330 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2334 if ((flags & Modifiers.VIRTUAL) != 0){
2335 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2339 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2340 Report.SymbolRelatedToPreviousError (this);
2341 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2342 mc.GetSignatureForError (), GetSignatureForError ());
2347 if ((flags & Modifiers.PRIVATE) != 0){
2348 if ((flags & vao) != 0){
2349 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2354 if ((flags & Modifiers.SEALED) != 0){
2355 if ((flags & Modifiers.OVERRIDE) == 0){
2356 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2364 protected override bool VerifyClsCompliance ()
2366 if (!base.VerifyClsCompliance ())
2369 // Check all container names for user classes
2370 if (Kind != MemberKind.Delegate)
2371 MemberCache.VerifyClsCompliance (Definition, Report);
2373 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2374 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2375 GetSignatureForError (), BaseType.GetSignatureForError ());
2381 /// Performs checks for an explicit interface implementation. First it
2382 /// checks whether the `interface_type' is a base inteface implementation.
2383 /// Then it checks whether `name' exists in the interface type.
2385 public bool VerifyImplements (InterfaceMemberBase mb)
2387 var ifaces = PartialContainer.Interfaces;
2388 if (ifaces != null) {
2389 foreach (TypeSpec t in ifaces){
2390 if (t == mb.InterfaceType)
2393 var expanded_base = t.Interfaces;
2394 if (expanded_base == null)
2397 foreach (var bt in expanded_base) {
2398 if (bt == mb.InterfaceType)
2404 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2405 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2406 mb.GetSignatureForError (), mb.InterfaceType.GetSignatureForError ());
2411 // Used for visiblity checks to tests whether this definition shares
2412 // base type baseType, it does member-definition search
2414 public bool IsBaseTypeDefinition (TypeSpec baseType)
2416 // RootContext check
2417 if (TypeBuilder == null)
2422 if (type.MemberDefinition == baseType.MemberDefinition)
2425 type = type.BaseType;
2426 } while (type != null);
2431 public override bool IsClsComplianceRequired ()
2434 return PartialContainer.IsClsComplianceRequired ();
2436 return base.IsClsComplianceRequired ();
2439 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2441 return Module.DeclaringAssembly == assembly;
2444 public virtual bool IsUnmanagedType ()
2449 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2451 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2455 // Public function used to locate types.
2457 // Returns: Type or null if they type can not be found.
2459 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2461 FullNamedExpression e;
2462 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2468 var tp = CurrentTypeParameters;
2470 TypeParameter tparam = tp.Find (name);
2472 e = new TypeParameterExpr (tparam, Location.Null);
2477 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2479 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2480 e = new TypeExpression (t, Location.Null);
2482 var errors = Compiler.Report.Errors;
2483 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2485 // TODO: LookupNamespaceOrType does more than just lookup. The result
2486 // cannot be cached or the error reporting won't happen
2487 if (errors != Compiler.Report.Errors)
2492 // TODO MemberCache: How to cache arity stuff ?
2493 if (arity == 0 && mode == LookupMode.Normal)
2499 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2501 // Has any nested type
2502 // Does not work, because base type can have
2503 //if (PartialContainer.Types == null)
2506 var container = PartialContainer.CurrentType;
2507 return MemberCache.FindNestedType (container, name, arity);
2510 public void Mark_HasEquals ()
2512 cached_method |= CachedMethods.Equals;
2515 public void Mark_HasGetHashCode ()
2517 cached_method |= CachedMethods.GetHashCode;
2520 public override void WriteDebugSymbol (MonoSymbolFile file)
2525 foreach (var m in members) {
2526 m.WriteDebugSymbol (file);
2531 /// Method container contains Equals method
2533 public bool HasEquals {
2535 return (cached_method & CachedMethods.Equals) != 0;
2540 /// Method container contains GetHashCode method
2542 public bool HasGetHashCode {
2544 return (cached_method & CachedMethods.GetHashCode) != 0;
2548 public bool HasStaticFieldInitializer {
2550 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2554 cached_method |= CachedMethods.HasStaticFieldInitializer;
2556 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2560 public override string DocCommentHeader {
2561 get { return "T:"; }
2565 public abstract class ClassOrStruct : TypeDefinition
2567 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2569 SecurityType declarative_security;
2570 protected Constructor generated_primary_constructor;
2572 protected ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2573 : base (parent, name, attrs, kind)
2577 public ToplevelBlock PrimaryConstructorBlock { get; set; }
2579 protected override TypeAttributes TypeAttr {
2581 TypeAttributes ta = base.TypeAttr;
2582 if (!has_static_constructor)
2583 ta |= TypeAttributes.BeforeFieldInit;
2585 if (Kind == MemberKind.Class) {
2586 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2588 ta |= StaticClassAttribute;
2590 ta |= TypeAttributes.SequentialLayout;
2597 public override void AddNameToContainer (MemberCore symbol, string name)
2599 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2600 if (symbol is TypeParameter) {
2601 Report.Error (694, symbol.Location,
2602 "Type parameter `{0}' has same name as containing type, or method",
2603 symbol.GetSignatureForError ());
2607 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2608 if (imb == null || !imb.IsExplicitImpl) {
2609 Report.SymbolRelatedToPreviousError (this);
2610 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2611 symbol.GetSignatureForError ());
2616 base.AddNameToContainer (symbol, name);
2619 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2621 if (a.IsValidSecurityAttribute ()) {
2622 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2626 if (a.Type == pa.StructLayout) {
2627 PartialContainer.HasStructLayout = true;
2628 if (a.IsExplicitLayoutKind ())
2629 PartialContainer.HasExplicitLayout = true;
2632 if (a.Type == pa.Dynamic) {
2633 a.Error_MisusedDynamicAttribute ();
2637 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2641 /// Defines the default constructors
2643 protected virtual Constructor DefineDefaultConstructor (bool is_static)
2645 // The default instance constructor is public
2646 // If the class is abstract, the default constructor is protected
2647 // The default static constructor is private
2650 ParametersCompiled parameters = null;
2652 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2653 parameters = ParametersCompiled.EmptyReadOnlyParameters;
2655 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2656 parameters = PrimaryConstructorParameters ?? ParametersCompiled.EmptyReadOnlyParameters;
2659 var c = new Constructor (this, MemberName.Name, mods, null, parameters, Location);
2660 if (Kind == MemberKind.Class)
2661 c.Initializer = new GeneratedBaseInitializer (Location, PrimaryConstructorBaseArguments);
2663 if (PrimaryConstructorParameters != null && !is_static)
2664 c.IsPrimaryConstructor = true;
2666 AddConstructor (c, true);
2667 if (PrimaryConstructorBlock == null) {
2668 c.Block = new ToplevelBlock (Compiler, parameters, Location) {
2669 IsCompilerGenerated = true
2672 c.Block = PrimaryConstructorBlock;
2678 protected override bool DoDefineMembers ()
2680 CheckProtectedModifier ();
2682 if (PrimaryConstructorParameters != null) {
2683 foreach (Parameter p in PrimaryConstructorParameters.FixedParameters) {
2684 if (p.Name == MemberName.Name) {
2685 Report.Error (8039, p.Location, "Primary constructor of type `{0}' has parameter of same name as containing type",
2686 GetSignatureForError ());
2689 if (CurrentTypeParameters != null) {
2690 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
2691 var tp = CurrentTypeParameters [i];
2692 if (p.Name == tp.Name) {
2693 Report.Error (8038, p.Location, "Primary constructor of type `{0}' has parameter of same name as type parameter `{1}'",
2694 GetSignatureForError (), p.GetSignatureForError ());
2701 base.DoDefineMembers ();
2706 public override void Emit ()
2708 if (!has_static_constructor && HasStaticFieldInitializer) {
2709 var c = DefineDefaultConstructor (true);
2715 if (declarative_security != null) {
2716 foreach (var de in declarative_security) {
2718 TypeBuilder.__AddDeclarativeSecurity (de);
2720 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2728 public sealed class Class : ClassOrStruct
2730 const Modifiers AllowedModifiers =
2733 Modifiers.PROTECTED |
2734 Modifiers.INTERNAL |
2736 Modifiers.ABSTRACT |
2741 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2742 : base (parent, name, attrs, MemberKind.Class)
2744 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2745 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2746 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2749 public override void Accept (StructuralVisitor visitor)
2751 visitor.Visit (this);
2754 public override void SetBaseTypes (List<FullNamedExpression> baseTypes)
2756 var pmn = MemberName;
2757 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2758 Report.Error (537, Location,
2759 "The class System.Object cannot have a base class or implement an interface.");
2761 base.SetBaseTypes (baseTypes);
2764 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2766 if (a.Type == pa.AttributeUsage) {
2767 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2768 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2772 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2773 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2777 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2778 a.Error_MissingGuidAttribute ();
2782 if (a.Type == pa.Extension) {
2783 a.Error_MisusedExtensionAttribute ();
2787 if (a.Type.IsConditionallyExcluded (this))
2790 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2793 public override AttributeTargets AttributeTargets {
2795 return AttributeTargets.Class;
2799 protected override bool DoDefineMembers ()
2801 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2802 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2805 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2806 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2810 if (PrimaryConstructorParameters != null) {
2811 Report.Error (-800, Location, "`{0}': Static classes cannot have primary constructor", GetSignatureForError ());
2812 PrimaryConstructorParameters = null;
2815 foreach (var m in Members) {
2816 if (m is Operator) {
2817 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2821 if (m is Destructor) {
2822 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2827 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2831 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2834 if (m is Constructor) {
2835 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2839 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2842 if (!PartialContainer.HasInstanceConstructor || PrimaryConstructorParameters != null)
2843 generated_primary_constructor = DefineDefaultConstructor (false);
2846 return base.DoDefineMembers ();
2849 public override void Emit ()
2853 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2854 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2856 if (base_type != null && base_type.HasDynamicElement) {
2857 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2861 public override void GetCompletionStartingWith (string prefix, List<string> results)
2863 base.GetCompletionStartingWith (prefix, results);
2866 while (bt != null) {
2867 results.AddRange (MemberCache.GetCompletitionMembers (this, bt, prefix).Where (l => l.IsStatic).Select (l => l.Name));
2872 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2874 var ifaces = base.ResolveBaseTypes (out base_class);
2876 if (base_class == null) {
2877 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2878 base_type = Compiler.BuiltinTypes.Object;
2880 if (base_type.IsGenericParameter){
2881 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2882 GetSignatureForError (), base_type.GetSignatureForError ());
2883 } else if (base_type.IsStatic) {
2884 Report.SymbolRelatedToPreviousError (base_type);
2885 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2886 GetSignatureForError (), base_type.GetSignatureForError ());
2887 } else if (base_type.IsSealed) {
2888 Report.SymbolRelatedToPreviousError (base_type);
2889 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2890 GetSignatureForError (), base_type.GetSignatureForError ());
2891 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2892 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2893 GetSignatureForError (), base_type.GetSignatureForError ());
2896 switch (base_type.BuiltinType) {
2897 case BuiltinTypeSpec.Type.Enum:
2898 case BuiltinTypeSpec.Type.ValueType:
2899 case BuiltinTypeSpec.Type.MulticastDelegate:
2900 case BuiltinTypeSpec.Type.Delegate:
2901 case BuiltinTypeSpec.Type.Array:
2902 if (!(spec is BuiltinTypeSpec)) {
2903 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2904 GetSignatureForError (), base_type.GetSignatureForError ());
2906 base_type = Compiler.BuiltinTypes.Object;
2911 if (!IsAccessibleAs (base_type)) {
2912 Report.SymbolRelatedToPreviousError (base_type);
2913 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2914 base_type.GetSignatureForError (), GetSignatureForError ());
2918 if (PartialContainer.IsStatic && ifaces != null) {
2919 foreach (var t in ifaces)
2920 Report.SymbolRelatedToPreviousError (t);
2921 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2927 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2928 /// Valid only for attribute classes.
2929 public override string[] ConditionalConditions ()
2931 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2934 caching_flags &= ~Flags.Excluded_Undetected;
2936 if (OptAttributes == null)
2939 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2943 string[] conditions = new string[attrs.Length];
2944 for (int i = 0; i < conditions.Length; ++i)
2945 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2947 caching_flags |= Flags.Excluded;
2952 public sealed class Struct : ClassOrStruct
2954 bool is_unmanaged, has_unmanaged_check_done;
2958 // Modifiers allowed in a struct declaration
2960 const Modifiers AllowedModifiers =
2963 Modifiers.PROTECTED |
2964 Modifiers.INTERNAL |
2968 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2969 : base (parent, name, attrs, MemberKind.Struct)
2971 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2972 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2973 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2976 public override AttributeTargets AttributeTargets {
2978 return AttributeTargets.Struct;
2982 public override void Accept (StructuralVisitor visitor)
2984 visitor.Visit (this);
2987 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2989 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2992 // When struct constains fixed fixed and struct layout has explicitly
2993 // set CharSet, its value has to be propagated to compiler generated
2996 if (a.Type == pa.StructLayout) {
2997 var value = a.GetNamedValue ("CharSet");
3001 for (int i = 0; i < Members.Count; ++i) {
3002 FixedField ff = Members [i] as FixedField;
3006 ff.CharSet = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
3011 bool CheckStructCycles ()
3017 foreach (var member in Members) {
3018 var field = member as Field;
3022 TypeSpec ftype = field.Spec.MemberType;
3023 if (!ftype.IsStruct)
3026 if (ftype is BuiltinTypeSpec)
3029 foreach (var targ in ftype.TypeArguments) {
3030 if (!CheckFieldTypeCycle (targ)) {
3031 Report.Error (523, field.Location,
3032 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3033 field.GetSignatureForError (), ftype.GetSignatureForError ());
3039 // Static fields of exactly same type are allowed
3041 if (field.IsStatic && ftype == CurrentType)
3044 if (!CheckFieldTypeCycle (ftype)) {
3045 Report.Error (523, field.Location,
3046 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3047 field.GetSignatureForError (), ftype.GetSignatureForError ());
3056 static bool CheckFieldTypeCycle (TypeSpec ts)
3058 var fts = ts.MemberDefinition as Struct;
3062 return fts.CheckStructCycles ();
3065 protected override bool DoDefineMembers ()
3067 if (PrimaryConstructorParameters != null)
3068 generated_primary_constructor = DefineDefaultConstructor (false);
3070 return base.DoDefineMembers ();
3073 public override void Emit ()
3075 CheckStructCycles ();
3080 bool HasExplicitConstructor ()
3082 foreach (var m in Members) {
3083 var c = m as Constructor;
3087 if (!c.ParameterInfo.IsEmpty)
3094 public override bool IsUnmanagedType ()
3096 if (has_unmanaged_check_done)
3097 return is_unmanaged;
3099 if (requires_delayed_unmanagedtype_check)
3102 var parent_def = Parent.PartialContainer;
3103 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
3104 has_unmanaged_check_done = true;
3108 if (first_nonstatic_field != null) {
3109 requires_delayed_unmanagedtype_check = true;
3111 foreach (var member in Members) {
3112 var f = member as Field;
3119 // It can happen when recursive unmanaged types are defined
3120 // struct S { S* s; }
3121 TypeSpec mt = f.MemberType;
3129 has_unmanaged_check_done = true;
3133 has_unmanaged_check_done = true;
3136 is_unmanaged = true;
3140 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
3142 var ifaces = base.ResolveBaseTypes (out base_class);
3143 base_type = Compiler.BuiltinTypes.ValueType;
3147 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
3149 if ((field.ModFlags & Modifiers.STATIC) == 0 && !HasExplicitConstructor ()) {
3150 Report.Error (8054, field.Location, "`{0}': Structs without explicit constructors cannot contain members with initializers",
3151 field.GetSignatureForError ());
3156 base.RegisterFieldForInitialization (field, expression);
3163 public sealed class Interface : TypeDefinition {
3166 /// Modifiers allowed in a class declaration
3168 const Modifiers AllowedModifiers =
3171 Modifiers.PROTECTED |
3172 Modifiers.INTERNAL |
3176 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
3177 : base (parent, name, attrs, MemberKind.Interface)
3179 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3181 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
3182 spec = new TypeSpec (Kind, null, this, null, ModFlags);
3187 public override AttributeTargets AttributeTargets {
3189 return AttributeTargets.Interface;
3193 protected override TypeAttributes TypeAttr {
3195 const TypeAttributes DefaultTypeAttributes =
3196 TypeAttributes.AutoLayout |
3197 TypeAttributes.Abstract |
3198 TypeAttributes.Interface;
3200 return base.TypeAttr | DefaultTypeAttributes;
3206 public override void Accept (StructuralVisitor visitor)
3208 visitor.Visit (this);
3211 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3213 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3214 a.Error_MissingGuidAttribute ();
3218 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3221 protected override bool VerifyClsCompliance ()
3223 if (!base.VerifyClsCompliance ())
3226 if (iface_exprs != null) {
3227 foreach (var iface in iface_exprs) {
3228 if (iface.IsCLSCompliant ())
3231 Report.SymbolRelatedToPreviousError (iface);
3232 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3233 GetSignatureForError (), iface.GetSignatureForError ());
3241 public abstract class InterfaceMemberBase : MemberBase
3244 // Common modifiers allowed in a class declaration
3246 protected const Modifiers AllowedModifiersClass =
3249 Modifiers.PROTECTED |
3250 Modifiers.INTERNAL |
3255 Modifiers.OVERRIDE |
3256 Modifiers.ABSTRACT |
3261 // Common modifiers allowed in a struct declaration
3263 protected const Modifiers AllowedModifiersStruct =
3266 Modifiers.PROTECTED |
3267 Modifiers.INTERNAL |
3270 Modifiers.OVERRIDE |
3275 // Common modifiers allowed in a interface declaration
3277 protected const Modifiers AllowedModifiersInterface =
3282 // Whether this is an interface member.
3284 public bool IsInterface;
3287 // If true, this is an explicit interface implementation
3289 public readonly bool IsExplicitImpl;
3291 protected bool is_external_implementation;
3294 // The interface type we are explicitly implementing
3296 public TypeSpec InterfaceType;
3299 // The method we're overriding if this is an override method.
3301 protected MethodSpec base_method;
3303 readonly Modifiers explicit_mod_flags;
3304 public MethodAttributes flags;
3306 protected InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3307 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3309 IsInterface = parent.Kind == MemberKind.Interface;
3310 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3311 explicit_mod_flags = mod;
3314 public abstract Variance ExpectedMemberTypeVariance { get; }
3316 protected override bool CheckBase ()
3318 if (!base.CheckBase ())
3321 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3322 CheckForDuplications ();
3327 // For System.Object only
3328 if (Parent.BaseType == null)
3331 MemberSpec candidate;
3332 bool overrides = false;
3333 var base_member = FindBaseMember (out candidate, ref overrides);
3335 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3336 if (base_member == null) {
3337 if (candidate == null) {
3338 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3339 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3340 "object.Finalize()");
3342 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3343 GetSignatureForError (), SimpleName.GetMemberType (this));
3346 Report.SymbolRelatedToPreviousError (candidate);
3348 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3349 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3350 else if (this is PropertyBase)
3351 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3352 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3354 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3355 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3362 // Handles ambiguous overrides
3364 if (candidate != null) {
3365 Report.SymbolRelatedToPreviousError (candidate);
3366 Report.SymbolRelatedToPreviousError (base_member);
3368 // Get member definition for error reporting
3369 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3370 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3372 Report.Error (462, Location,
3373 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3374 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3377 if (!CheckOverrideAgainstBase (base_member))
3380 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3382 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3383 Report.SymbolRelatedToPreviousError (base_member);
3384 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3385 GetSignatureForError (), base_member.GetSignatureForError ());
3388 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3389 Report.SymbolRelatedToPreviousError (base_member);
3390 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3391 GetSignatureForError (), base_member.GetSignatureForError ());
3395 base_method = base_member as MethodSpec;
3399 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3400 base_member = candidate;
3402 if (base_member == null) {
3403 if ((ModFlags & Modifiers.NEW) != 0) {
3404 if (base_member == null) {
3405 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3406 GetSignatureForError ());
3410 if ((ModFlags & Modifiers.NEW) == 0) {
3411 ModFlags |= Modifiers.NEW;
3412 if (!IsCompilerGenerated) {
3413 Report.SymbolRelatedToPreviousError (base_member);
3414 if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3415 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",
3416 GetSignatureForError (), base_member.GetSignatureForError ());
3418 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3419 GetSignatureForError (), base_member.GetSignatureForError ());
3424 if (!IsInterface && base_member.IsAbstract && !overrides && !IsStatic) {
3425 Report.SymbolRelatedToPreviousError (base_member);
3426 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3427 GetSignatureForError (), base_member.GetSignatureForError ());
3434 protected virtual bool CheckForDuplications ()
3436 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3440 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3441 // that have been defined.
3443 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3447 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3448 Report.SymbolRelatedToPreviousError (base_member);
3449 Report.Error (506, Location,
3450 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3451 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3455 // Now we check that the overriden method is not final
3456 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3457 Report.SymbolRelatedToPreviousError (base_member);
3458 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3459 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3463 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3464 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3465 Report.SymbolRelatedToPreviousError (base_member);
3466 if (this is PropertyBasedMember) {
3467 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3468 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3470 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3471 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3479 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3481 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3482 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3484 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3486 // It must be at least "protected"
3488 if ((thisp & Modifiers.PROTECTED) == 0) {
3493 // when overriding protected internal, the method can be declared
3494 // protected internal only within the same assembly or assembly
3495 // which has InternalsVisibleTo
3497 if ((thisp & Modifiers.INTERNAL) != 0) {
3498 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3502 // protected overriding protected internal inside same assembly
3503 // requires internal modifier as well
3505 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3512 return thisp == base_classp;
3515 public override bool Define ()
3518 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3519 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3521 flags = MethodAttributes.Public |
3522 MethodAttributes.Abstract |
3523 MethodAttributes.HideBySig |
3524 MethodAttributes.NewSlot |
3525 MethodAttributes.Virtual;
3527 Parent.PartialContainer.MethodModifiersValid (this);
3529 flags = ModifiersExtensions.MethodAttr (ModFlags);
3532 if (IsExplicitImpl) {
3533 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3534 if (InterfaceType == null)
3537 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3538 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3539 GetSignatureForError ());
3542 if (!InterfaceType.IsInterface) {
3543 Report.SymbolRelatedToPreviousError (InterfaceType);
3544 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3545 InterfaceType.GetSignatureForError ());
3547 Parent.PartialContainer.VerifyImplements (this);
3550 Modifiers allowed_explicit = Modifiers.AllowedExplicitImplFlags;
3552 allowed_explicit |= Modifiers.ASYNC;
3554 ModifiersExtensions.Check (allowed_explicit, explicit_mod_flags, 0, Location, Report);
3557 return base.Define ();
3560 protected bool DefineParameters (ParametersCompiled parameters)
3562 if (!parameters.Resolve (this))
3566 for (int i = 0; i < parameters.Count; ++i) {
3567 Parameter p = parameters [i];
3569 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3570 p.Warning_UselessOptionalParameter (Report);
3572 if (p.CheckAccessibility (this))
3575 TypeSpec t = parameters.Types [i];
3576 Report.SymbolRelatedToPreviousError (t);
3577 if (this is Indexer)
3578 Report.Error (55, Location,
3579 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3580 t.GetSignatureForError (), GetSignatureForError ());
3581 else if (this is Operator)
3582 Report.Error (57, Location,
3583 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3584 t.GetSignatureForError (), GetSignatureForError ());
3586 Report.Error (51, Location,
3587 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3588 t.GetSignatureForError (), GetSignatureForError ());
3594 protected override void DoMemberTypeDependentChecks ()
3596 base.DoMemberTypeDependentChecks ();
3598 VarianceDecl.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3601 public override void Emit()
3603 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3604 // We are more strict than csc and report this as an error because SRE does not allow emit that
3605 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3606 if (this is Constructor) {
3607 Report.Warning (824, 1, Location,
3608 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3610 Report.Warning (626, 1, Location,
3611 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3612 GetSignatureForError ());
3619 public override bool EnableOverloadChecks (MemberCore overload)
3622 // Two members can differ in their explicit interface
3623 // type parameter only
3625 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3626 if (imb != null && imb.IsExplicitImpl) {
3627 if (IsExplicitImpl) {
3628 caching_flags |= Flags.MethodOverloadsExist;
3633 return IsExplicitImpl;
3636 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3638 var base_modifiers = base_member.Modifiers;
3640 // Remove internal modifier from types which are not internally accessible
3641 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3642 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3643 base_modifiers = Modifiers.PROTECTED;
3645 Report.SymbolRelatedToPreviousError (base_member);
3646 Report.Error (507, member.Location,
3647 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3648 member.GetSignatureForError (),
3649 ModifiersExtensions.AccessibilityName (base_modifiers),
3650 base_member.GetSignatureForError ());
3653 protected void Error_StaticReturnType ()
3655 Report.Error (722, Location,
3656 "`{0}': static types cannot be used as return types",
3657 MemberType.GetSignatureForError ());
3661 /// Gets base method and its return type
3663 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3665 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3669 // The "short" name of this property / indexer / event. This is the
3670 // name without the explicit interface.
3672 public string ShortName {
3673 get { return MemberName.Name; }
3677 // Returns full metadata method name
3679 public string GetFullName (MemberName name)
3681 return GetFullName (name.Name);
3684 public string GetFullName (string name)
3686 if (!IsExplicitImpl)
3690 // When dealing with explicit members a full interface type
3691 // name is added to member name to avoid possible name conflicts
3693 // We use CSharpName which gets us full name with benefit of
3694 // replacing predefined names which saves some space and name
3697 return InterfaceType.GetSignatureForError () + "." + name;
3700 public override string GetSignatureForDocumentation ()
3703 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetExplicitNameSignatureForDocumentation () + "#" + ShortName;
3705 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3708 public override bool IsUsed
3710 get { return IsExplicitImpl || base.IsUsed; }
3713 public override void SetConstraints (List<Constraints> constraints_list)
3715 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3716 Report.Error (460, Location,
3717 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3718 GetSignatureForError ());
3721 base.SetConstraints (constraints_list);
3725 public abstract class MemberBase : MemberCore
3727 protected FullNamedExpression type_expr;
3728 protected TypeSpec member_type;
3729 public new TypeDefinition Parent;
3731 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3732 : base (parent, name, attrs)
3734 this.Parent = parent;
3735 this.type_expr = type;
3737 if (name != MemberName.Null)
3738 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3743 public TypeSpec MemberType {
3749 public FullNamedExpression TypeExpression {
3758 // Main member define entry
3760 public override bool Define ()
3762 DoMemberTypeIndependentChecks ();
3765 // Returns false only when type resolution failed
3767 if (!ResolveMemberType ())
3770 DoMemberTypeDependentChecks ();
3775 // Any type_name independent checks
3777 protected virtual void DoMemberTypeIndependentChecks ()
3779 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3780 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3781 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3782 GetSignatureForError (), Parent.GetSignatureForError ());
3787 // Any type_name dependent checks
3789 protected virtual void DoMemberTypeDependentChecks ()
3791 // verify accessibility
3792 if (!IsAccessibleAs (MemberType)) {
3793 Report.SymbolRelatedToPreviousError (MemberType);
3794 if (this is Property)
3795 Report.Error (53, Location,
3796 "Inconsistent accessibility: property type `" +
3797 MemberType.GetSignatureForError () + "' is less " +
3798 "accessible than property `" + GetSignatureForError () + "'");
3799 else if (this is Indexer)
3800 Report.Error (54, Location,
3801 "Inconsistent accessibility: indexer return type `" +
3802 MemberType.GetSignatureForError () + "' is less " +
3803 "accessible than indexer `" + GetSignatureForError () + "'");
3804 else if (this is MethodCore) {
3805 if (this is Operator)
3806 Report.Error (56, Location,
3807 "Inconsistent accessibility: return type `" +
3808 MemberType.GetSignatureForError () + "' is less " +
3809 "accessible than operator `" + GetSignatureForError () + "'");
3811 Report.Error (50, Location,
3812 "Inconsistent accessibility: return type `" +
3813 MemberType.GetSignatureForError () + "' is less " +
3814 "accessible than method `" + GetSignatureForError () + "'");
3815 } else if (this is Event) {
3816 Report.Error (7025, Location,
3817 "Inconsistent accessibility: event type `{0}' is less accessible than event `{1}'",
3818 MemberType.GetSignatureForError (), GetSignatureForError ());
3820 Report.Error (52, Location,
3821 "Inconsistent accessibility: field type `" +
3822 MemberType.GetSignatureForError () + "' is less " +
3823 "accessible than field `" + GetSignatureForError () + "'");
3828 protected void IsTypePermitted ()
3830 if (MemberType.IsSpecialRuntimeType) {
3831 if (Parent is StateMachine) {
3832 Report.Error (4012, Location,
3833 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3834 MemberType.GetSignatureForError ());
3835 } else if (Parent is HoistedStoreyClass) {
3836 Report.Error (4013, Location,
3837 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3838 MemberType.GetSignatureForError ());
3840 Report.Error (610, Location,
3841 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3846 protected virtual bool CheckBase ()
3848 CheckProtectedModifier ();
3853 public override string GetSignatureForDocumentation ()
3855 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3858 protected virtual bool ResolveMemberType ()
3860 if (member_type != null)
3861 throw new InternalErrorException ("Multi-resolve");
3863 member_type = type_expr.ResolveAsType (this);
3864 return member_type != null;