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. Used
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);
301 if (PartialContainer != null && PartialContainer != this) {
309 public virtual void ExpandBaseInterfaces ()
311 if (containers != null) {
312 foreach (TypeContainer tc in containers) {
313 tc.ExpandBaseInterfaces ();
318 protected virtual void DefineNamespace ()
320 if (containers != null) {
321 foreach (var tc in containers) {
323 tc.DefineNamespace ();
324 } catch (Exception e) {
325 throw new InternalErrorException (tc, e);
331 protected virtual void DoDefineContainer ()
335 public virtual void EmitContainer ()
337 if (containers != null) {
338 for (int i = 0; i < containers.Count; ++i)
339 containers[i].EmitContainer ();
343 protected void Error_MissingPartialModifier (MemberCore type)
345 Report.Error (260, type.Location,
346 "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
347 type.GetSignatureForError ());
350 public override string GetSignatureForDocumentation ()
352 if (Parent != null && Parent.MemberName != null)
353 return Parent.GetSignatureForDocumentation () + "." + MemberName.GetSignatureForDocumentation ();
355 return MemberName.GetSignatureForDocumentation ();
358 public override string GetSignatureForError ()
360 if (Parent != null && Parent.MemberName != null)
361 return Parent.GetSignatureForError () + "." + MemberName.GetSignatureForError ();
363 return MemberName.GetSignatureForError ();
366 public virtual string GetSignatureForMetadata ()
368 var sb = new StringBuilder ();
369 CreateMetadataName (sb);
370 return sb.ToString ();
373 public virtual void RemoveContainer (TypeContainer cont)
375 if (containers != null)
376 containers.Remove (cont);
378 var tc = Parent == Module ? Module : this;
379 tc.defined_names.Remove (cont.MemberName.Basename);
382 public virtual void VerifyMembers ()
384 if (containers != null) {
385 foreach (TypeContainer tc in containers)
390 public override void WriteDebugSymbol (MonoSymbolFile file)
392 if (containers != null) {
393 foreach (TypeContainer tc in containers) {
394 tc.WriteDebugSymbol (file);
400 public abstract class TypeDefinition : TypeContainer, ITypeDefinition
403 // Different context is needed when resolving type container base
404 // types. Type names come from the parent scope but type parameter
405 // names from the container scope.
407 public struct BaseContext : IMemberContext
411 public BaseContext (TypeContainer tc)
416 #region IMemberContext Members
418 public CompilerContext Compiler {
419 get { return tc.Compiler; }
422 public TypeSpec CurrentType {
423 get { return tc.PartialContainer.CurrentType; }
426 public TypeParameters CurrentTypeParameters {
427 get { return tc.PartialContainer.CurrentTypeParameters; }
430 public MemberCore CurrentMemberDefinition {
434 public bool IsObsolete {
435 get { return tc.IsObsolete; }
438 public bool IsUnsafe {
439 get { return tc.IsUnsafe; }
442 public bool IsStatic {
443 get { return tc.IsStatic; }
446 public ModuleContainer Module {
447 get { return tc.Module; }
450 public string GetSignatureForError ()
452 return tc.GetSignatureForError ();
455 public ExtensionMethodCandidates LookupExtensionMethod (string name, int arity)
460 public FullNamedExpression LookupNamespaceAlias (string name)
462 return tc.Parent.LookupNamespaceAlias (name);
465 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
468 var tp = CurrentTypeParameters;
470 TypeParameter t = tp.Find (name);
472 return new TypeParameterExpr (t, loc);
476 return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc);
486 GetHashCode = 1 << 1,
487 HasStaticFieldInitializer = 1 << 2
490 readonly List<MemberCore> members;
492 // Holds a list of fields that have initializers
493 protected List<FieldInitializer> initialized_fields;
495 // Holds a list of static fields that have initializers
496 protected List<FieldInitializer> initialized_static_fields;
498 Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
500 Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
503 // Points to the first non-static field added to the container.
505 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
506 // and the first one's as good as any.
508 protected FieldBase first_nonstatic_field;
511 // This one is computed after we can distinguish interfaces
512 // from classes from the arraylist `type_bases'
514 protected TypeSpec base_type;
515 FullNamedExpression base_type_expr; // TODO: It's temporary variable
516 protected TypeSpec[] iface_exprs;
518 protected List<FullNamedExpression> type_bases;
520 // Partial parts for classes only
521 List<TypeDefinition> class_partial_parts;
523 TypeDefinition InTransit;
525 public TypeBuilder TypeBuilder;
526 GenericTypeParameterBuilder[] all_tp_builders;
528 // All recursive type parameters put together sharing same
529 // TypeParameter instances
531 TypeParameters all_type_parameters;
533 public const string DefaultIndexerName = "Item";
535 bool has_normal_indexers;
538 bool members_defined;
539 bool members_defined_ok;
540 protected bool has_static_constructor;
542 private CachedMethods cached_method;
544 protected TypeSpec spec;
545 TypeSpec current_type;
547 public int DynamicSitesCounter;
548 public int AnonymousMethodsCounter;
549 public int MethodGroupsCounter;
551 static readonly string[] attribute_targets = new [] { "type" };
552 static readonly string[] attribute_targets_primary = new [] { "type", "method" };
555 /// The pending methods that need to be implemented
556 // (interfaces or abstract methods)
558 PendingImplementation pending;
560 protected TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
561 : base (parent, name, attrs, kind)
563 PartialContainer = this;
564 members = new List<MemberCore> ();
569 public List<FullNamedExpression> BaseTypeExpressions {
575 public override TypeSpec CurrentType {
577 if (current_type == null) {
578 if (IsGenericOrParentIsGeneric) {
580 // Switch to inflated version as it's used by all expressions
582 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Types;
583 current_type = spec.MakeGenericType (this, targs);
593 public override TypeParameters CurrentTypeParameters {
595 return PartialContainer.MemberName.TypeParameters;
599 int CurrentTypeParametersStartIndex {
601 int total = all_tp_builders.Length;
602 if (CurrentTypeParameters != null) {
603 return total - CurrentTypeParameters.Count;
609 public virtual AssemblyDefinition DeclaringAssembly {
611 return Module.DeclaringAssembly;
615 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
617 return Module.DeclaringAssembly;
621 public TypeSpec Definition {
627 public bool HasMembersDefined {
629 return members_defined;
633 public bool HasInstanceConstructor {
635 return (caching_flags & Flags.HasInstanceConstructor) != 0;
638 caching_flags |= Flags.HasInstanceConstructor;
642 public bool HasInstanceField {
644 return (caching_flags & Flags.HasInstanceField) != 0;
647 caching_flags |= Flags.HasInstanceField;
651 // Indicated whether container has StructLayout attribute set Explicit
652 public bool HasExplicitLayout {
653 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
654 set { caching_flags |= Flags.HasExplicitLayout; }
657 public bool HasOperators {
659 return (caching_flags & Flags.HasUserOperators) != 0;
662 caching_flags |= Flags.HasUserOperators;
666 public bool HasStructLayout {
667 get { return (caching_flags & Flags.HasStructLayout) != 0; }
668 set { caching_flags |= Flags.HasStructLayout; }
671 public TypeSpec[] Interfaces {
677 public bool IsGenericOrParentIsGeneric {
679 return all_type_parameters != null;
683 public bool IsTopLevel {
685 return !(Parent is TypeDefinition);
689 public bool IsPartial {
691 return (ModFlags & Modifiers.PARTIAL) != 0;
695 bool ITypeDefinition.IsTypeForwarder {
701 bool ITypeDefinition.IsCyclicTypeForwarder {
708 // Returns true for secondary partial containers
712 return PartialContainer != this;
716 public MemberCache MemberCache {
718 return spec.MemberCache;
722 public List<MemberCore> Members {
728 string ITypeDefinition.Namespace {
731 while (p.Kind != MemberKind.Namespace)
734 return p.MemberName == null ? null : p.GetSignatureForError ();
738 public ParametersCompiled PrimaryConstructorParameters { get; set; }
740 public Arguments PrimaryConstructorBaseArguments { get; set; }
742 public Location PrimaryConstructorBaseArgumentsStart { get; set; }
744 public TypeParameters TypeParametersAll {
746 return all_type_parameters;
750 public override string[] ValidAttributeTargets {
752 return PrimaryConstructorParameters != null ? attribute_targets_primary : attribute_targets;
758 public override void Accept (StructuralVisitor visitor)
760 visitor.Visit (this);
763 public void AddMember (MemberCore symbol)
765 if (symbol.MemberName.ExplicitInterface != null) {
766 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
767 Report.Error (541, symbol.Location,
768 "`{0}': explicit interface declaration can only be declared in a class or struct",
769 symbol.GetSignatureForError ());
773 AddNameToContainer (symbol, symbol.MemberName.Name);
774 members.Add (symbol);
777 public override void AddTypeContainer (TypeContainer tc)
779 AddNameToContainer (tc, tc.MemberName.Basename);
781 base.AddTypeContainer (tc);
784 protected override void AddTypeContainerMember (TypeContainer tc)
788 if (containers == null)
789 containers = new List<TypeContainer> ();
791 base.AddTypeContainerMember (tc);
795 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
797 public virtual void AddNameToContainer (MemberCore symbol, string name)
799 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
803 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
804 PartialContainer.defined_names.Add (name, symbol);
808 if (symbol.EnableOverloadChecks (mc))
811 InterfaceMemberBase im = mc as InterfaceMemberBase;
812 if (im != null && im.IsExplicitImpl)
815 Report.SymbolRelatedToPreviousError (mc);
816 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
817 Error_MissingPartialModifier (symbol);
821 if (symbol is TypeParameter) {
822 Report.Error (692, symbol.Location,
823 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
825 Report.Error (102, symbol.Location,
826 "The type `{0}' already contains a definition for `{1}'",
827 GetSignatureForError (), name);
833 public void AddConstructor (Constructor c)
835 AddConstructor (c, false);
838 public void AddConstructor (Constructor c, bool isDefault)
840 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
842 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
844 if (is_static && c.ParameterInfo.IsEmpty) {
845 PartialContainer.has_static_constructor = true;
847 PartialContainer.HasInstanceConstructor = true;
853 public bool AddField (FieldBase field)
857 if ((field.ModFlags & Modifiers.STATIC) != 0)
860 if (!PartialContainer.HasInstanceField) {
861 PartialContainer.HasInstanceField = true;
862 PartialContainer.first_nonstatic_field = field;
866 if (Kind == MemberKind.Struct) {
867 var first_field = PartialContainer.first_nonstatic_field;
868 if (first_field.Parent != field.Parent) {
869 Report.SymbolRelatedToPreviousError (first_field.Parent);
870 Report.Warning (282, 3, field.Location,
871 "struct instance field `{0}' found in different declaration from instance field `{1}'",
872 field.GetSignatureForError (), first_field.GetSignatureForError ());
880 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
882 public void AddIndexer (Indexer i)
887 public void AddOperator (Operator op)
889 PartialContainer.HasOperators = true;
893 public void AddPartialPart (TypeDefinition part)
895 if (Kind != MemberKind.Class)
898 if (class_partial_parts == null)
899 class_partial_parts = new List<TypeDefinition> ();
901 class_partial_parts.Add (part);
904 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
906 if (a.Target == AttributeTargets.Method) {
907 foreach (var m in members) {
908 var c = m as Constructor;
912 if (c.IsPrimaryConstructor) {
913 c.ApplyAttributeBuilder (a, ctor, cdata, pa);
918 throw new InternalErrorException ();
921 if (has_normal_indexers && a.Type == pa.DefaultMember) {
922 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
926 if (a.Type == pa.Required) {
927 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
931 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
934 public override AttributeTargets AttributeTargets {
936 throw new NotSupportedException ();
940 public TypeSpec BaseType {
942 return spec.BaseType;
946 protected virtual TypeAttributes TypeAttr {
948 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
952 public int TypeParametersCount {
954 return MemberName.Arity;
958 TypeParameterSpec[] ITypeDefinition.TypeParameters {
960 var ctp = PartialContainer.CurrentTypeParameters;
961 return ctp == null ? TypeParameterSpec.EmptyTypes : ctp.Types;
965 public string GetAttributeDefaultMember ()
967 return indexer_name ?? DefaultIndexerName;
970 public bool IsComImport {
972 if (OptAttributes == null)
975 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
979 public void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
982 PartialContainer.RegisterFieldForInitialization (field, expression);
984 if ((field.ModFlags & Modifiers.STATIC) != 0){
985 if (initialized_static_fields == null) {
986 HasStaticFieldInitializer = true;
987 initialized_static_fields = new List<FieldInitializer> (4);
990 initialized_static_fields.Add (expression);
992 if (Kind == MemberKind.Struct) {
993 if (Compiler.Settings.Version != LanguageVersion.Experimental) {
994 Report.Error (573, expression.Location, "'{0}': Structs cannot have instance property or field initializers",
995 GetSignatureForError ());
999 if (initialized_fields == null)
1000 initialized_fields = new List<FieldInitializer> (4);
1002 initialized_fields.Add (expression);
1006 public void ResolveFieldInitializers (BlockContext ec)
1008 Debug.Assert (!IsPartialPart);
1011 if (initialized_static_fields == null)
1014 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
1016 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
1017 for (i = 0; i < initialized_static_fields.Count; ++i) {
1018 FieldInitializer fi = initialized_static_fields [i];
1019 ExpressionStatement s = fi.ResolveStatement (ec);
1021 s = EmptyExpressionStatement.Instance;
1022 } else if (!fi.IsSideEffectFree) {
1023 has_complex_initializer = true;
1029 for (i = 0; i < initialized_static_fields.Count; ++i) {
1030 FieldInitializer fi = initialized_static_fields [i];
1032 // Need special check to not optimize code like this
1033 // static int a = b = 5;
1034 // static int b = 0;
1036 if (!has_complex_initializer && fi.IsDefaultInitializer)
1039 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1040 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
1046 if (initialized_fields == null)
1049 for (int i = 0; i < initialized_fields.Count; ++i) {
1050 FieldInitializer fi = initialized_fields [i];
1053 // Clone before resolving otherwise when field initializer is needed
1054 // in more than 1 constructor any resolve after the initial one would
1055 // only took the resolved expression which is problem for expressions
1056 // that generate extra expressions or code during Resolve phase
1058 var cloned = fi.Clone (new CloneContext ());
1060 ExpressionStatement s = fi.ResolveStatement (ec);
1062 initialized_fields [i] = new FieldInitializer (fi.Field, ErrorExpression.Instance, Location.Null);
1067 // Field is re-initialized to its default value => removed
1069 if (fi.IsDefaultInitializer && Kind != MemberKind.Struct && ec.Module.Compiler.Settings.Optimize)
1072 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1073 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
1074 initialized_fields [i] = (FieldInitializer) cloned;
1078 public override string DocComment {
1090 public PendingImplementation PendingImplementations {
1091 get { return pending; }
1094 internal override void GenerateDocComment (DocumentationBuilder builder)
1099 base.GenerateDocComment (builder);
1101 foreach (var member in members)
1102 member.GenerateDocComment (builder);
1105 public TypeSpec GetAttributeCoClass ()
1107 if (OptAttributes == null)
1110 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
1114 return a.GetCoClassAttributeValue ();
1117 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1120 if (OptAttributes != null) {
1121 a = OptAttributes.Search (pa);
1127 return a.GetAttributeUsageAttribute ();
1130 public virtual CompilationSourceFile GetCompilationSourceFile ()
1132 TypeContainer ns = Parent;
1134 var sf = ns as CompilationSourceFile;
1142 public override string GetSignatureForMetadata ()
1144 if (Parent is TypeDefinition) {
1145 return Parent.GetSignatureForMetadata () + "+" + TypeNameParser.Escape (FilterNestedName (MemberName.Basename));
1148 return base.GetSignatureForMetadata ();
1151 public virtual void SetBaseTypes (List<FullNamedExpression> baseTypes)
1153 type_bases = baseTypes;
1157 /// This function computes the Base class and also the
1158 /// list of interfaces that the class or struct @c implements.
1160 /// The return value is an array (might be null) of
1161 /// interfaces implemented (as Types).
1163 /// The @base_class argument is set to the base object or null
1164 /// if this is `System.Object'.
1166 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1169 if (type_bases == null)
1172 int count = type_bases.Count;
1173 TypeSpec[] ifaces = null;
1174 var base_context = new BaseContext (this);
1175 for (int i = 0, j = 0; i < count; i++){
1176 FullNamedExpression fne = type_bases [i];
1178 var fne_resolved = fne.ResolveAsType (base_context);
1179 if (fne_resolved == null)
1182 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1183 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1184 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1185 GetSignatureForError ());
1190 base_type = fne_resolved;
1196 ifaces = new TypeSpec [count - i];
1198 if (fne_resolved.IsInterface) {
1199 for (int ii = 0; ii < j; ++ii) {
1200 if (fne_resolved == ifaces [ii]) {
1201 Report.Error (528, Location, "`{0}' is already listed in interface list",
1202 fne_resolved.GetSignatureForError ());
1207 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1208 Report.Error (61, fne.Location,
1209 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1210 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1213 Report.SymbolRelatedToPreviousError (fne_resolved);
1214 if (Kind != MemberKind.Class) {
1215 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1216 } else if (base_class != null)
1217 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1218 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1220 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1221 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1225 ifaces [j++] = fne_resolved;
1232 // Checks that some operators come in pairs:
1238 // They are matched based on the return type and the argument types
1240 void CheckPairedOperators ()
1242 bool has_equality_or_inequality = false;
1243 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1245 for (int i = 0; i < members.Count; ++i) {
1246 var o_a = members[i] as Operator;
1250 var o_type = o_a.OperatorType;
1251 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1252 has_equality_or_inequality = true;
1254 if (found_matched.Contains (o_type))
1257 var matching_type = o_a.GetMatchingOperator ();
1258 if (matching_type == Operator.OpType.TOP) {
1262 bool pair_found = false;
1263 for (int ii = 0; ii < members.Count; ++ii) {
1264 var o_b = members[ii] as Operator;
1265 if (o_b == null || o_b.OperatorType != matching_type)
1268 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1271 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1274 found_matched.Add (matching_type);
1280 Report.Error (216, o_a.Location,
1281 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1282 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1286 if (has_equality_or_inequality) {
1288 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1289 GetSignatureForError ());
1291 if (!HasGetHashCode)
1292 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1293 GetSignatureForError ());
1297 public override void CreateMetadataName (StringBuilder sb)
1299 if (Parent.MemberName != null) {
1300 Parent.CreateMetadataName (sb);
1302 if (sb.Length != 0) {
1307 sb.Append (MemberName.Basename);
1310 bool CreateTypeBuilder ()
1313 // Sets .size to 1 for structs with no instance fields
1315 int type_size = Kind == MemberKind.Struct && !HasInstanceField && !(this is StateMachine) ? 1 : 0;
1317 var parent_def = Parent as TypeDefinition;
1318 if (parent_def == null) {
1319 var sb = new StringBuilder ();
1320 CreateMetadataName (sb);
1321 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1323 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (FilterNestedName (MemberName.Basename), TypeAttr, null, type_size);
1326 if (DeclaringAssembly.Importer != null)
1327 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1329 spec.SetMetaInfo (TypeBuilder);
1330 spec.MemberCache = new MemberCache (this);
1332 TypeParameters parentAllTypeParameters = null;
1333 if (parent_def != null) {
1334 spec.DeclaringType = Parent.CurrentType;
1335 parent_def.MemberCache.AddMember (spec);
1336 parentAllTypeParameters = parent_def.all_type_parameters;
1339 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1340 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1342 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1344 if (CurrentTypeParameters != null) {
1345 CurrentTypeParameters.Create (spec, CurrentTypeParametersStartIndex, this);
1346 CurrentTypeParameters.Define (all_tp_builders);
1353 public static string FilterNestedName (string name)
1356 // SRE API does not handle namespaces and types separately but
1357 // determine that from '.' in name. That's problematic because
1358 // dot is valid character for type name. By replacing any '.'
1359 // in name we avoid any ambiguities and never emit metadata
1360 // namespace for nested types
1362 return name.Replace ('.', '_');
1365 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1368 int parent_offset = 0;
1369 if (parentAllTypeParameters != null) {
1370 if (CurrentTypeParameters == null) {
1371 all_type_parameters = parentAllTypeParameters;
1372 return parentAllTypeParameters.GetAllNames ();
1375 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1376 all_type_parameters = new TypeParameters (names.Length);
1377 all_type_parameters.Add (parentAllTypeParameters);
1379 parent_offset = all_type_parameters.Count;
1380 for (int i = 0; i < parent_offset; ++i)
1381 names[i] = all_type_parameters[i].MemberName.Name;
1384 names = new string[CurrentTypeParameters.Count];
1387 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1388 if (all_type_parameters != null)
1389 all_type_parameters.Add (MemberName.TypeParameters[i]);
1391 var name = CurrentTypeParameters[i].MemberName.Name;
1392 names[parent_offset + i] = name;
1393 for (int ii = 0; ii < parent_offset + i; ++ii) {
1394 if (names[ii] != name)
1397 var tp = CurrentTypeParameters[i];
1398 var conflict = all_type_parameters[ii];
1400 tp.WarningParentNameConflict (conflict);
1404 if (all_type_parameters == null)
1405 all_type_parameters = CurrentTypeParameters;
1411 public SourceMethodBuilder CreateMethodSymbolEntry ()
1413 if (Module.DeclaringAssembly.SymbolWriter == null || (ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1416 var source_file = GetCompilationSourceFile ();
1417 if (source_file == null)
1420 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1424 // Creates a proxy base method call inside this container for hoisted base member calls
1426 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1428 Method proxy_method;
1431 // One proxy per base method is enough
1433 if (hoisted_base_call_proxies == null) {
1434 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1435 proxy_method = null;
1437 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1440 if (proxy_method == null) {
1441 string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1443 MemberName member_name;
1444 TypeArguments targs = null;
1445 TypeSpec return_type = method.ReturnType;
1446 var local_param_types = method.Parameters.Types;
1448 if (method.IsGeneric) {
1450 // Copy all base generic method type parameters info
1452 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1453 var tparams = new TypeParameters ();
1455 targs = new TypeArguments ();
1456 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1457 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1458 var tp = hoisted_tparams[i];
1459 var tp_name = tp.Name;
1461 tp_name += "_Proxy";
1463 var local_tp = new TypeParameter (tp, null, new MemberName (tp_name, Location), null);
1464 tparams.Add (local_tp);
1466 targs.Add (new SimpleName (tp.Name, Location));
1467 targs.Arguments[i] = local_tp.Type;
1470 member_name = new MemberName (name, tparams, Location);
1473 // Mutate any method type parameters from original
1474 // to newly created hoisted version
1476 var mutator = new TypeParameterMutator (hoisted_tparams, tparams);
1477 return_type = mutator.Mutate (return_type);
1478 local_param_types = mutator.Mutate (local_param_types);
1480 var inflator = new TypeParameterInflator (this, null, hoisted_tparams, targs.Arguments);
1481 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1482 var tp_spec = (TypeParameterSpec) targs.Arguments [i];
1483 tp_spec.InflateConstraints (inflator, tp_spec);
1486 member_name = new MemberName (name);
1489 var base_parameters = new Parameter[method.Parameters.Count];
1490 for (int i = 0; i < base_parameters.Length; ++i) {
1491 var base_param = method.Parameters.FixedParameters[i];
1492 base_parameters[i] = new Parameter (new TypeExpression (local_param_types [i], Location),
1493 base_param.Name, base_param.ModFlags, null, Location);
1494 base_parameters[i].Resolve (this, i);
1497 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, local_param_types);
1498 if (method.Parameters.HasArglist) {
1499 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1500 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1503 // Compiler generated proxy
1504 proxy_method = new Method (this, new TypeExpression (return_type, Location),
1505 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1506 member_name, cloned_params, null);
1508 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1509 IsCompilerGenerated = true
1512 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1513 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1515 mg.SetTypeArguments (rc, targs);
1517 // Get all the method parameters and pass them as arguments
1518 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1519 Statement statement;
1520 if (method.ReturnType.Kind == MemberKind.Void)
1521 statement = new StatementExpression (real_base_call);
1523 statement = new Return (real_base_call, Location);
1525 block.AddStatement (statement);
1526 proxy_method.Block = block;
1528 members.Add (proxy_method);
1529 proxy_method.Define ();
1530 proxy_method.PrepareEmit ();
1532 hoisted_base_call_proxies.Add (method, proxy_method);
1535 return proxy_method.Spec;
1538 protected bool DefineBaseTypes ()
1540 if (IsPartialPart && Kind == MemberKind.Class)
1543 return DoDefineBaseType ();
1546 bool DoDefineBaseType ()
1548 iface_exprs = ResolveBaseTypes (out base_type_expr);
1551 if (IsPartialPart) {
1552 set_base_type = false;
1554 if (base_type_expr != null) {
1555 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1556 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1557 Report.Error (263, Location,
1558 "Partial declarations of `{0}' must not specify different base classes",
1559 GetSignatureForError ());
1561 PartialContainer.base_type_expr = base_type_expr;
1562 PartialContainer.base_type = base_type;
1563 set_base_type = true;
1567 if (iface_exprs != null) {
1568 if (PartialContainer.iface_exprs == null)
1569 PartialContainer.iface_exprs = iface_exprs;
1571 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1572 foreach (var iface_partial in iface_exprs) {
1573 if (ifaces.Contains (iface_partial))
1576 ifaces.Add (iface_partial);
1579 PartialContainer.iface_exprs = ifaces.ToArray ();
1583 PartialContainer.members.AddRange (members);
1584 if (containers != null) {
1585 if (PartialContainer.containers == null)
1586 PartialContainer.containers = new List<TypeContainer> ();
1588 PartialContainer.containers.AddRange (containers);
1591 if (PrimaryConstructorParameters != null) {
1592 if (PartialContainer.PrimaryConstructorParameters != null) {
1593 Report.Error (8036, Location, "Only one part of a partial type can declare primary constructor parameters");
1595 PartialContainer.PrimaryConstructorParameters = PrimaryConstructorParameters;
1599 members_defined = members_defined_ok = true;
1600 caching_flags |= Flags.CloseTypeCreated;
1602 set_base_type = true;
1605 var cycle = CheckRecursiveDefinition (this);
1606 if (cycle != null) {
1607 Report.SymbolRelatedToPreviousError (cycle);
1608 if (this is Interface) {
1609 Report.Error (529, Location,
1610 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1611 GetSignatureForError (), cycle.GetSignatureForError ());
1614 PartialContainer.iface_exprs = null;
1616 Report.Error (146, Location,
1617 "Circular base class dependency involving `{0}' and `{1}'",
1618 GetSignatureForError (), cycle.GetSignatureForError ());
1621 PartialContainer.base_type = null;
1625 if (iface_exprs != null) {
1626 if (!PrimaryConstructorBaseArgumentsStart.IsNull) {
1627 Report.Error (8049, PrimaryConstructorBaseArgumentsStart, "Implemented interfaces cannot have arguments");
1630 foreach (var iface_type in iface_exprs) {
1631 // Prevents a crash, the interface might not have been resolved: 442144
1632 if (iface_type == null)
1635 if (!spec.AddInterfaceDefined (iface_type))
1638 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1642 if (Kind == MemberKind.Interface) {
1643 spec.BaseType = Compiler.BuiltinTypes.Object;
1647 if (set_base_type) {
1652 // Base type of partial container has to be resolved before we
1653 // resolve any nested types of the container. We need to know
1654 // partial parts because the base type can be specified in file
1655 // defined after current container
1657 if (class_partial_parts != null) {
1658 foreach (var pp in class_partial_parts) {
1659 if (pp.PrimaryConstructorBaseArguments != null)
1660 PrimaryConstructorBaseArguments = pp.PrimaryConstructorBaseArguments;
1662 pp.DoDefineBaseType ();
1672 if (base_type == null) {
1673 TypeBuilder.SetParent (null);
1677 if (spec.BaseType == base_type)
1680 spec.BaseType = base_type;
1683 spec.UpdateInflatedInstancesBaseType ();
1685 // Set base type after type creation
1686 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1689 public override void ExpandBaseInterfaces ()
1691 DoResolveTypeParameters ();
1694 DoExpandBaseInterfaces ();
1696 base.ExpandBaseInterfaces ();
1699 public void DoExpandBaseInterfaces ()
1701 if ((caching_flags & Flags.InterfacesExpanded) != 0)
1704 caching_flags |= Flags.InterfacesExpanded;
1707 // Expand base interfaces. It cannot be done earlier because all partial
1708 // interface parts need to be defined before the type they are used from
1710 if (iface_exprs != null) {
1711 foreach (var iface in iface_exprs) {
1715 var td = iface.MemberDefinition as TypeDefinition;
1717 td.DoExpandBaseInterfaces ();
1719 if (iface.Interfaces == null)
1722 foreach (var biface in iface.Interfaces) {
1723 if (spec.AddInterfaceDefined (biface)) {
1724 TypeBuilder.AddInterfaceImplementation (biface.GetMetaInfo ());
1731 // Include all base type interfaces too, see ImportTypeBase for details
1733 if (base_type != null) {
1734 var td = base_type.MemberDefinition as TypeDefinition;
1736 td.DoExpandBaseInterfaces ();
1739 // Simply use base interfaces only, they are all expanded which makes
1740 // it easy to handle generic type argument propagation with single
1743 // interface IA<T> : IB<T>
1744 // interface IB<U> : IC<U>
1747 if (base_type.Interfaces != null) {
1748 foreach (var iface in base_type.Interfaces) {
1749 spec.AddInterfaceDefined (iface);
1755 public override void PrepareEmit ()
1757 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1760 foreach (var member in members) {
1761 var pbm = member as MemberBase;
1766 base.PrepareEmit ();
1770 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1772 public override bool CreateContainer ()
1774 if (TypeBuilder != null)
1780 if (IsPartialPart) {
1781 spec = PartialContainer.spec;
1782 TypeBuilder = PartialContainer.TypeBuilder;
1783 all_tp_builders = PartialContainer.all_tp_builders;
1784 all_type_parameters = PartialContainer.all_type_parameters;
1786 if (!CreateTypeBuilder ()) {
1792 return base.CreateContainer ();
1795 protected override void DoDefineContainer ()
1801 // Replaces normal spec with predefined one when compiling corlib
1802 // and this type container defines predefined type
1804 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1806 // When compiling build-in types we start with two
1807 // version of same type. One is of BuiltinTypeSpec and
1808 // second one is ordinary TypeSpec. The unification
1809 // happens at later stage when we know which type
1810 // really matches the builtin type signature. However
1811 // that means TypeSpec create during CreateType of this
1812 // type has to be replaced with builtin one
1814 spec.SetMetaInfo (TypeBuilder);
1815 spec.MemberCache = this.spec.MemberCache;
1816 spec.DeclaringType = this.spec.DeclaringType;
1819 current_type = null;
1820 if (class_partial_parts != null) {
1821 foreach (var part in class_partial_parts) {
1823 part.current_type = null;
1828 public override void RemoveContainer (TypeContainer cont)
1830 base.RemoveContainer (cont);
1831 Members.Remove (cont);
1832 Cache.Remove (cont.MemberName.Basename);
1835 protected virtual bool DoResolveTypeParameters ()
1837 var tparams = MemberName.TypeParameters;
1838 if (tparams == null)
1841 var base_context = new BaseContext (this);
1842 for (int i = 0; i < tparams.Count; ++i) {
1843 var tp = tparams[i];
1845 if (!tp.ResolveConstraints (base_context)) {
1850 if (IsPartialPart) {
1851 var pc_tp = PartialContainer.CurrentTypeParameters [i];
1853 tp.Create (spec, this);
1856 if (tp.OptAttributes != null) {
1857 if (pc_tp.OptAttributes == null)
1858 pc_tp.OptAttributes = tp.OptAttributes;
1860 pc_tp.OptAttributes.Attrs.AddRange (tp.OptAttributes.Attrs);
1865 if (IsPartialPart) {
1866 PartialContainer.CurrentTypeParameters.UpdateConstraints (this);
1872 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1874 if (InTransit != null)
1879 if (base_type != null) {
1880 var ptc = base_type.MemberDefinition as TypeDefinition;
1881 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1885 if (iface_exprs != null && this is Interface) {
1886 foreach (var iface in iface_exprs) {
1887 // the interface might not have been resolved, prevents a crash, see #442144
1890 var ptc = iface.MemberDefinition as Interface;
1891 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1896 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1904 /// Populates our TypeBuilder with fields and methods
1906 public sealed override bool Define ()
1908 if (members_defined)
1909 return members_defined_ok;
1911 members_defined_ok = DoDefineMembers ();
1912 members_defined = true;
1916 return members_defined_ok;
1919 protected virtual bool DoDefineMembers ()
1921 Debug.Assert (!IsPartialPart);
1923 if (iface_exprs != null) {
1924 foreach (var iface_type in iface_exprs) {
1925 if (iface_type == null)
1928 // Ensure the base is always setup
1929 var compiled_iface = iface_type.MemberDefinition as Interface;
1930 if (compiled_iface != null)
1931 compiled_iface.Define ();
1933 iface_type.CheckObsoleteness (this, Location);
1935 if (iface_type.Arity > 0) {
1936 // TODO: passing `this' is wrong, should be base type iface instead
1937 VarianceDecl.CheckTypeVariance (iface_type, Variance.Covariant, this);
1939 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1940 Report.Error (1966, Location,
1941 "`{0}': cannot implement a dynamic interface `{1}'",
1942 GetSignatureForError (), iface_type.GetSignatureForError ());
1947 if (iface_type.IsGenericOrParentIsGeneric) {
1948 foreach (var prev_iface in iface_exprs) {
1949 if (prev_iface == iface_type || prev_iface == null)
1952 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1955 Report.Error (695, Location,
1956 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1957 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1962 if (Kind == MemberKind.Interface) {
1963 foreach (var iface in spec.Interfaces) {
1964 MemberCache.AddInterface (iface);
1969 if (base_type != null) {
1971 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1973 if (base_type_expr != null) {
1974 base_type.CheckObsoleteness (this, base_type_expr.Location);
1976 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1977 Report.Error (698, base_type_expr.Location,
1978 "A generic type cannot derive from `{0}' because it is an attribute class",
1979 base_type.GetSignatureForError ());
1983 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1984 if (baseContainer != null) {
1985 baseContainer.Define ();
1988 // It can trigger define of this type (for generic types only)
1990 if (HasMembersDefined)
1995 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1996 pending = PendingImplementation.GetPendingImplementations (this);
1999 var count = members.Count;
2000 for (int i = 0; i < count; ++i) {
2001 var mc = members[i] as InterfaceMemberBase;
2002 if (mc == null || !mc.IsExplicitImpl)
2007 } catch (Exception e) {
2008 throw new InternalErrorException (mc, e);
2012 for (int i = 0; i < count; ++i) {
2013 var mc = members[i] as InterfaceMemberBase;
2014 if (mc != null && mc.IsExplicitImpl)
2017 if (members[i] is TypeContainer)
2021 members[i].Define ();
2022 } catch (Exception e) {
2023 throw new InternalErrorException (members[i], e);
2028 CheckPairedOperators ();
2031 ComputeIndexerName();
2033 if (HasEquals && !HasGetHashCode) {
2034 Report.Warning (659, 3, Location,
2035 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
2038 if (Kind == MemberKind.Interface && iface_exprs != null) {
2039 MemberCache.RemoveHiddenMembers (spec);
2045 void ComputeIndexerName ()
2047 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
2048 if (indexers == null)
2051 string class_indexer_name = null;
2054 // Check normal indexers for consistent name, explicit interface implementation
2055 // indexers are ignored
2057 foreach (var indexer in indexers) {
2059 // FindMembers can return unfiltered full hierarchy names
2061 if (indexer.DeclaringType != spec)
2064 has_normal_indexers = true;
2066 if (class_indexer_name == null) {
2067 indexer_name = class_indexer_name = indexer.Name;
2071 if (indexer.Name != class_indexer_name)
2072 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
2073 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
2077 void EmitIndexerName ()
2079 if (!has_normal_indexers)
2082 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
2086 var encoder = new AttributeEncoder ();
2087 encoder.Encode (GetAttributeDefaultMember ());
2088 encoder.EncodeEmptyNamedArguments ();
2090 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2093 public override void VerifyMembers ()
2096 // Check for internal or private fields that were never assigned
2098 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
2099 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
2100 foreach (var member in members) {
2101 if (member is Event) {
2103 // An event can be assigned from same class only, report
2104 // this warning for all accessibility modes
2106 if (!member.IsUsed && !PartialContainer.HasStructLayout)
2107 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
2112 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
2113 if (is_type_exposed)
2116 member.SetIsUsed ();
2119 var f = member as Field;
2123 if (!member.IsUsed) {
2124 if (!PartialContainer.HasStructLayout) {
2125 if ((member.caching_flags & Flags.IsAssigned) == 0) {
2126 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
2128 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
2129 member.GetSignatureForError ());
2136 if ((f.caching_flags & Flags.IsAssigned) != 0)
2140 // Only report 649 on level 4
2142 if (Compiler.Settings.WarningLevel < 4)
2146 // Don't be pedantic when type requires specific layout
2148 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2151 Constant c = New.Constantify (f.MemberType, f.Location);
2154 value = c.GetValueAsLiteral ();
2155 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
2162 value = " `" + value + "'";
2164 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
2165 f.GetSignatureForError (), value);
2169 base.VerifyMembers ();
2172 public override void Emit ()
2174 if (OptAttributes != null)
2175 OptAttributes.Emit ();
2177 if (!IsCompilerGenerated) {
2179 MemberSpec candidate;
2180 bool overrides = false;
2181 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
2182 if (conflict_symbol == null && candidate == null) {
2183 if ((ModFlags & Modifiers.NEW) != 0)
2184 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
2185 GetSignatureForError ());
2187 if ((ModFlags & Modifiers.NEW) == 0) {
2188 if (candidate == null)
2189 candidate = conflict_symbol;
2191 Report.SymbolRelatedToPreviousError (candidate);
2192 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
2193 GetSignatureForError (), candidate.GetSignatureForError ());
2198 // Run constraints check on all possible generic types
2199 if (base_type != null && base_type_expr != null) {
2200 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
2203 if (iface_exprs != null) {
2204 foreach (var iface_type in iface_exprs) {
2205 if (iface_type == null)
2208 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2213 if (all_tp_builders != null) {
2214 int current_starts_index = CurrentTypeParametersStartIndex;
2215 for (int i = 0; i < all_tp_builders.Length; i++) {
2216 if (i < current_starts_index) {
2217 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2219 var tp = CurrentTypeParameters [i - current_starts_index];
2220 tp.CheckGenericConstraints (!IsObsolete);
2226 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2227 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2230 if (Kind == MemberKind.Struct && HasInstanceField) {
2231 TypeBuilder.__SetLayout (0, 0);
2234 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2235 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2240 for (int i = 0; i < members.Count; i++) {
2242 if ((m.caching_flags & Flags.CloseTypeCreated) != 0)
2249 CheckAttributeClsCompliance ();
2251 if (pending != null)
2252 pending.VerifyPendingMethods ();
2256 void CheckAttributeClsCompliance ()
2258 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2261 foreach (var m in members) {
2262 var c = m as Constructor;
2266 if (c.HasCompliantArgs)
2270 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2273 public sealed override void EmitContainer ()
2275 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2281 public override void CloseContainer ()
2283 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2286 // Close base type container first to avoid TypeLoadException
2287 if (spec.BaseType != null) {
2288 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2289 if (btype != null) {
2290 btype.CloseContainer ();
2292 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2298 caching_flags |= Flags.CloseTypeCreated;
2299 TypeBuilder.CreateType ();
2300 } catch (TypeLoadException) {
2302 // This is fine, the code still created the type
2304 } catch (Exception e) {
2305 throw new InternalErrorException (this, e);
2308 base.CloseContainer ();
2311 initialized_fields = null;
2312 initialized_static_fields = null;
2314 OptAttributes = null;
2318 // Performs the validation on a Method's modifiers (properties have
2319 // the same properties).
2321 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2323 public bool MethodModifiersValid (MemberCore mc)
2325 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2326 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2328 var flags = mc.ModFlags;
2331 // At most one of static, virtual or override
2333 if ((flags & Modifiers.STATIC) != 0){
2334 if ((flags & vao) != 0){
2335 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2336 mc.GetSignatureForError ());
2341 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2342 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2343 mc.GetSignatureForError ());
2348 // If the declaration includes the abstract modifier, then the
2349 // declaration does not include static, virtual or extern
2351 if ((flags & Modifiers.ABSTRACT) != 0){
2352 if ((flags & Modifiers.EXTERN) != 0){
2354 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2358 if ((flags & Modifiers.SEALED) != 0) {
2359 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2363 if ((flags & Modifiers.VIRTUAL) != 0){
2364 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2368 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2369 Report.SymbolRelatedToPreviousError (this);
2370 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2371 mc.GetSignatureForError (), GetSignatureForError ());
2376 if ((flags & Modifiers.PRIVATE) != 0){
2377 if ((flags & vao) != 0){
2378 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2383 if ((flags & Modifiers.SEALED) != 0){
2384 if ((flags & Modifiers.OVERRIDE) == 0){
2385 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2393 protected override bool VerifyClsCompliance ()
2395 if (!base.VerifyClsCompliance ())
2398 // Check all container names for user classes
2399 if (Kind != MemberKind.Delegate)
2400 MemberCache.VerifyClsCompliance (Definition, Report);
2402 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2403 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2404 GetSignatureForError (), BaseType.GetSignatureForError ());
2410 /// Performs checks for an explicit interface implementation. First it
2411 /// checks whether the `interface_type' is a base inteface implementation.
2412 /// Then it checks whether `name' exists in the interface type.
2414 public bool VerifyImplements (InterfaceMemberBase mb)
2416 var ifaces = PartialContainer.Interfaces;
2417 if (ifaces != null) {
2418 foreach (TypeSpec t in ifaces){
2419 if (t == mb.InterfaceType || t == null)
2422 var expanded_base = t.Interfaces;
2423 if (expanded_base == null)
2426 foreach (var bt in expanded_base) {
2427 if (bt == mb.InterfaceType)
2433 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2434 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2435 mb.GetSignatureForError (), mb.InterfaceType.GetSignatureForError ());
2440 // Used for visiblity checks to tests whether this definition shares
2441 // base type baseType, it does member-definition search
2443 public bool IsBaseTypeDefinition (TypeSpec baseType)
2445 // RootContext check
2446 if (TypeBuilder == null)
2451 if (type.MemberDefinition == baseType.MemberDefinition)
2454 type = type.BaseType;
2455 } while (type != null);
2460 public override bool IsClsComplianceRequired ()
2463 return PartialContainer.IsClsComplianceRequired ();
2465 return base.IsClsComplianceRequired ();
2468 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2470 return Module.DeclaringAssembly == assembly;
2473 public virtual bool IsUnmanagedType ()
2478 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2480 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2484 // Public function used to locate types.
2486 // Returns: Type or null if they type can not be found.
2488 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2490 FullNamedExpression e;
2491 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2497 var tp = CurrentTypeParameters;
2499 TypeParameter tparam = tp.Find (name);
2501 e = new TypeParameterExpr (tparam, Location.Null);
2506 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2508 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2509 e = new TypeExpression (t, Location.Null);
2511 var errors = Compiler.Report.Errors;
2512 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2514 // TODO: LookupNamespaceOrType does more than just lookup. The result
2515 // cannot be cached or the error reporting won't happen
2516 if (errors != Compiler.Report.Errors)
2521 // TODO MemberCache: How to cache arity stuff ?
2522 if (arity == 0 && mode == LookupMode.Normal)
2528 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2530 // Has any nested type
2531 // Does not work, because base type can have
2532 //if (PartialContainer.Types == null)
2535 var container = PartialContainer.CurrentType;
2536 return MemberCache.FindNestedType (container, name, arity, false);
2539 public void Mark_HasEquals ()
2541 cached_method |= CachedMethods.Equals;
2544 public void Mark_HasGetHashCode ()
2546 cached_method |= CachedMethods.GetHashCode;
2549 public override void WriteDebugSymbol (MonoSymbolFile file)
2554 foreach (var m in members) {
2555 m.WriteDebugSymbol (file);
2560 /// Method container contains Equals method
2562 public bool HasEquals {
2564 return (cached_method & CachedMethods.Equals) != 0;
2569 /// Method container contains GetHashCode method
2571 public bool HasGetHashCode {
2573 return (cached_method & CachedMethods.GetHashCode) != 0;
2577 public bool HasStaticFieldInitializer {
2579 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2583 cached_method |= CachedMethods.HasStaticFieldInitializer;
2585 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2589 public override string DocCommentHeader {
2590 get { return "T:"; }
2594 public abstract class ClassOrStruct : TypeDefinition
2596 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2598 SecurityType declarative_security;
2599 protected Constructor generated_primary_constructor;
2601 protected ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2602 : base (parent, name, attrs, kind)
2606 public ToplevelBlock PrimaryConstructorBlock { get; set; }
2608 protected override TypeAttributes TypeAttr {
2610 TypeAttributes ta = base.TypeAttr;
2611 if (!has_static_constructor)
2612 ta |= TypeAttributes.BeforeFieldInit;
2614 if (Kind == MemberKind.Class) {
2615 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2617 ta |= StaticClassAttribute;
2619 ta |= TypeAttributes.SequentialLayout;
2626 public override void AddNameToContainer (MemberCore symbol, string name)
2628 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2629 if (symbol is TypeParameter) {
2630 Report.Error (694, symbol.Location,
2631 "Type parameter `{0}' has same name as containing type, or method",
2632 symbol.GetSignatureForError ());
2636 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2637 if (imb == null || !imb.IsExplicitImpl) {
2638 Report.SymbolRelatedToPreviousError (this);
2639 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2640 symbol.GetSignatureForError ());
2645 base.AddNameToContainer (symbol, name);
2648 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2650 if (a.IsValidSecurityAttribute ()) {
2651 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2655 if (a.Type == pa.StructLayout) {
2656 PartialContainer.HasStructLayout = true;
2657 if (a.IsExplicitLayoutKind ())
2658 PartialContainer.HasExplicitLayout = true;
2661 if (a.Type == pa.Dynamic) {
2662 a.Error_MisusedDynamicAttribute ();
2666 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2670 /// Defines the default constructors
2672 protected virtual Constructor DefineDefaultConstructor (bool is_static)
2674 // The default instance constructor is public
2675 // If the class is abstract, the default constructor is protected
2676 // The default static constructor is private
2679 ParametersCompiled parameters = null;
2681 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2682 parameters = ParametersCompiled.EmptyReadOnlyParameters;
2684 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2685 parameters = PrimaryConstructorParameters ?? ParametersCompiled.EmptyReadOnlyParameters;
2688 var c = new Constructor (this, MemberName.Name, mods, null, parameters, Location);
2689 if (Kind == MemberKind.Class)
2690 c.Initializer = new GeneratedBaseInitializer (Location, PrimaryConstructorBaseArguments);
2692 if (PrimaryConstructorParameters != null && !is_static) {
2693 c.IsPrimaryConstructor = true;
2694 c.caching_flags |= Flags.MethodOverloadsExist;
2697 AddConstructor (c, true);
2698 if (PrimaryConstructorBlock == null) {
2699 c.Block = new ToplevelBlock (Compiler, parameters, Location) {
2700 IsCompilerGenerated = true
2703 c.Block = PrimaryConstructorBlock;
2709 protected override bool DoDefineMembers ()
2711 CheckProtectedModifier ();
2713 if (PrimaryConstructorParameters != null) {
2715 foreach (Parameter p in PrimaryConstructorParameters.FixedParameters) {
2716 if (p.Name == MemberName.Name) {
2717 Report.Error (8039, p.Location, "Primary constructor of type `{0}' has parameter of same name as containing type",
2718 GetSignatureForError ());
2721 if (CurrentTypeParameters != null) {
2722 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
2723 var tp = CurrentTypeParameters [i];
2724 if (p.Name == tp.Name) {
2725 Report.Error (8038, p.Location, "Primary constructor of type `{0}' has parameter of same name as type parameter `{1}'",
2726 GetSignatureForError (), p.GetSignatureForError ());
2733 base.DoDefineMembers ();
2738 public override void PrepareEmit ()
2740 var s = this as Struct;
2741 if (s == null || !s.HasUnmanagedCheckDone) {
2742 for (int i = 0; i < Members.Count; ++i) {
2743 var f = Members [i] as Field;
2744 if (f == null || f.MemberType == null || !f.MemberType.IsPointer)
2747 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
2751 base.PrepareEmit ();
2754 public override void Emit ()
2756 if (!has_static_constructor && HasStaticFieldInitializer) {
2757 var c = DefineDefaultConstructor (true);
2763 if (declarative_security != null) {
2764 foreach (var de in declarative_security) {
2766 TypeBuilder.__AddDeclarativeSecurity (de);
2768 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2776 public sealed class Class : ClassOrStruct
2778 const Modifiers AllowedModifiers =
2781 Modifiers.PROTECTED |
2782 Modifiers.INTERNAL |
2784 Modifiers.ABSTRACT |
2789 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2790 : base (parent, name, attrs, MemberKind.Class)
2792 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2793 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2794 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2797 public override void Accept (StructuralVisitor visitor)
2799 visitor.Visit (this);
2802 public override void SetBaseTypes (List<FullNamedExpression> baseTypes)
2804 var pmn = MemberName;
2805 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2806 Report.Error (537, Location,
2807 "The class System.Object cannot have a base class or implement an interface.");
2809 base.SetBaseTypes (baseTypes);
2812 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2814 if (a.Type == pa.AttributeUsage) {
2815 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2816 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2820 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2821 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2825 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2826 a.Error_MissingGuidAttribute ();
2830 if (a.Type == pa.Extension) {
2831 a.Error_MisusedExtensionAttribute ();
2835 if (a.Type.IsConditionallyExcluded (this))
2838 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2841 public override AttributeTargets AttributeTargets {
2843 return AttributeTargets.Class;
2847 protected override bool DoDefineMembers ()
2849 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2850 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2853 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2854 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2858 if (PrimaryConstructorParameters != null) {
2859 Report.Error (-800, Location, "`{0}': Static classes cannot have primary constructor", GetSignatureForError ());
2860 PrimaryConstructorParameters = null;
2863 foreach (var m in Members) {
2864 if (m is Operator) {
2865 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2869 if (m is Destructor) {
2870 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2875 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2879 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2882 if (m is Constructor) {
2883 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2887 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2890 if (!PartialContainer.HasInstanceConstructor || PrimaryConstructorParameters != null)
2891 generated_primary_constructor = DefineDefaultConstructor (false);
2894 return base.DoDefineMembers ();
2897 public override void Emit ()
2901 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2902 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2904 if (base_type != null && base_type.HasDynamicElement) {
2905 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2909 public override void GetCompletionStartingWith (string prefix, List<string> results)
2911 base.GetCompletionStartingWith (prefix, results);
2914 while (bt != null) {
2915 results.AddRange (MemberCache.GetCompletitionMembers (this, bt, prefix).Where (l => l.IsStatic).Select (l => l.Name));
2920 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2922 var ifaces = base.ResolveBaseTypes (out base_class);
2924 if (base_class == null) {
2925 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2926 base_type = Compiler.BuiltinTypes.Object;
2928 if (base_type.IsGenericParameter){
2929 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2930 GetSignatureForError (), base_type.GetSignatureForError ());
2931 } else if (base_type.IsStatic) {
2932 Report.SymbolRelatedToPreviousError (base_type);
2933 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2934 GetSignatureForError (), base_type.GetSignatureForError ());
2935 } else if (base_type.IsSealed) {
2936 Report.SymbolRelatedToPreviousError (base_type);
2937 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2938 GetSignatureForError (), base_type.GetSignatureForError ());
2939 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2940 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2941 GetSignatureForError (), base_type.GetSignatureForError ());
2944 switch (base_type.BuiltinType) {
2945 case BuiltinTypeSpec.Type.Enum:
2946 case BuiltinTypeSpec.Type.ValueType:
2947 case BuiltinTypeSpec.Type.MulticastDelegate:
2948 case BuiltinTypeSpec.Type.Delegate:
2949 case BuiltinTypeSpec.Type.Array:
2950 if (!(spec is BuiltinTypeSpec)) {
2951 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2952 GetSignatureForError (), base_type.GetSignatureForError ());
2954 base_type = Compiler.BuiltinTypes.Object;
2959 if (!IsAccessibleAs (base_type)) {
2960 Report.SymbolRelatedToPreviousError (base_type);
2961 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2962 base_type.GetSignatureForError (), GetSignatureForError ());
2966 if (PartialContainer.IsStatic && ifaces != null) {
2967 foreach (var t in ifaces)
2968 Report.SymbolRelatedToPreviousError (t);
2969 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2975 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2976 /// Valid only for attribute classes.
2977 public override string[] ConditionalConditions ()
2979 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2982 caching_flags &= ~Flags.Excluded_Undetected;
2984 if (OptAttributes == null)
2987 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2991 string[] conditions = new string[attrs.Length];
2992 for (int i = 0; i < conditions.Length; ++i)
2993 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2995 caching_flags |= Flags.Excluded;
3000 public sealed class Struct : ClassOrStruct
3002 bool is_unmanaged, has_unmanaged_check_done, requires_delayed_unmanagedtype_check;
3006 // Modifiers allowed in a struct declaration
3008 const Modifiers AllowedModifiers =
3011 Modifiers.PROTECTED |
3012 Modifiers.INTERNAL |
3016 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
3017 : base (parent, name, attrs, MemberKind.Struct)
3019 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3020 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
3021 spec = new TypeSpec (Kind, null, this, null, ModFlags);
3024 public override AttributeTargets AttributeTargets {
3026 return AttributeTargets.Struct;
3030 public override void Accept (StructuralVisitor visitor)
3032 visitor.Visit (this);
3035 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3037 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3040 // When struct constains fixed fixed and struct layout has explicitly
3041 // set CharSet, its value has to be propagated to compiler generated
3044 if (a.Type == pa.StructLayout) {
3045 var value = a.GetNamedValue ("CharSet");
3049 for (int i = 0; i < Members.Count; ++i) {
3050 FixedField ff = Members [i] as FixedField;
3054 ff.CharSetValue = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
3059 bool CheckStructCycles ()
3065 foreach (var member in Members) {
3066 var field = member as Field;
3070 TypeSpec ftype = field.Spec.MemberType;
3071 if (!ftype.IsStruct)
3074 if (ftype is BuiltinTypeSpec)
3077 foreach (var targ in ftype.TypeArguments) {
3078 if (!CheckFieldTypeCycle (targ)) {
3079 Report.Error (523, field.Location,
3080 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3081 field.GetSignatureForError (), ftype.GetSignatureForError ());
3087 // Static fields of exactly same type are allowed
3089 if (field.IsStatic && ftype == CurrentType)
3092 if (!CheckFieldTypeCycle (ftype)) {
3093 Report.Error (523, field.Location,
3094 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3095 field.GetSignatureForError (), ftype.GetSignatureForError ());
3104 static bool CheckFieldTypeCycle (TypeSpec ts)
3106 var fts = ts.MemberDefinition as Struct;
3110 return fts.CheckStructCycles ();
3113 protected override bool DoDefineMembers ()
3115 var res = base.DoDefineMembers ();
3117 if (PrimaryConstructorParameters != null || (initialized_fields != null && !HasUserDefaultConstructor ())) {
3118 generated_primary_constructor = DefineDefaultConstructor (false);
3119 generated_primary_constructor.Define ();
3125 public override void Emit ()
3127 CheckStructCycles ();
3132 public bool HasUnmanagedCheckDone {
3134 return has_unmanaged_check_done;
3138 bool HasUserDefaultConstructor ()
3140 foreach (var m in PartialContainer.Members) {
3141 var c = m as Constructor;
3145 if (!c.IsStatic && c.ParameterInfo.IsEmpty)
3152 public override bool IsUnmanagedType ()
3154 if (has_unmanaged_check_done)
3155 return is_unmanaged;
3157 if (requires_delayed_unmanagedtype_check)
3160 var parent_def = Parent.PartialContainer;
3161 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
3162 has_unmanaged_check_done = true;
3166 if (HasInstanceField) {
3167 requires_delayed_unmanagedtype_check = true;
3169 foreach (var member in Members) {
3170 var f = member as Field;
3177 // It can happen when recursive unmanaged types are defined
3178 // struct S { S* s; }
3179 TypeSpec mt = f.MemberType;
3187 has_unmanaged_check_done = true;
3191 has_unmanaged_check_done = true;
3194 is_unmanaged = true;
3198 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
3200 var ifaces = base.ResolveBaseTypes (out base_class);
3201 base_type = Compiler.BuiltinTypes.ValueType;
3209 public sealed class Interface : TypeDefinition {
3212 /// Modifiers allowed in a class declaration
3214 const Modifiers AllowedModifiers =
3217 Modifiers.PROTECTED |
3218 Modifiers.INTERNAL |
3222 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
3223 : base (parent, name, attrs, MemberKind.Interface)
3225 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3227 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
3228 spec = new TypeSpec (Kind, null, this, null, ModFlags);
3233 public override AttributeTargets AttributeTargets {
3235 return AttributeTargets.Interface;
3239 protected override TypeAttributes TypeAttr {
3241 const TypeAttributes DefaultTypeAttributes =
3242 TypeAttributes.AutoLayout |
3243 TypeAttributes.Abstract |
3244 TypeAttributes.Interface;
3246 return base.TypeAttr | DefaultTypeAttributes;
3252 public override void Accept (StructuralVisitor visitor)
3254 visitor.Visit (this);
3257 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3259 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3260 a.Error_MissingGuidAttribute ();
3264 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3267 protected override bool VerifyClsCompliance ()
3269 if (!base.VerifyClsCompliance ())
3272 if (iface_exprs != null) {
3273 foreach (var iface in iface_exprs) {
3274 if (iface.IsCLSCompliant ())
3277 Report.SymbolRelatedToPreviousError (iface);
3278 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3279 GetSignatureForError (), iface.GetSignatureForError ());
3287 public abstract class InterfaceMemberBase : MemberBase
3290 // Common modifiers allowed in a class declaration
3292 protected const Modifiers AllowedModifiersClass =
3295 Modifiers.PROTECTED |
3296 Modifiers.INTERNAL |
3301 Modifiers.OVERRIDE |
3302 Modifiers.ABSTRACT |
3307 // Common modifiers allowed in a struct declaration
3309 protected const Modifiers AllowedModifiersStruct =
3312 Modifiers.PROTECTED |
3313 Modifiers.INTERNAL |
3316 Modifiers.OVERRIDE |
3321 // Common modifiers allowed in a interface declaration
3323 protected const Modifiers AllowedModifiersInterface =
3328 // Whether this is an interface member.
3330 public bool IsInterface;
3333 // If true, this is an explicit interface implementation
3335 public readonly bool IsExplicitImpl;
3337 protected bool is_external_implementation;
3340 // The interface type we are explicitly implementing
3342 public TypeSpec InterfaceType;
3345 // The method we're overriding if this is an override method.
3347 protected MethodSpec base_method;
3349 readonly Modifiers explicit_mod_flags;
3350 public MethodAttributes flags;
3352 protected InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3353 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3355 IsInterface = parent.Kind == MemberKind.Interface;
3356 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3357 explicit_mod_flags = mod;
3360 public abstract Variance ExpectedMemberTypeVariance { get; }
3362 protected override bool CheckBase ()
3364 if (!base.CheckBase ())
3367 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3368 CheckForDuplications ();
3373 // For System.Object only
3374 if (Parent.BaseType == null)
3377 MemberSpec candidate;
3378 bool overrides = false;
3379 var base_member = FindBaseMember (out candidate, ref overrides);
3381 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3382 if (base_member == null) {
3383 if (candidate == null) {
3384 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3385 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3386 "object.Finalize()");
3388 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3389 GetSignatureForError (), SimpleName.GetMemberType (this));
3392 Report.SymbolRelatedToPreviousError (candidate);
3394 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3395 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3396 else if (this is PropertyBase)
3397 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3398 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3400 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3401 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3408 // Handles ambiguous overrides
3410 if (candidate != null) {
3411 Report.SymbolRelatedToPreviousError (candidate);
3412 Report.SymbolRelatedToPreviousError (base_member);
3414 // Get member definition for error reporting
3415 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3416 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3418 Report.Error (462, Location,
3419 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3420 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3423 if (!CheckOverrideAgainstBase (base_member))
3426 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3428 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3429 Report.SymbolRelatedToPreviousError (base_member);
3430 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3431 GetSignatureForError (), base_member.GetSignatureForError ());
3434 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3435 Report.SymbolRelatedToPreviousError (base_member);
3436 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3437 GetSignatureForError (), base_member.GetSignatureForError ());
3441 base_method = base_member as MethodSpec;
3445 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3446 base_member = candidate;
3448 if (base_member == null) {
3449 if ((ModFlags & Modifiers.NEW) != 0) {
3450 if (base_member == null) {
3451 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3452 GetSignatureForError ());
3456 if ((ModFlags & Modifiers.NEW) == 0) {
3457 ModFlags |= Modifiers.NEW;
3458 if (!IsCompilerGenerated) {
3459 Report.SymbolRelatedToPreviousError (base_member);
3460 if ((base_member.Kind & MemberKind.NestedMask) == 0 && !IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3461 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",
3462 GetSignatureForError (), base_member.GetSignatureForError ());
3464 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3465 GetSignatureForError (), base_member.GetSignatureForError ());
3470 if (!IsInterface && base_member.IsAbstract && !overrides && !IsStatic) {
3471 switch (base_member.Kind) {
3472 case MemberKind.Event:
3473 case MemberKind.Indexer:
3474 case MemberKind.Method:
3475 case MemberKind.Property:
3476 Report.SymbolRelatedToPreviousError (base_member);
3477 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3478 GetSignatureForError (), base_member.GetSignatureForError ());
3487 protected virtual bool CheckForDuplications ()
3489 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3493 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3494 // that have been defined.
3496 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3500 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3501 Report.SymbolRelatedToPreviousError (base_member);
3502 Report.Error (506, Location,
3503 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3504 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3508 // Now we check that the overriden method is not final
3509 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3510 Report.SymbolRelatedToPreviousError (base_member);
3511 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3512 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3516 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3517 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3518 Report.SymbolRelatedToPreviousError (base_member);
3519 if (this is PropertyBasedMember) {
3520 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3521 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3523 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3524 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3532 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3534 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3535 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3537 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3539 // It must be at least "protected"
3541 if ((thisp & Modifiers.PROTECTED) == 0) {
3546 // when overriding protected internal, the method can be declared
3547 // protected internal only within the same assembly or assembly
3548 // which has InternalsVisibleTo
3550 if ((thisp & Modifiers.INTERNAL) != 0) {
3551 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3555 // protected overriding protected internal inside same assembly
3556 // requires internal modifier as well
3558 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3565 return thisp == base_classp;
3568 public override bool Define ()
3571 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3572 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3574 flags = MethodAttributes.Public |
3575 MethodAttributes.Abstract |
3576 MethodAttributes.HideBySig |
3577 MethodAttributes.NewSlot |
3578 MethodAttributes.Virtual;
3580 Parent.PartialContainer.MethodModifiersValid (this);
3582 flags = ModifiersExtensions.MethodAttr (ModFlags);
3585 if (IsExplicitImpl) {
3586 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3587 if (InterfaceType == null)
3590 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3591 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3592 GetSignatureForError ());
3595 if (!InterfaceType.IsInterface) {
3596 Report.SymbolRelatedToPreviousError (InterfaceType);
3597 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3598 InterfaceType.GetSignatureForError ());
3600 Parent.PartialContainer.VerifyImplements (this);
3603 Modifiers allowed_explicit = Modifiers.AllowedExplicitImplFlags;
3605 allowed_explicit |= Modifiers.ASYNC;
3607 ModifiersExtensions.Check (allowed_explicit, explicit_mod_flags, 0, Location, Report);
3610 return base.Define ();
3613 protected bool DefineParameters (ParametersCompiled parameters)
3615 if (!parameters.Resolve (this))
3619 for (int i = 0; i < parameters.Count; ++i) {
3620 Parameter p = parameters [i];
3622 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3623 p.Warning_UselessOptionalParameter (Report);
3625 if (p.CheckAccessibility (this))
3628 TypeSpec t = parameters.Types [i];
3629 Report.SymbolRelatedToPreviousError (t);
3630 if (this is Indexer)
3631 Report.Error (55, Location,
3632 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3633 t.GetSignatureForError (), GetSignatureForError ());
3634 else if (this is Operator)
3635 Report.Error (57, Location,
3636 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3637 t.GetSignatureForError (), GetSignatureForError ());
3639 Report.Error (51, Location,
3640 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3641 t.GetSignatureForError (), GetSignatureForError ());
3647 protected override void DoMemberTypeDependentChecks ()
3649 base.DoMemberTypeDependentChecks ();
3651 VarianceDecl.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3654 public override void Emit()
3656 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3657 // We are more strict than csc and report this as an error because SRE does not allow emit that
3658 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3659 if (this is Constructor) {
3660 Report.Warning (824, 1, Location,
3661 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3663 Report.Warning (626, 1, Location,
3664 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3665 GetSignatureForError ());
3672 public override bool EnableOverloadChecks (MemberCore overload)
3675 // Two members can differ in their explicit interface
3676 // type parameter only
3678 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3679 if (imb != null && imb.IsExplicitImpl) {
3680 if (IsExplicitImpl) {
3681 caching_flags |= Flags.MethodOverloadsExist;
3686 return IsExplicitImpl;
3689 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3691 var base_modifiers = base_member.Modifiers;
3693 // Remove internal modifier from types which are not internally accessible
3694 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3695 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3696 base_modifiers = Modifiers.PROTECTED;
3698 Report.SymbolRelatedToPreviousError (base_member);
3699 Report.Error (507, member.Location,
3700 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3701 member.GetSignatureForError (),
3702 ModifiersExtensions.AccessibilityName (base_modifiers),
3703 base_member.GetSignatureForError ());
3706 protected void Error_StaticReturnType ()
3708 Report.Error (722, Location,
3709 "`{0}': static types cannot be used as return types",
3710 MemberType.GetSignatureForError ());
3714 /// Gets base method and its return type
3716 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3718 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3722 // The "short" name of this property / indexer / event. This is the
3723 // name without the explicit interface.
3725 public string ShortName {
3726 get { return MemberName.Name; }
3730 // Returns full metadata method name
3732 public string GetFullName (MemberName name)
3734 return GetFullName (name.Name);
3737 public string GetFullName (string name)
3739 if (!IsExplicitImpl)
3743 // When dealing with explicit members a full interface type
3744 // name is added to member name to avoid possible name conflicts
3746 // We use CSharpName which gets us full name with benefit of
3747 // replacing predefined names which saves some space and name
3750 return InterfaceType.GetSignatureForError () + "." + name;
3753 public override string GetSignatureForDocumentation ()
3756 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetSignatureForDocumentation (true) + "#" + ShortName;
3758 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3761 public override bool IsUsed
3763 get { return IsExplicitImpl || base.IsUsed; }
3766 public override void SetConstraints (List<Constraints> constraints_list)
3768 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3769 Report.Error (460, Location,
3770 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3771 GetSignatureForError ());
3774 base.SetConstraints (constraints_list);
3778 public abstract class MemberBase : MemberCore
3780 protected FullNamedExpression type_expr;
3781 protected TypeSpec member_type;
3782 public new TypeDefinition Parent;
3784 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3785 : base (parent, name, attrs)
3787 this.Parent = parent;
3788 this.type_expr = type;
3790 if (name != MemberName.Null)
3791 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3796 public TypeSpec MemberType {
3802 public FullNamedExpression TypeExpression {
3814 // Main member define entry
3816 public override bool Define ()
3818 DoMemberTypeIndependentChecks ();
3821 // Returns false only when type resolution failed
3823 if (!ResolveMemberType ())
3826 DoMemberTypeDependentChecks ();
3831 // Any type_name independent checks
3833 protected virtual void DoMemberTypeIndependentChecks ()
3835 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3836 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3837 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3838 GetSignatureForError (), Parent.GetSignatureForError ());
3843 // Any type_name dependent checks
3845 protected virtual void DoMemberTypeDependentChecks ()
3847 // verify accessibility
3848 if (!IsAccessibleAs (MemberType)) {
3849 Report.SymbolRelatedToPreviousError (MemberType);
3850 if (this is Property)
3851 Report.Error (53, Location,
3852 "Inconsistent accessibility: property type `" +
3853 MemberType.GetSignatureForError () + "' is less " +
3854 "accessible than property `" + GetSignatureForError () + "'");
3855 else if (this is Indexer)
3856 Report.Error (54, Location,
3857 "Inconsistent accessibility: indexer return type `" +
3858 MemberType.GetSignatureForError () + "' is less " +
3859 "accessible than indexer `" + GetSignatureForError () + "'");
3860 else if (this is MethodCore) {
3861 if (this is Operator)
3862 Report.Error (56, Location,
3863 "Inconsistent accessibility: return type `" +
3864 MemberType.GetSignatureForError () + "' is less " +
3865 "accessible than operator `" + GetSignatureForError () + "'");
3867 Report.Error (50, Location,
3868 "Inconsistent accessibility: return type `" +
3869 MemberType.GetSignatureForError () + "' is less " +
3870 "accessible than method `" + GetSignatureForError () + "'");
3871 } else if (this is Event) {
3872 Report.Error (7025, Location,
3873 "Inconsistent accessibility: event type `{0}' is less accessible than event `{1}'",
3874 MemberType.GetSignatureForError (), GetSignatureForError ());
3876 Report.Error (52, Location,
3877 "Inconsistent accessibility: field type `" +
3878 MemberType.GetSignatureForError () + "' is less " +
3879 "accessible than field `" + GetSignatureForError () + "'");
3884 protected void IsTypePermitted ()
3886 if (MemberType.IsSpecialRuntimeType) {
3887 if (Parent is StateMachine) {
3888 Report.Error (4012, Location,
3889 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3890 MemberType.GetSignatureForError ());
3891 } else if (Parent is HoistedStoreyClass) {
3892 Report.Error (4013, Location,
3893 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3894 MemberType.GetSignatureForError ());
3896 Report.Error (610, Location,
3897 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3902 protected virtual bool CheckBase ()
3904 CheckProtectedModifier ();
3909 public override string GetSignatureForDocumentation ()
3911 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3914 public virtual void PrepareEmit ()
3916 if (member_type != null && type_expr != null)
3917 member_type.CheckObsoleteness (this, type_expr.Location);
3920 protected virtual bool ResolveMemberType ()
3922 if (member_type != null)
3923 throw new InternalErrorException ("Multi-resolve");
3925 member_type = type_expr.ResolveAsType (this);
3926 return member_type != null;