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 // Indicated whether container has StructLayout attribute set Explicit
643 public bool HasExplicitLayout {
644 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
645 set { caching_flags |= Flags.HasExplicitLayout; }
648 public bool HasOperators {
650 return (caching_flags & Flags.HasUserOperators) != 0;
653 caching_flags |= Flags.HasUserOperators;
657 public bool HasStructLayout {
658 get { return (caching_flags & Flags.HasStructLayout) != 0; }
659 set { caching_flags |= Flags.HasStructLayout; }
662 public TypeSpec[] Interfaces {
668 public bool IsGenericOrParentIsGeneric {
670 return all_type_parameters != null;
674 public bool IsTopLevel {
676 return !(Parent is TypeDefinition);
680 public bool IsPartial {
682 return (ModFlags & Modifiers.PARTIAL) != 0;
686 bool ITypeDefinition.IsTypeForwarder {
692 bool ITypeDefinition.IsCyclicTypeForwarder {
699 // Returns true for secondary partial containers
703 return PartialContainer != this;
707 public MemberCache MemberCache {
709 return spec.MemberCache;
713 public List<MemberCore> Members {
719 string ITypeDefinition.Namespace {
722 while (p.Kind != MemberKind.Namespace)
725 return p.MemberName == null ? null : p.GetSignatureForError ();
729 public ParametersCompiled PrimaryConstructorParameters { get; set; }
731 public Arguments PrimaryConstructorBaseArguments { get; set; }
733 public Location PrimaryConstructorBaseArgumentsStart { get; set; }
735 public TypeParameters TypeParametersAll {
737 return all_type_parameters;
741 public override string[] ValidAttributeTargets {
743 return PrimaryConstructorParameters != null ? attribute_targets_primary : attribute_targets;
749 public override void Accept (StructuralVisitor visitor)
751 visitor.Visit (this);
754 public void AddMember (MemberCore symbol)
756 if (symbol.MemberName.ExplicitInterface != null) {
757 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
758 Report.Error (541, symbol.Location,
759 "`{0}': explicit interface declaration can only be declared in a class or struct",
760 symbol.GetSignatureForError ());
764 AddNameToContainer (symbol, symbol.MemberName.Name);
765 members.Add (symbol);
768 public override void AddTypeContainer (TypeContainer tc)
770 AddNameToContainer (tc, tc.MemberName.Basename);
772 base.AddTypeContainer (tc);
775 protected override void AddTypeContainerMember (TypeContainer tc)
779 if (containers == null)
780 containers = new List<TypeContainer> ();
782 base.AddTypeContainerMember (tc);
786 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
788 public virtual void AddNameToContainer (MemberCore symbol, string name)
790 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
794 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
795 PartialContainer.defined_names.Add (name, symbol);
799 if (symbol.EnableOverloadChecks (mc))
802 InterfaceMemberBase im = mc as InterfaceMemberBase;
803 if (im != null && im.IsExplicitImpl)
806 Report.SymbolRelatedToPreviousError (mc);
807 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
808 Error_MissingPartialModifier (symbol);
812 if (symbol is TypeParameter) {
813 Report.Error (692, symbol.Location,
814 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
816 Report.Error (102, symbol.Location,
817 "The type `{0}' already contains a definition for `{1}'",
818 GetSignatureForError (), name);
824 public void AddConstructor (Constructor c)
826 AddConstructor (c, false);
829 public void AddConstructor (Constructor c, bool isDefault)
831 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
833 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
835 if (is_static && c.ParameterInfo.IsEmpty) {
836 PartialContainer.has_static_constructor = true;
838 PartialContainer.HasInstanceConstructor = true;
844 public bool AddField (FieldBase field)
848 if ((field.ModFlags & Modifiers.STATIC) != 0)
851 var first_field = PartialContainer.first_nonstatic_field;
852 if (first_field == null) {
853 PartialContainer.first_nonstatic_field = field;
857 if (Kind == MemberKind.Struct && first_field.Parent != field.Parent) {
858 Report.SymbolRelatedToPreviousError (first_field.Parent);
859 Report.Warning (282, 3, field.Location,
860 "struct instance field `{0}' found in different declaration from instance field `{1}'",
861 field.GetSignatureForError (), first_field.GetSignatureForError ());
867 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
869 public void AddIndexer (Indexer i)
874 public void AddOperator (Operator op)
876 PartialContainer.HasOperators = true;
880 public void AddPartialPart (TypeDefinition part)
882 if (Kind != MemberKind.Class)
885 if (class_partial_parts == null)
886 class_partial_parts = new List<TypeDefinition> ();
888 class_partial_parts.Add (part);
891 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
893 if (a.Target == AttributeTargets.Method) {
894 foreach (var m in members) {
895 var c = m as Constructor;
899 if (c.IsPrimaryConstructor) {
900 c.ApplyAttributeBuilder (a, ctor, cdata, pa);
905 throw new InternalErrorException ();
908 if (has_normal_indexers && a.Type == pa.DefaultMember) {
909 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
913 if (a.Type == pa.Required) {
914 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
918 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
921 public override AttributeTargets AttributeTargets {
923 throw new NotSupportedException ();
927 public TypeSpec BaseType {
929 return spec.BaseType;
933 protected virtual TypeAttributes TypeAttr {
935 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
939 public int TypeParametersCount {
941 return MemberName.Arity;
945 TypeParameterSpec[] ITypeDefinition.TypeParameters {
947 var ctp = PartialContainer.CurrentTypeParameters;
948 return ctp == null ? TypeParameterSpec.EmptyTypes : ctp.Types;
952 public string GetAttributeDefaultMember ()
954 return indexer_name ?? DefaultIndexerName;
957 public bool IsComImport {
959 if (OptAttributes == null)
962 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
966 public void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
969 PartialContainer.RegisterFieldForInitialization (field, expression);
971 if ((field.ModFlags & Modifiers.STATIC) != 0){
972 if (initialized_static_fields == null) {
973 HasStaticFieldInitializer = true;
974 initialized_static_fields = new List<FieldInitializer> (4);
977 initialized_static_fields.Add (expression);
979 if (Kind == MemberKind.Struct) {
980 if (Compiler.Settings.Version != LanguageVersion.Experimental) {
981 Report.Error (573, expression.Location, "'{0}': Structs cannot have instance property or field initializers",
982 GetSignatureForError ());
986 if (initialized_fields == null)
987 initialized_fields = new List<FieldInitializer> (4);
989 initialized_fields.Add (expression);
993 public void ResolveFieldInitializers (BlockContext ec)
995 Debug.Assert (!IsPartialPart);
998 if (initialized_static_fields == null)
1001 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
1003 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
1004 for (i = 0; i < initialized_static_fields.Count; ++i) {
1005 FieldInitializer fi = initialized_static_fields [i];
1006 ExpressionStatement s = fi.ResolveStatement (ec);
1008 s = EmptyExpressionStatement.Instance;
1009 } else if (!fi.IsSideEffectFree) {
1010 has_complex_initializer = true;
1016 for (i = 0; i < initialized_static_fields.Count; ++i) {
1017 FieldInitializer fi = initialized_static_fields [i];
1019 // Need special check to not optimize code like this
1020 // static int a = b = 5;
1021 // static int b = 0;
1023 if (!has_complex_initializer && fi.IsDefaultInitializer)
1026 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1027 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
1033 if (initialized_fields == null)
1036 for (int i = 0; i < initialized_fields.Count; ++i) {
1037 FieldInitializer fi = initialized_fields [i];
1040 // Clone before resolving otherwise when field initializer is needed
1041 // in more than 1 constructor any resolve after the initial one would
1042 // only took the resolved expression which is problem for expressions
1043 // that generate extra expressions or code during Resolve phase
1045 var cloned = fi.Clone (new CloneContext ());
1047 ExpressionStatement s = fi.ResolveStatement (ec);
1049 initialized_fields [i] = new FieldInitializer (fi.Field, ErrorExpression.Instance, Location.Null);
1054 // Field is re-initialized to its default value => removed
1056 if (fi.IsDefaultInitializer && Kind != MemberKind.Struct && ec.Module.Compiler.Settings.Optimize)
1059 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1060 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
1061 initialized_fields [i] = (FieldInitializer) cloned;
1065 public override string DocComment {
1077 public PendingImplementation PendingImplementations {
1078 get { return pending; }
1081 internal override void GenerateDocComment (DocumentationBuilder builder)
1086 base.GenerateDocComment (builder);
1088 foreach (var member in members)
1089 member.GenerateDocComment (builder);
1092 public TypeSpec GetAttributeCoClass ()
1094 if (OptAttributes == null)
1097 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
1101 return a.GetCoClassAttributeValue ();
1104 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1107 if (OptAttributes != null) {
1108 a = OptAttributes.Search (pa);
1114 return a.GetAttributeUsageAttribute ();
1117 public virtual CompilationSourceFile GetCompilationSourceFile ()
1119 TypeContainer ns = Parent;
1121 var sf = ns as CompilationSourceFile;
1129 public override string GetSignatureForMetadata ()
1131 if (Parent is TypeDefinition) {
1132 return Parent.GetSignatureForMetadata () + "+" + TypeNameParser.Escape (FilterNestedName (MemberName.Basename));
1135 return base.GetSignatureForMetadata ();
1138 public virtual void SetBaseTypes (List<FullNamedExpression> baseTypes)
1140 type_bases = baseTypes;
1144 /// This function computes the Base class and also the
1145 /// list of interfaces that the class or struct @c implements.
1147 /// The return value is an array (might be null) of
1148 /// interfaces implemented (as Types).
1150 /// The @base_class argument is set to the base object or null
1151 /// if this is `System.Object'.
1153 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1156 if (type_bases == null)
1159 int count = type_bases.Count;
1160 TypeSpec[] ifaces = null;
1161 var base_context = new BaseContext (this);
1162 for (int i = 0, j = 0; i < count; i++){
1163 FullNamedExpression fne = type_bases [i];
1165 var fne_resolved = fne.ResolveAsType (base_context);
1166 if (fne_resolved == null)
1169 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1170 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1171 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1172 GetSignatureForError ());
1177 base_type = fne_resolved;
1183 ifaces = new TypeSpec [count - i];
1185 if (fne_resolved.IsInterface) {
1186 for (int ii = 0; ii < j; ++ii) {
1187 if (fne_resolved == ifaces [ii]) {
1188 Report.Error (528, Location, "`{0}' is already listed in interface list",
1189 fne_resolved.GetSignatureForError ());
1194 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1195 Report.Error (61, fne.Location,
1196 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1197 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1200 Report.SymbolRelatedToPreviousError (fne_resolved);
1201 if (Kind != MemberKind.Class) {
1202 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1203 } else if (base_class != null)
1204 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1205 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1207 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1208 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1212 ifaces [j++] = fne_resolved;
1219 // Checks that some operators come in pairs:
1225 // They are matched based on the return type and the argument types
1227 void CheckPairedOperators ()
1229 bool has_equality_or_inequality = false;
1230 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1232 for (int i = 0; i < members.Count; ++i) {
1233 var o_a = members[i] as Operator;
1237 var o_type = o_a.OperatorType;
1238 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1239 has_equality_or_inequality = true;
1241 if (found_matched.Contains (o_type))
1244 var matching_type = o_a.GetMatchingOperator ();
1245 if (matching_type == Operator.OpType.TOP) {
1249 bool pair_found = false;
1250 for (int ii = 0; ii < members.Count; ++ii) {
1251 var o_b = members[ii] as Operator;
1252 if (o_b == null || o_b.OperatorType != matching_type)
1255 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1258 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1261 found_matched.Add (matching_type);
1267 Report.Error (216, o_a.Location,
1268 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1269 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1273 if (has_equality_or_inequality) {
1275 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1276 GetSignatureForError ());
1278 if (!HasGetHashCode)
1279 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1280 GetSignatureForError ());
1284 public override void CreateMetadataName (StringBuilder sb)
1286 if (Parent.MemberName != null) {
1287 Parent.CreateMetadataName (sb);
1289 if (sb.Length != 0) {
1294 sb.Append (MemberName.Basename);
1297 bool CreateTypeBuilder ()
1300 // Sets .size to 1 for structs with no instance fields
1302 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null && !(this is StateMachine) ? 1 : 0;
1304 var parent_def = Parent as TypeDefinition;
1305 if (parent_def == null) {
1306 var sb = new StringBuilder ();
1307 CreateMetadataName (sb);
1308 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1310 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (FilterNestedName (MemberName.Basename), TypeAttr, null, type_size);
1313 if (DeclaringAssembly.Importer != null)
1314 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1316 spec.SetMetaInfo (TypeBuilder);
1317 spec.MemberCache = new MemberCache (this);
1319 TypeParameters parentAllTypeParameters = null;
1320 if (parent_def != null) {
1321 spec.DeclaringType = Parent.CurrentType;
1322 parent_def.MemberCache.AddMember (spec);
1323 parentAllTypeParameters = parent_def.all_type_parameters;
1326 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1327 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1329 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1331 if (CurrentTypeParameters != null) {
1332 CurrentTypeParameters.Create (spec, CurrentTypeParametersStartIndex, this);
1333 CurrentTypeParameters.Define (all_tp_builders);
1340 public static string FilterNestedName (string name)
1343 // SRE API does not handle namespaces and types separately but
1344 // determine that from '.' in name. That's problematic because
1345 // dot is valid character for type name. By replacing any '.'
1346 // in name we avoid any ambiguities and never emit metadata
1347 // namespace for nested types
1349 return name.Replace ('.', '_');
1352 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1355 int parent_offset = 0;
1356 if (parentAllTypeParameters != null) {
1357 if (CurrentTypeParameters == null) {
1358 all_type_parameters = parentAllTypeParameters;
1359 return parentAllTypeParameters.GetAllNames ();
1362 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1363 all_type_parameters = new TypeParameters (names.Length);
1364 all_type_parameters.Add (parentAllTypeParameters);
1366 parent_offset = all_type_parameters.Count;
1367 for (int i = 0; i < parent_offset; ++i)
1368 names[i] = all_type_parameters[i].MemberName.Name;
1371 names = new string[CurrentTypeParameters.Count];
1374 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1375 if (all_type_parameters != null)
1376 all_type_parameters.Add (MemberName.TypeParameters[i]);
1378 var name = CurrentTypeParameters[i].MemberName.Name;
1379 names[parent_offset + i] = name;
1380 for (int ii = 0; ii < parent_offset + i; ++ii) {
1381 if (names[ii] != name)
1384 var tp = CurrentTypeParameters[i];
1385 var conflict = all_type_parameters[ii];
1387 tp.WarningParentNameConflict (conflict);
1391 if (all_type_parameters == null)
1392 all_type_parameters = CurrentTypeParameters;
1398 public SourceMethodBuilder CreateMethodSymbolEntry ()
1400 if (Module.DeclaringAssembly.SymbolWriter == null || (ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1403 var source_file = GetCompilationSourceFile ();
1404 if (source_file == null)
1407 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1411 // Creates a proxy base method call inside this container for hoisted base member calls
1413 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1415 Method proxy_method;
1418 // One proxy per base method is enough
1420 if (hoisted_base_call_proxies == null) {
1421 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1422 proxy_method = null;
1424 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1427 if (proxy_method == null) {
1428 string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1430 MemberName member_name;
1431 TypeArguments targs = null;
1432 TypeSpec return_type = method.ReturnType;
1433 var local_param_types = method.Parameters.Types;
1435 if (method.IsGeneric) {
1437 // Copy all base generic method type parameters info
1439 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1440 var tparams = new TypeParameters ();
1442 targs = new TypeArguments ();
1443 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1444 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1445 var tp = hoisted_tparams[i];
1446 var tp_name = tp.Name;
1448 tp_name += "_Proxy";
1450 var local_tp = new TypeParameter (tp, null, new MemberName (tp_name, Location), null);
1451 tparams.Add (local_tp);
1453 targs.Add (new SimpleName (tp.Name, Location));
1454 targs.Arguments[i] = local_tp.Type;
1457 member_name = new MemberName (name, tparams, Location);
1460 // Mutate any method type parameters from original
1461 // to newly created hoisted version
1463 var mutator = new TypeParameterMutator (hoisted_tparams, tparams);
1464 return_type = mutator.Mutate (return_type);
1465 local_param_types = mutator.Mutate (local_param_types);
1467 var inflator = new TypeParameterInflator (this, null, hoisted_tparams, targs.Arguments);
1468 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1469 var tp_spec = (TypeParameterSpec) targs.Arguments [i];
1470 tp_spec.InflateConstraints (inflator, tp_spec);
1473 member_name = new MemberName (name);
1476 var base_parameters = new Parameter[method.Parameters.Count];
1477 for (int i = 0; i < base_parameters.Length; ++i) {
1478 var base_param = method.Parameters.FixedParameters[i];
1479 base_parameters[i] = new Parameter (new TypeExpression (local_param_types [i], Location),
1480 base_param.Name, base_param.ModFlags, null, Location);
1481 base_parameters[i].Resolve (this, i);
1484 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, local_param_types);
1485 if (method.Parameters.HasArglist) {
1486 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1487 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1490 // Compiler generated proxy
1491 proxy_method = new Method (this, new TypeExpression (return_type, Location),
1492 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1493 member_name, cloned_params, null);
1495 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1496 IsCompilerGenerated = true
1499 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1500 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1502 mg.SetTypeArguments (rc, targs);
1504 // Get all the method parameters and pass them as arguments
1505 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1506 Statement statement;
1507 if (method.ReturnType.Kind == MemberKind.Void)
1508 statement = new StatementExpression (real_base_call);
1510 statement = new Return (real_base_call, Location);
1512 block.AddStatement (statement);
1513 proxy_method.Block = block;
1515 members.Add (proxy_method);
1516 proxy_method.Define ();
1517 proxy_method.PrepareEmit ();
1519 hoisted_base_call_proxies.Add (method, proxy_method);
1522 return proxy_method.Spec;
1525 protected bool DefineBaseTypes ()
1527 if (IsPartialPart && Kind == MemberKind.Class)
1530 return DoDefineBaseType ();
1533 bool DoDefineBaseType ()
1535 iface_exprs = ResolveBaseTypes (out base_type_expr);
1538 if (IsPartialPart) {
1539 set_base_type = false;
1541 if (base_type_expr != null) {
1542 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1543 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1544 Report.Error (263, Location,
1545 "Partial declarations of `{0}' must not specify different base classes",
1546 GetSignatureForError ());
1548 PartialContainer.base_type_expr = base_type_expr;
1549 PartialContainer.base_type = base_type;
1550 set_base_type = true;
1554 if (iface_exprs != null) {
1555 if (PartialContainer.iface_exprs == null)
1556 PartialContainer.iface_exprs = iface_exprs;
1558 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1559 foreach (var iface_partial in iface_exprs) {
1560 if (ifaces.Contains (iface_partial))
1563 ifaces.Add (iface_partial);
1566 PartialContainer.iface_exprs = ifaces.ToArray ();
1570 PartialContainer.members.AddRange (members);
1571 if (containers != null) {
1572 if (PartialContainer.containers == null)
1573 PartialContainer.containers = new List<TypeContainer> ();
1575 PartialContainer.containers.AddRange (containers);
1578 if (PrimaryConstructorParameters != null) {
1579 if (PartialContainer.PrimaryConstructorParameters != null) {
1580 Report.Error (8036, Location, "Only one part of a partial type can declare primary constructor parameters");
1582 PartialContainer.PrimaryConstructorParameters = PrimaryConstructorParameters;
1586 members_defined = members_defined_ok = true;
1587 caching_flags |= Flags.CloseTypeCreated;
1589 set_base_type = true;
1592 var cycle = CheckRecursiveDefinition (this);
1593 if (cycle != null) {
1594 Report.SymbolRelatedToPreviousError (cycle);
1595 if (this is Interface) {
1596 Report.Error (529, Location,
1597 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1598 GetSignatureForError (), cycle.GetSignatureForError ());
1601 PartialContainer.iface_exprs = null;
1603 Report.Error (146, Location,
1604 "Circular base class dependency involving `{0}' and `{1}'",
1605 GetSignatureForError (), cycle.GetSignatureForError ());
1608 PartialContainer.base_type = null;
1612 if (iface_exprs != null) {
1613 if (!PrimaryConstructorBaseArgumentsStart.IsNull) {
1614 Report.Error (8049, PrimaryConstructorBaseArgumentsStart, "Implemented interfaces cannot have arguments");
1617 foreach (var iface_type in iface_exprs) {
1618 // Prevents a crash, the interface might not have been resolved: 442144
1619 if (iface_type == null)
1622 if (!spec.AddInterfaceDefined (iface_type))
1625 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1629 if (Kind == MemberKind.Interface) {
1630 spec.BaseType = Compiler.BuiltinTypes.Object;
1634 if (set_base_type) {
1639 // Base type of partial container has to be resolved before we
1640 // resolve any nested types of the container. We need to know
1641 // partial parts because the base type can be specified in file
1642 // defined after current container
1644 if (class_partial_parts != null) {
1645 foreach (var pp in class_partial_parts) {
1646 if (pp.PrimaryConstructorBaseArguments != null)
1647 PrimaryConstructorBaseArguments = pp.PrimaryConstructorBaseArguments;
1649 pp.DoDefineBaseType ();
1659 if (base_type == null) {
1660 TypeBuilder.SetParent (null);
1664 if (spec.BaseType == base_type)
1667 spec.BaseType = base_type;
1670 spec.UpdateInflatedInstancesBaseType ();
1672 // Set base type after type creation
1673 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1676 public override void ExpandBaseInterfaces ()
1678 DoResolveTypeParameters ();
1681 DoExpandBaseInterfaces ();
1683 base.ExpandBaseInterfaces ();
1686 public void DoExpandBaseInterfaces ()
1688 if ((caching_flags & Flags.InterfacesExpanded) != 0)
1691 caching_flags |= Flags.InterfacesExpanded;
1694 // Expand base interfaces. It cannot be done earlier because all partial
1695 // interface parts need to be defined before the type they are used from
1697 if (iface_exprs != null) {
1698 foreach (var iface in iface_exprs) {
1702 var td = iface.MemberDefinition as TypeDefinition;
1704 td.DoExpandBaseInterfaces ();
1706 if (iface.Interfaces == null)
1709 foreach (var biface in iface.Interfaces) {
1710 if (spec.AddInterfaceDefined (biface)) {
1711 TypeBuilder.AddInterfaceImplementation (biface.GetMetaInfo ());
1718 // Include all base type interfaces too, see ImportTypeBase for details
1720 if (base_type != null) {
1721 var td = base_type.MemberDefinition as TypeDefinition;
1723 td.DoExpandBaseInterfaces ();
1726 // Simply use base interfaces only, they are all expanded which makes
1727 // it easy to handle generic type argument propagation with single
1730 // interface IA<T> : IB<T>
1731 // interface IB<U> : IC<U>
1734 if (base_type.Interfaces != null) {
1735 foreach (var iface in base_type.Interfaces) {
1736 spec.AddInterfaceDefined (iface);
1742 public override void PrepareEmit ()
1744 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1747 foreach (var member in members) {
1748 var pbm = member as MemberBase;
1753 base.PrepareEmit ();
1757 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1759 public override bool CreateContainer ()
1761 if (TypeBuilder != null)
1767 if (IsPartialPart) {
1768 spec = PartialContainer.spec;
1769 TypeBuilder = PartialContainer.TypeBuilder;
1770 all_tp_builders = PartialContainer.all_tp_builders;
1771 all_type_parameters = PartialContainer.all_type_parameters;
1773 if (!CreateTypeBuilder ()) {
1779 return base.CreateContainer ();
1782 protected override void DoDefineContainer ()
1788 // Replaces normal spec with predefined one when compiling corlib
1789 // and this type container defines predefined type
1791 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1793 // When compiling build-in types we start with two
1794 // version of same type. One is of BuiltinTypeSpec and
1795 // second one is ordinary TypeSpec. The unification
1796 // happens at later stage when we know which type
1797 // really matches the builtin type signature. However
1798 // that means TypeSpec create during CreateType of this
1799 // type has to be replaced with builtin one
1801 spec.SetMetaInfo (TypeBuilder);
1802 spec.MemberCache = this.spec.MemberCache;
1803 spec.DeclaringType = this.spec.DeclaringType;
1806 current_type = null;
1807 if (class_partial_parts != null) {
1808 foreach (var part in class_partial_parts)
1813 public override void RemoveContainer (TypeContainer cont)
1815 base.RemoveContainer (cont);
1816 Members.Remove (cont);
1817 Cache.Remove (cont.MemberName.Basename);
1820 protected virtual bool DoResolveTypeParameters ()
1822 var tparams = MemberName.TypeParameters;
1823 if (tparams == null)
1826 var base_context = new BaseContext (this);
1827 for (int i = 0; i < tparams.Count; ++i) {
1828 var tp = tparams[i];
1830 if (!tp.ResolveConstraints (base_context)) {
1835 if (IsPartialPart) {
1836 var pc_tp = PartialContainer.CurrentTypeParameters [i];
1838 tp.Create (spec, this);
1841 if (tp.OptAttributes != null) {
1842 if (pc_tp.OptAttributes == null)
1843 pc_tp.OptAttributes = tp.OptAttributes;
1845 pc_tp.OptAttributes.Attrs.AddRange (tp.OptAttributes.Attrs);
1850 if (IsPartialPart) {
1851 PartialContainer.CurrentTypeParameters.UpdateConstraints (this);
1857 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1859 if (InTransit != null)
1864 if (base_type != null) {
1865 var ptc = base_type.MemberDefinition as TypeDefinition;
1866 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1870 if (iface_exprs != null && this is Interface) {
1871 foreach (var iface in iface_exprs) {
1872 // the interface might not have been resolved, prevents a crash, see #442144
1875 var ptc = iface.MemberDefinition as Interface;
1876 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1881 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1889 /// Populates our TypeBuilder with fields and methods
1891 public sealed override bool Define ()
1893 if (members_defined)
1894 return members_defined_ok;
1896 members_defined_ok = DoDefineMembers ();
1897 members_defined = true;
1901 return members_defined_ok;
1904 protected virtual bool DoDefineMembers ()
1906 Debug.Assert (!IsPartialPart);
1908 if (iface_exprs != null) {
1909 foreach (var iface_type in iface_exprs) {
1910 if (iface_type == null)
1913 // Ensure the base is always setup
1914 var compiled_iface = iface_type.MemberDefinition as Interface;
1915 if (compiled_iface != null)
1916 compiled_iface.Define ();
1918 iface_type.CheckObsoleteness (this, Location);
1920 if (iface_type.Arity > 0) {
1921 // TODO: passing `this' is wrong, should be base type iface instead
1922 VarianceDecl.CheckTypeVariance (iface_type, Variance.Covariant, this);
1924 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1925 Report.Error (1966, Location,
1926 "`{0}': cannot implement a dynamic interface `{1}'",
1927 GetSignatureForError (), iface_type.GetSignatureForError ());
1932 if (iface_type.IsGenericOrParentIsGeneric) {
1933 foreach (var prev_iface in iface_exprs) {
1934 if (prev_iface == iface_type || prev_iface == null)
1937 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1940 Report.Error (695, Location,
1941 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1942 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1947 if (Kind == MemberKind.Interface) {
1948 foreach (var iface in spec.Interfaces) {
1949 MemberCache.AddInterface (iface);
1954 if (base_type != null) {
1956 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1958 if (base_type_expr != null) {
1959 base_type.CheckObsoleteness (this, base_type_expr.Location);
1961 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1962 Report.Error (698, base_type_expr.Location,
1963 "A generic type cannot derive from `{0}' because it is an attribute class",
1964 base_type.GetSignatureForError ());
1968 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1969 if (baseContainer != null) {
1970 baseContainer.Define ();
1973 // It can trigger define of this type (for generic types only)
1975 if (HasMembersDefined)
1980 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1981 pending = PendingImplementation.GetPendingImplementations (this);
1984 var count = members.Count;
1985 for (int i = 0; i < count; ++i) {
1986 var mc = members[i] as InterfaceMemberBase;
1987 if (mc == null || !mc.IsExplicitImpl)
1992 } catch (Exception e) {
1993 throw new InternalErrorException (mc, e);
1997 for (int i = 0; i < count; ++i) {
1998 var mc = members[i] as InterfaceMemberBase;
1999 if (mc != null && mc.IsExplicitImpl)
2002 if (members[i] is TypeContainer)
2006 members[i].Define ();
2007 } catch (Exception e) {
2008 throw new InternalErrorException (members[i], e);
2013 CheckPairedOperators ();
2016 ComputeIndexerName();
2018 if (HasEquals && !HasGetHashCode) {
2019 Report.Warning (659, 3, Location,
2020 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
2023 if (Kind == MemberKind.Interface && iface_exprs != null) {
2024 MemberCache.RemoveHiddenMembers (spec);
2030 void ComputeIndexerName ()
2032 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
2033 if (indexers == null)
2036 string class_indexer_name = null;
2039 // Check normal indexers for consistent name, explicit interface implementation
2040 // indexers are ignored
2042 foreach (var indexer in indexers) {
2044 // FindMembers can return unfiltered full hierarchy names
2046 if (indexer.DeclaringType != spec)
2049 has_normal_indexers = true;
2051 if (class_indexer_name == null) {
2052 indexer_name = class_indexer_name = indexer.Name;
2056 if (indexer.Name != class_indexer_name)
2057 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
2058 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
2062 void EmitIndexerName ()
2064 if (!has_normal_indexers)
2067 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
2071 var encoder = new AttributeEncoder ();
2072 encoder.Encode (GetAttributeDefaultMember ());
2073 encoder.EncodeEmptyNamedArguments ();
2075 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2078 public override void VerifyMembers ()
2081 // Check for internal or private fields that were never assigned
2083 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
2084 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
2085 foreach (var member in members) {
2086 if (member is Event) {
2088 // An event can be assigned from same class only, report
2089 // this warning for all accessibility modes
2091 if (!member.IsUsed && !PartialContainer.HasStructLayout)
2092 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
2097 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
2098 if (is_type_exposed)
2101 member.SetIsUsed ();
2104 var f = member as Field;
2108 if (!member.IsUsed) {
2109 if (!PartialContainer.HasStructLayout) {
2110 if ((member.caching_flags & Flags.IsAssigned) == 0) {
2111 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
2113 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
2114 member.GetSignatureForError ());
2121 if ((f.caching_flags & Flags.IsAssigned) != 0)
2125 // Only report 649 on level 4
2127 if (Compiler.Settings.WarningLevel < 4)
2131 // Don't be pedantic when type requires specific layout
2133 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2136 Constant c = New.Constantify (f.MemberType, f.Location);
2139 value = c.GetValueAsLiteral ();
2140 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
2147 value = " `" + value + "'";
2149 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
2150 f.GetSignatureForError (), value);
2154 base.VerifyMembers ();
2157 public override void Emit ()
2159 if (OptAttributes != null)
2160 OptAttributes.Emit ();
2162 if (!IsCompilerGenerated) {
2164 MemberSpec candidate;
2165 bool overrides = false;
2166 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
2167 if (conflict_symbol == null && candidate == null) {
2168 if ((ModFlags & Modifiers.NEW) != 0)
2169 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
2170 GetSignatureForError ());
2172 if ((ModFlags & Modifiers.NEW) == 0) {
2173 if (candidate == null)
2174 candidate = conflict_symbol;
2176 Report.SymbolRelatedToPreviousError (candidate);
2177 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
2178 GetSignatureForError (), candidate.GetSignatureForError ());
2183 // Run constraints check on all possible generic types
2184 if (base_type != null && base_type_expr != null) {
2185 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
2188 if (iface_exprs != null) {
2189 foreach (var iface_type in iface_exprs) {
2190 if (iface_type == null)
2193 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2198 if (all_tp_builders != null) {
2199 int current_starts_index = CurrentTypeParametersStartIndex;
2200 for (int i = 0; i < all_tp_builders.Length; i++) {
2201 if (i < current_starts_index) {
2202 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2204 var tp = CurrentTypeParameters [i - current_starts_index];
2205 tp.CheckGenericConstraints (!IsObsolete);
2211 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2212 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2215 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2216 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2221 for (int i = 0; i < members.Count; i++) {
2223 if ((m.caching_flags & Flags.CloseTypeCreated) != 0)
2230 CheckAttributeClsCompliance ();
2232 if (pending != null)
2233 pending.VerifyPendingMethods ();
2237 void CheckAttributeClsCompliance ()
2239 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2242 foreach (var m in members) {
2243 var c = m as Constructor;
2247 if (c.HasCompliantArgs)
2251 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2254 public sealed override void EmitContainer ()
2256 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2262 public override void CloseContainer ()
2264 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2267 // Close base type container first to avoid TypeLoadException
2268 if (spec.BaseType != null) {
2269 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2270 if (btype != null) {
2271 btype.CloseContainer ();
2273 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2279 caching_flags |= Flags.CloseTypeCreated;
2280 TypeBuilder.CreateType ();
2281 } catch (TypeLoadException) {
2283 // This is fine, the code still created the type
2285 } catch (Exception e) {
2286 throw new InternalErrorException (this, e);
2289 base.CloseContainer ();
2292 initialized_fields = null;
2293 initialized_static_fields = null;
2295 OptAttributes = null;
2299 // Performs the validation on a Method's modifiers (properties have
2300 // the same properties).
2302 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2304 public bool MethodModifiersValid (MemberCore mc)
2306 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2307 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2309 var flags = mc.ModFlags;
2312 // At most one of static, virtual or override
2314 if ((flags & Modifiers.STATIC) != 0){
2315 if ((flags & vao) != 0){
2316 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2317 mc.GetSignatureForError ());
2322 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2323 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2324 mc.GetSignatureForError ());
2329 // If the declaration includes the abstract modifier, then the
2330 // declaration does not include static, virtual or extern
2332 if ((flags & Modifiers.ABSTRACT) != 0){
2333 if ((flags & Modifiers.EXTERN) != 0){
2335 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2339 if ((flags & Modifiers.SEALED) != 0) {
2340 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2344 if ((flags & Modifiers.VIRTUAL) != 0){
2345 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2349 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2350 Report.SymbolRelatedToPreviousError (this);
2351 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2352 mc.GetSignatureForError (), GetSignatureForError ());
2357 if ((flags & Modifiers.PRIVATE) != 0){
2358 if ((flags & vao) != 0){
2359 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2364 if ((flags & Modifiers.SEALED) != 0){
2365 if ((flags & Modifiers.OVERRIDE) == 0){
2366 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2374 protected override bool VerifyClsCompliance ()
2376 if (!base.VerifyClsCompliance ())
2379 // Check all container names for user classes
2380 if (Kind != MemberKind.Delegate)
2381 MemberCache.VerifyClsCompliance (Definition, Report);
2383 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2384 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2385 GetSignatureForError (), BaseType.GetSignatureForError ());
2391 /// Performs checks for an explicit interface implementation. First it
2392 /// checks whether the `interface_type' is a base inteface implementation.
2393 /// Then it checks whether `name' exists in the interface type.
2395 public bool VerifyImplements (InterfaceMemberBase mb)
2397 var ifaces = PartialContainer.Interfaces;
2398 if (ifaces != null) {
2399 foreach (TypeSpec t in ifaces){
2400 if (t == mb.InterfaceType || t == null)
2403 var expanded_base = t.Interfaces;
2404 if (expanded_base == null)
2407 foreach (var bt in expanded_base) {
2408 if (bt == mb.InterfaceType)
2414 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2415 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2416 mb.GetSignatureForError (), mb.InterfaceType.GetSignatureForError ());
2421 // Used for visiblity checks to tests whether this definition shares
2422 // base type baseType, it does member-definition search
2424 public bool IsBaseTypeDefinition (TypeSpec baseType)
2426 // RootContext check
2427 if (TypeBuilder == null)
2432 if (type.MemberDefinition == baseType.MemberDefinition)
2435 type = type.BaseType;
2436 } while (type != null);
2441 public override bool IsClsComplianceRequired ()
2444 return PartialContainer.IsClsComplianceRequired ();
2446 return base.IsClsComplianceRequired ();
2449 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2451 return Module.DeclaringAssembly == assembly;
2454 public virtual bool IsUnmanagedType ()
2459 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2461 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2465 // Public function used to locate types.
2467 // Returns: Type or null if they type can not be found.
2469 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2471 FullNamedExpression e;
2472 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2478 var tp = CurrentTypeParameters;
2480 TypeParameter tparam = tp.Find (name);
2482 e = new TypeParameterExpr (tparam, Location.Null);
2487 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2489 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2490 e = new TypeExpression (t, Location.Null);
2492 var errors = Compiler.Report.Errors;
2493 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2495 // TODO: LookupNamespaceOrType does more than just lookup. The result
2496 // cannot be cached or the error reporting won't happen
2497 if (errors != Compiler.Report.Errors)
2502 // TODO MemberCache: How to cache arity stuff ?
2503 if (arity == 0 && mode == LookupMode.Normal)
2509 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2511 // Has any nested type
2512 // Does not work, because base type can have
2513 //if (PartialContainer.Types == null)
2516 var container = PartialContainer.CurrentType;
2517 return MemberCache.FindNestedType (container, name, arity, false);
2520 public void Mark_HasEquals ()
2522 cached_method |= CachedMethods.Equals;
2525 public void Mark_HasGetHashCode ()
2527 cached_method |= CachedMethods.GetHashCode;
2530 public override void WriteDebugSymbol (MonoSymbolFile file)
2535 foreach (var m in members) {
2536 m.WriteDebugSymbol (file);
2541 /// Method container contains Equals method
2543 public bool HasEquals {
2545 return (cached_method & CachedMethods.Equals) != 0;
2550 /// Method container contains GetHashCode method
2552 public bool HasGetHashCode {
2554 return (cached_method & CachedMethods.GetHashCode) != 0;
2558 public bool HasStaticFieldInitializer {
2560 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2564 cached_method |= CachedMethods.HasStaticFieldInitializer;
2566 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2570 public override string DocCommentHeader {
2571 get { return "T:"; }
2575 public abstract class ClassOrStruct : TypeDefinition
2577 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2579 SecurityType declarative_security;
2580 protected Constructor generated_primary_constructor;
2582 protected ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2583 : base (parent, name, attrs, kind)
2587 public ToplevelBlock PrimaryConstructorBlock { get; set; }
2589 protected override TypeAttributes TypeAttr {
2591 TypeAttributes ta = base.TypeAttr;
2592 if (!has_static_constructor)
2593 ta |= TypeAttributes.BeforeFieldInit;
2595 if (Kind == MemberKind.Class) {
2596 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2598 ta |= StaticClassAttribute;
2600 ta |= TypeAttributes.SequentialLayout;
2607 public override void AddNameToContainer (MemberCore symbol, string name)
2609 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2610 if (symbol is TypeParameter) {
2611 Report.Error (694, symbol.Location,
2612 "Type parameter `{0}' has same name as containing type, or method",
2613 symbol.GetSignatureForError ());
2617 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2618 if (imb == null || !imb.IsExplicitImpl) {
2619 Report.SymbolRelatedToPreviousError (this);
2620 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2621 symbol.GetSignatureForError ());
2626 base.AddNameToContainer (symbol, name);
2629 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2631 if (a.IsValidSecurityAttribute ()) {
2632 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2636 if (a.Type == pa.StructLayout) {
2637 PartialContainer.HasStructLayout = true;
2638 if (a.IsExplicitLayoutKind ())
2639 PartialContainer.HasExplicitLayout = true;
2642 if (a.Type == pa.Dynamic) {
2643 a.Error_MisusedDynamicAttribute ();
2647 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2651 /// Defines the default constructors
2653 protected virtual Constructor DefineDefaultConstructor (bool is_static)
2655 // The default instance constructor is public
2656 // If the class is abstract, the default constructor is protected
2657 // The default static constructor is private
2660 ParametersCompiled parameters = null;
2662 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2663 parameters = ParametersCompiled.EmptyReadOnlyParameters;
2665 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2666 parameters = PrimaryConstructorParameters ?? ParametersCompiled.EmptyReadOnlyParameters;
2669 var c = new Constructor (this, MemberName.Name, mods, null, parameters, Location);
2670 if (Kind == MemberKind.Class)
2671 c.Initializer = new GeneratedBaseInitializer (Location, PrimaryConstructorBaseArguments);
2673 if (PrimaryConstructorParameters != null && !is_static) {
2674 c.IsPrimaryConstructor = true;
2675 c.caching_flags |= Flags.MethodOverloadsExist;
2678 AddConstructor (c, true);
2679 if (PrimaryConstructorBlock == null) {
2680 c.Block = new ToplevelBlock (Compiler, parameters, Location) {
2681 IsCompilerGenerated = true
2684 c.Block = PrimaryConstructorBlock;
2690 protected override bool DoDefineMembers ()
2692 CheckProtectedModifier ();
2694 if (PrimaryConstructorParameters != null) {
2696 foreach (Parameter p in PrimaryConstructorParameters.FixedParameters) {
2697 if (p.Name == MemberName.Name) {
2698 Report.Error (8039, p.Location, "Primary constructor of type `{0}' has parameter of same name as containing type",
2699 GetSignatureForError ());
2702 if (CurrentTypeParameters != null) {
2703 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
2704 var tp = CurrentTypeParameters [i];
2705 if (p.Name == tp.Name) {
2706 Report.Error (8038, p.Location, "Primary constructor of type `{0}' has parameter of same name as type parameter `{1}'",
2707 GetSignatureForError (), p.GetSignatureForError ());
2714 base.DoDefineMembers ();
2719 public override void PrepareEmit ()
2721 var s = this as Struct;
2722 if (s == null || !s.HasUnmanagedCheckDone) {
2723 for (int i = 0; i < Members.Count; ++i) {
2724 var f = Members [i] as Field;
2725 if (f == null || f.MemberType == null || !f.MemberType.IsPointer)
2728 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
2732 base.PrepareEmit ();
2735 public override void Emit ()
2737 if (!has_static_constructor && HasStaticFieldInitializer) {
2738 var c = DefineDefaultConstructor (true);
2744 if (declarative_security != null) {
2745 foreach (var de in declarative_security) {
2747 TypeBuilder.__AddDeclarativeSecurity (de);
2749 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2757 public sealed class Class : ClassOrStruct
2759 const Modifiers AllowedModifiers =
2762 Modifiers.PROTECTED |
2763 Modifiers.INTERNAL |
2765 Modifiers.ABSTRACT |
2770 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2771 : base (parent, name, attrs, MemberKind.Class)
2773 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2774 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2775 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2778 public override void Accept (StructuralVisitor visitor)
2780 visitor.Visit (this);
2783 public override void SetBaseTypes (List<FullNamedExpression> baseTypes)
2785 var pmn = MemberName;
2786 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2787 Report.Error (537, Location,
2788 "The class System.Object cannot have a base class or implement an interface.");
2790 base.SetBaseTypes (baseTypes);
2793 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2795 if (a.Type == pa.AttributeUsage) {
2796 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2797 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2801 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2802 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2806 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2807 a.Error_MissingGuidAttribute ();
2811 if (a.Type == pa.Extension) {
2812 a.Error_MisusedExtensionAttribute ();
2816 if (a.Type.IsConditionallyExcluded (this))
2819 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2822 public override AttributeTargets AttributeTargets {
2824 return AttributeTargets.Class;
2828 protected override bool DoDefineMembers ()
2830 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2831 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2834 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2835 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2839 if (PrimaryConstructorParameters != null) {
2840 Report.Error (-800, Location, "`{0}': Static classes cannot have primary constructor", GetSignatureForError ());
2841 PrimaryConstructorParameters = null;
2844 foreach (var m in Members) {
2845 if (m is Operator) {
2846 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2850 if (m is Destructor) {
2851 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2856 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2860 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2863 if (m is Constructor) {
2864 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2868 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2871 if (!PartialContainer.HasInstanceConstructor || PrimaryConstructorParameters != null)
2872 generated_primary_constructor = DefineDefaultConstructor (false);
2875 return base.DoDefineMembers ();
2878 public override void Emit ()
2882 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2883 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2885 if (base_type != null && base_type.HasDynamicElement) {
2886 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2890 public override void GetCompletionStartingWith (string prefix, List<string> results)
2892 base.GetCompletionStartingWith (prefix, results);
2895 while (bt != null) {
2896 results.AddRange (MemberCache.GetCompletitionMembers (this, bt, prefix).Where (l => l.IsStatic).Select (l => l.Name));
2901 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2903 var ifaces = base.ResolveBaseTypes (out base_class);
2905 if (base_class == null) {
2906 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2907 base_type = Compiler.BuiltinTypes.Object;
2909 if (base_type.IsGenericParameter){
2910 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2911 GetSignatureForError (), base_type.GetSignatureForError ());
2912 } else if (base_type.IsStatic) {
2913 Report.SymbolRelatedToPreviousError (base_type);
2914 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2915 GetSignatureForError (), base_type.GetSignatureForError ());
2916 } else if (base_type.IsSealed) {
2917 Report.SymbolRelatedToPreviousError (base_type);
2918 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2919 GetSignatureForError (), base_type.GetSignatureForError ());
2920 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2921 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2922 GetSignatureForError (), base_type.GetSignatureForError ());
2925 switch (base_type.BuiltinType) {
2926 case BuiltinTypeSpec.Type.Enum:
2927 case BuiltinTypeSpec.Type.ValueType:
2928 case BuiltinTypeSpec.Type.MulticastDelegate:
2929 case BuiltinTypeSpec.Type.Delegate:
2930 case BuiltinTypeSpec.Type.Array:
2931 if (!(spec is BuiltinTypeSpec)) {
2932 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2933 GetSignatureForError (), base_type.GetSignatureForError ());
2935 base_type = Compiler.BuiltinTypes.Object;
2940 if (!IsAccessibleAs (base_type)) {
2941 Report.SymbolRelatedToPreviousError (base_type);
2942 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2943 base_type.GetSignatureForError (), GetSignatureForError ());
2947 if (PartialContainer.IsStatic && ifaces != null) {
2948 foreach (var t in ifaces)
2949 Report.SymbolRelatedToPreviousError (t);
2950 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2956 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2957 /// Valid only for attribute classes.
2958 public override string[] ConditionalConditions ()
2960 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2963 caching_flags &= ~Flags.Excluded_Undetected;
2965 if (OptAttributes == null)
2968 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2972 string[] conditions = new string[attrs.Length];
2973 for (int i = 0; i < conditions.Length; ++i)
2974 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2976 caching_flags |= Flags.Excluded;
2981 public sealed class Struct : ClassOrStruct
2983 bool is_unmanaged, has_unmanaged_check_done, requires_delayed_unmanagedtype_check;
2987 // Modifiers allowed in a struct declaration
2989 const Modifiers AllowedModifiers =
2992 Modifiers.PROTECTED |
2993 Modifiers.INTERNAL |
2997 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2998 : base (parent, name, attrs, MemberKind.Struct)
3000 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3001 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
3002 spec = new TypeSpec (Kind, null, this, null, ModFlags);
3005 public override AttributeTargets AttributeTargets {
3007 return AttributeTargets.Struct;
3011 public override void Accept (StructuralVisitor visitor)
3013 visitor.Visit (this);
3016 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3018 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3021 // When struct constains fixed fixed and struct layout has explicitly
3022 // set CharSet, its value has to be propagated to compiler generated
3025 if (a.Type == pa.StructLayout) {
3026 var value = a.GetNamedValue ("CharSet");
3030 for (int i = 0; i < Members.Count; ++i) {
3031 FixedField ff = Members [i] as FixedField;
3035 ff.CharSetValue = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
3040 bool CheckStructCycles ()
3046 foreach (var member in Members) {
3047 var field = member as Field;
3051 TypeSpec ftype = field.Spec.MemberType;
3052 if (!ftype.IsStruct)
3055 if (ftype is BuiltinTypeSpec)
3058 foreach (var targ in ftype.TypeArguments) {
3059 if (!CheckFieldTypeCycle (targ)) {
3060 Report.Error (523, field.Location,
3061 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3062 field.GetSignatureForError (), ftype.GetSignatureForError ());
3068 // Static fields of exactly same type are allowed
3070 if (field.IsStatic && ftype == CurrentType)
3073 if (!CheckFieldTypeCycle (ftype)) {
3074 Report.Error (523, field.Location,
3075 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3076 field.GetSignatureForError (), ftype.GetSignatureForError ());
3085 static bool CheckFieldTypeCycle (TypeSpec ts)
3087 var fts = ts.MemberDefinition as Struct;
3091 return fts.CheckStructCycles ();
3094 protected override bool DoDefineMembers ()
3096 var res = base.DoDefineMembers ();
3098 if (PrimaryConstructorParameters != null || (initialized_fields != null && !HasUserDefaultConstructor ())) {
3099 generated_primary_constructor = DefineDefaultConstructor (false);
3100 generated_primary_constructor.Define ();
3106 public override void Emit ()
3108 CheckStructCycles ();
3113 public bool HasUnmanagedCheckDone {
3115 return has_unmanaged_check_done;
3119 bool HasUserDefaultConstructor ()
3121 foreach (var m in PartialContainer.Members) {
3122 var c = m as Constructor;
3126 if (!c.IsStatic && c.ParameterInfo.IsEmpty)
3133 public override bool IsUnmanagedType ()
3135 if (has_unmanaged_check_done)
3136 return is_unmanaged;
3138 if (requires_delayed_unmanagedtype_check)
3141 var parent_def = Parent.PartialContainer;
3142 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
3143 has_unmanaged_check_done = true;
3147 if (first_nonstatic_field != null) {
3148 requires_delayed_unmanagedtype_check = true;
3150 foreach (var member in Members) {
3151 var f = member as Field;
3158 // It can happen when recursive unmanaged types are defined
3159 // struct S { S* s; }
3160 TypeSpec mt = f.MemberType;
3168 has_unmanaged_check_done = true;
3172 has_unmanaged_check_done = true;
3175 is_unmanaged = true;
3179 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
3181 var ifaces = base.ResolveBaseTypes (out base_class);
3182 base_type = Compiler.BuiltinTypes.ValueType;
3190 public sealed class Interface : TypeDefinition {
3193 /// Modifiers allowed in a class declaration
3195 const Modifiers AllowedModifiers =
3198 Modifiers.PROTECTED |
3199 Modifiers.INTERNAL |
3203 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
3204 : base (parent, name, attrs, MemberKind.Interface)
3206 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3208 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
3209 spec = new TypeSpec (Kind, null, this, null, ModFlags);
3214 public override AttributeTargets AttributeTargets {
3216 return AttributeTargets.Interface;
3220 protected override TypeAttributes TypeAttr {
3222 const TypeAttributes DefaultTypeAttributes =
3223 TypeAttributes.AutoLayout |
3224 TypeAttributes.Abstract |
3225 TypeAttributes.Interface;
3227 return base.TypeAttr | DefaultTypeAttributes;
3233 public override void Accept (StructuralVisitor visitor)
3235 visitor.Visit (this);
3238 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3240 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3241 a.Error_MissingGuidAttribute ();
3245 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3248 protected override bool VerifyClsCompliance ()
3250 if (!base.VerifyClsCompliance ())
3253 if (iface_exprs != null) {
3254 foreach (var iface in iface_exprs) {
3255 if (iface.IsCLSCompliant ())
3258 Report.SymbolRelatedToPreviousError (iface);
3259 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3260 GetSignatureForError (), iface.GetSignatureForError ());
3268 public abstract class InterfaceMemberBase : MemberBase
3271 // Common modifiers allowed in a class declaration
3273 protected const Modifiers AllowedModifiersClass =
3276 Modifiers.PROTECTED |
3277 Modifiers.INTERNAL |
3282 Modifiers.OVERRIDE |
3283 Modifiers.ABSTRACT |
3288 // Common modifiers allowed in a struct declaration
3290 protected const Modifiers AllowedModifiersStruct =
3293 Modifiers.PROTECTED |
3294 Modifiers.INTERNAL |
3297 Modifiers.OVERRIDE |
3302 // Common modifiers allowed in a interface declaration
3304 protected const Modifiers AllowedModifiersInterface =
3309 // Whether this is an interface member.
3311 public bool IsInterface;
3314 // If true, this is an explicit interface implementation
3316 public readonly bool IsExplicitImpl;
3318 protected bool is_external_implementation;
3321 // The interface type we are explicitly implementing
3323 public TypeSpec InterfaceType;
3326 // The method we're overriding if this is an override method.
3328 protected MethodSpec base_method;
3330 readonly Modifiers explicit_mod_flags;
3331 public MethodAttributes flags;
3333 protected InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3334 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3336 IsInterface = parent.Kind == MemberKind.Interface;
3337 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3338 explicit_mod_flags = mod;
3341 public abstract Variance ExpectedMemberTypeVariance { get; }
3343 protected override bool CheckBase ()
3345 if (!base.CheckBase ())
3348 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3349 CheckForDuplications ();
3354 // For System.Object only
3355 if (Parent.BaseType == null)
3358 MemberSpec candidate;
3359 bool overrides = false;
3360 var base_member = FindBaseMember (out candidate, ref overrides);
3362 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3363 if (base_member == null) {
3364 if (candidate == null) {
3365 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3366 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3367 "object.Finalize()");
3369 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3370 GetSignatureForError (), SimpleName.GetMemberType (this));
3373 Report.SymbolRelatedToPreviousError (candidate);
3375 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3376 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3377 else if (this is PropertyBase)
3378 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3379 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3381 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3382 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3389 // Handles ambiguous overrides
3391 if (candidate != null) {
3392 Report.SymbolRelatedToPreviousError (candidate);
3393 Report.SymbolRelatedToPreviousError (base_member);
3395 // Get member definition for error reporting
3396 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3397 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3399 Report.Error (462, Location,
3400 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3401 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3404 if (!CheckOverrideAgainstBase (base_member))
3407 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3409 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3410 Report.SymbolRelatedToPreviousError (base_member);
3411 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3412 GetSignatureForError (), base_member.GetSignatureForError ());
3415 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3416 Report.SymbolRelatedToPreviousError (base_member);
3417 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3418 GetSignatureForError (), base_member.GetSignatureForError ());
3422 base_method = base_member as MethodSpec;
3426 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3427 base_member = candidate;
3429 if (base_member == null) {
3430 if ((ModFlags & Modifiers.NEW) != 0) {
3431 if (base_member == null) {
3432 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3433 GetSignatureForError ());
3437 if ((ModFlags & Modifiers.NEW) == 0) {
3438 ModFlags |= Modifiers.NEW;
3439 if (!IsCompilerGenerated) {
3440 Report.SymbolRelatedToPreviousError (base_member);
3441 if ((base_member.Kind & MemberKind.NestedMask) == 0 && !IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3442 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",
3443 GetSignatureForError (), base_member.GetSignatureForError ());
3445 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3446 GetSignatureForError (), base_member.GetSignatureForError ());
3451 if (!IsInterface && base_member.IsAbstract && !overrides && !IsStatic) {
3452 switch (base_member.Kind) {
3453 case MemberKind.Event:
3454 case MemberKind.Indexer:
3455 case MemberKind.Method:
3456 case MemberKind.Property:
3457 Report.SymbolRelatedToPreviousError (base_member);
3458 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3459 GetSignatureForError (), base_member.GetSignatureForError ());
3468 protected virtual bool CheckForDuplications ()
3470 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3474 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3475 // that have been defined.
3477 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3481 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3482 Report.SymbolRelatedToPreviousError (base_member);
3483 Report.Error (506, Location,
3484 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3485 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3489 // Now we check that the overriden method is not final
3490 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3491 Report.SymbolRelatedToPreviousError (base_member);
3492 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3493 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3497 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3498 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3499 Report.SymbolRelatedToPreviousError (base_member);
3500 if (this is PropertyBasedMember) {
3501 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3502 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3504 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3505 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3513 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3515 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3516 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3518 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3520 // It must be at least "protected"
3522 if ((thisp & Modifiers.PROTECTED) == 0) {
3527 // when overriding protected internal, the method can be declared
3528 // protected internal only within the same assembly or assembly
3529 // which has InternalsVisibleTo
3531 if ((thisp & Modifiers.INTERNAL) != 0) {
3532 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3536 // protected overriding protected internal inside same assembly
3537 // requires internal modifier as well
3539 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3546 return thisp == base_classp;
3549 public override bool Define ()
3552 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3553 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3555 flags = MethodAttributes.Public |
3556 MethodAttributes.Abstract |
3557 MethodAttributes.HideBySig |
3558 MethodAttributes.NewSlot |
3559 MethodAttributes.Virtual;
3561 Parent.PartialContainer.MethodModifiersValid (this);
3563 flags = ModifiersExtensions.MethodAttr (ModFlags);
3566 if (IsExplicitImpl) {
3567 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3568 if (InterfaceType == null)
3571 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3572 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3573 GetSignatureForError ());
3576 if (!InterfaceType.IsInterface) {
3577 Report.SymbolRelatedToPreviousError (InterfaceType);
3578 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3579 InterfaceType.GetSignatureForError ());
3581 Parent.PartialContainer.VerifyImplements (this);
3584 Modifiers allowed_explicit = Modifiers.AllowedExplicitImplFlags;
3586 allowed_explicit |= Modifiers.ASYNC;
3588 ModifiersExtensions.Check (allowed_explicit, explicit_mod_flags, 0, Location, Report);
3591 return base.Define ();
3594 protected bool DefineParameters (ParametersCompiled parameters)
3596 if (!parameters.Resolve (this))
3600 for (int i = 0; i < parameters.Count; ++i) {
3601 Parameter p = parameters [i];
3603 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3604 p.Warning_UselessOptionalParameter (Report);
3606 if (p.CheckAccessibility (this))
3609 TypeSpec t = parameters.Types [i];
3610 Report.SymbolRelatedToPreviousError (t);
3611 if (this is Indexer)
3612 Report.Error (55, Location,
3613 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3614 t.GetSignatureForError (), GetSignatureForError ());
3615 else if (this is Operator)
3616 Report.Error (57, Location,
3617 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3618 t.GetSignatureForError (), GetSignatureForError ());
3620 Report.Error (51, Location,
3621 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3622 t.GetSignatureForError (), GetSignatureForError ());
3628 protected override void DoMemberTypeDependentChecks ()
3630 base.DoMemberTypeDependentChecks ();
3632 VarianceDecl.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3635 public override void Emit()
3637 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3638 // We are more strict than csc and report this as an error because SRE does not allow emit that
3639 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3640 if (this is Constructor) {
3641 Report.Warning (824, 1, Location,
3642 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3644 Report.Warning (626, 1, Location,
3645 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3646 GetSignatureForError ());
3653 public override bool EnableOverloadChecks (MemberCore overload)
3656 // Two members can differ in their explicit interface
3657 // type parameter only
3659 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3660 if (imb != null && imb.IsExplicitImpl) {
3661 if (IsExplicitImpl) {
3662 caching_flags |= Flags.MethodOverloadsExist;
3667 return IsExplicitImpl;
3670 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3672 var base_modifiers = base_member.Modifiers;
3674 // Remove internal modifier from types which are not internally accessible
3675 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3676 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3677 base_modifiers = Modifiers.PROTECTED;
3679 Report.SymbolRelatedToPreviousError (base_member);
3680 Report.Error (507, member.Location,
3681 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3682 member.GetSignatureForError (),
3683 ModifiersExtensions.AccessibilityName (base_modifiers),
3684 base_member.GetSignatureForError ());
3687 protected void Error_StaticReturnType ()
3689 Report.Error (722, Location,
3690 "`{0}': static types cannot be used as return types",
3691 MemberType.GetSignatureForError ());
3695 /// Gets base method and its return type
3697 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3699 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3703 // The "short" name of this property / indexer / event. This is the
3704 // name without the explicit interface.
3706 public string ShortName {
3707 get { return MemberName.Name; }
3711 // Returns full metadata method name
3713 public string GetFullName (MemberName name)
3715 return GetFullName (name.Name);
3718 public string GetFullName (string name)
3720 if (!IsExplicitImpl)
3724 // When dealing with explicit members a full interface type
3725 // name is added to member name to avoid possible name conflicts
3727 // We use CSharpName which gets us full name with benefit of
3728 // replacing predefined names which saves some space and name
3731 return InterfaceType.GetSignatureForError () + "." + name;
3734 public override string GetSignatureForDocumentation ()
3737 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetSignatureForDocumentation (true) + "#" + ShortName;
3739 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3742 public override bool IsUsed
3744 get { return IsExplicitImpl || base.IsUsed; }
3747 public override void SetConstraints (List<Constraints> constraints_list)
3749 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3750 Report.Error (460, Location,
3751 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3752 GetSignatureForError ());
3755 base.SetConstraints (constraints_list);
3759 public abstract class MemberBase : MemberCore
3761 protected FullNamedExpression type_expr;
3762 protected TypeSpec member_type;
3763 public new TypeDefinition Parent;
3765 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3766 : base (parent, name, attrs)
3768 this.Parent = parent;
3769 this.type_expr = type;
3771 if (name != MemberName.Null)
3772 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3777 public TypeSpec MemberType {
3783 public FullNamedExpression TypeExpression {
3795 // Main member define entry
3797 public override bool Define ()
3799 DoMemberTypeIndependentChecks ();
3802 // Returns false only when type resolution failed
3804 if (!ResolveMemberType ())
3807 DoMemberTypeDependentChecks ();
3812 // Any type_name independent checks
3814 protected virtual void DoMemberTypeIndependentChecks ()
3816 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3817 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3818 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3819 GetSignatureForError (), Parent.GetSignatureForError ());
3824 // Any type_name dependent checks
3826 protected virtual void DoMemberTypeDependentChecks ()
3828 // verify accessibility
3829 if (!IsAccessibleAs (MemberType)) {
3830 Report.SymbolRelatedToPreviousError (MemberType);
3831 if (this is Property)
3832 Report.Error (53, Location,
3833 "Inconsistent accessibility: property type `" +
3834 MemberType.GetSignatureForError () + "' is less " +
3835 "accessible than property `" + GetSignatureForError () + "'");
3836 else if (this is Indexer)
3837 Report.Error (54, Location,
3838 "Inconsistent accessibility: indexer return type `" +
3839 MemberType.GetSignatureForError () + "' is less " +
3840 "accessible than indexer `" + GetSignatureForError () + "'");
3841 else if (this is MethodCore) {
3842 if (this is Operator)
3843 Report.Error (56, Location,
3844 "Inconsistent accessibility: return type `" +
3845 MemberType.GetSignatureForError () + "' is less " +
3846 "accessible than operator `" + GetSignatureForError () + "'");
3848 Report.Error (50, Location,
3849 "Inconsistent accessibility: return type `" +
3850 MemberType.GetSignatureForError () + "' is less " +
3851 "accessible than method `" + GetSignatureForError () + "'");
3852 } else if (this is Event) {
3853 Report.Error (7025, Location,
3854 "Inconsistent accessibility: event type `{0}' is less accessible than event `{1}'",
3855 MemberType.GetSignatureForError (), GetSignatureForError ());
3857 Report.Error (52, Location,
3858 "Inconsistent accessibility: field type `" +
3859 MemberType.GetSignatureForError () + "' is less " +
3860 "accessible than field `" + GetSignatureForError () + "'");
3865 protected void IsTypePermitted ()
3867 if (MemberType.IsSpecialRuntimeType) {
3868 if (Parent is StateMachine) {
3869 Report.Error (4012, Location,
3870 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3871 MemberType.GetSignatureForError ());
3872 } else if (Parent is HoistedStoreyClass) {
3873 Report.Error (4013, Location,
3874 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3875 MemberType.GetSignatureForError ());
3877 Report.Error (610, Location,
3878 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3883 protected virtual bool CheckBase ()
3885 CheckProtectedModifier ();
3890 public override string GetSignatureForDocumentation ()
3892 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3895 public virtual void PrepareEmit ()
3897 if (member_type != null && type_expr != null)
3898 member_type.CheckObsoleteness (this, type_expr.Location);
3901 protected virtual bool ResolveMemberType ()
3903 if (member_type != null)
3904 throw new InternalErrorException ("Multi-resolve");
3906 member_type = type_expr.ResolveAsType (this);
3907 return member_type != null;