2 // class.cs: Class and Struct handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@ximian.com)
6 // Marek Safar (marek.safar@gmail.com)
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2011 Novell, Inc
12 // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
17 using System.Collections.Generic;
18 using System.Runtime.InteropServices;
19 using System.Security;
20 using System.Security.Permissions;
22 using System.Diagnostics;
23 using Mono.CompilerServices.SymbolWriter;
26 using XmlElement = System.Object;
30 using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
31 using IKVM.Reflection;
32 using IKVM.Reflection.Emit;
34 using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
35 using System.Reflection;
36 using System.Reflection.Emit;
42 // General types container, used as a base class for all constructs which can hold types
44 public abstract class TypeContainer : MemberCore
46 public readonly MemberKind Kind;
48 protected List<TypeContainer> containers;
50 TypeDefinition main_container;
52 protected Dictionary<string, MemberCore> defined_names;
54 protected bool is_defined;
56 public int CounterAnonymousMethods { get; set; }
57 public int CounterAnonymousContainers { get; set; }
58 public int CounterSwitchTypes { get; set; }
60 protected TypeContainer (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
61 : base (parent, name, attrs)
64 defined_names = new Dictionary<string, MemberCore> ();
67 public override TypeSpec CurrentType {
73 public Dictionary<string, MemberCore> DefinedNames {
79 public TypeDefinition PartialContainer {
81 return main_container;
84 main_container = value;
88 public IList<TypeContainer> Containers {
95 // Any unattached attributes during parsing get added here. User
98 public Attributes UnattachedAttributes {
102 public void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
104 AddTypeContainerMember (c);
107 public virtual void AddPartial (TypeDefinition next_part)
110 (PartialContainer ?? this).defined_names.TryGetValue (next_part.MemberName.Basename, out mc);
112 AddPartial (next_part, mc as TypeDefinition);
115 protected void AddPartial (TypeDefinition next_part, TypeDefinition existing)
117 next_part.ModFlags |= Modifiers.PARTIAL;
119 if (existing == null) {
120 AddTypeContainer (next_part);
124 if ((existing.ModFlags & Modifiers.PARTIAL) == 0) {
125 if (existing.Kind != next_part.Kind) {
126 AddTypeContainer (next_part);
128 Report.SymbolRelatedToPreviousError (next_part);
129 Error_MissingPartialModifier (existing);
135 if (existing.Kind != next_part.Kind) {
136 Report.SymbolRelatedToPreviousError (existing);
137 Report.Error (261, next_part.Location,
138 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
139 next_part.GetSignatureForError ());
142 if ((existing.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) &&
143 ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) == 0 &&
144 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) == 0)) {
145 Report.SymbolRelatedToPreviousError (existing);
146 Report.Error (262, next_part.Location,
147 "Partial declarations of `{0}' have conflicting accessibility modifiers",
148 next_part.GetSignatureForError ());
151 var tc_names = existing.CurrentTypeParameters;
152 if (tc_names != null) {
153 for (int i = 0; i < tc_names.Count; ++i) {
154 var tp = next_part.MemberName.TypeParameters[i];
155 if (tc_names[i].MemberName.Name != tp.MemberName.Name) {
156 Report.SymbolRelatedToPreviousError (existing.Location, "");
157 Report.Error (264, next_part.Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
158 next_part.GetSignatureForError ());
162 if (tc_names[i].Variance != tp.Variance) {
163 Report.SymbolRelatedToPreviousError (existing.Location, "");
164 Report.Error (1067, next_part.Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers",
165 next_part.GetSignatureForError ());
171 if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) != 0) {
172 existing.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFIER | Modifiers.AccessibilityMask);
173 } else if ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) != 0) {
174 existing.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFIER | Modifiers.AccessibilityMask);
175 existing.ModFlags |= next_part.ModFlags;
177 existing.ModFlags |= next_part.ModFlags;
180 existing.Definition.Modifiers = existing.ModFlags;
182 if (next_part.attributes != null) {
183 if (existing.attributes == null)
184 existing.attributes = next_part.attributes;
186 existing.attributes.AddAttributes (next_part.attributes.Attrs);
189 next_part.PartialContainer = existing;
191 existing.AddPartialPart (next_part);
193 AddTypeContainerMember (next_part);
196 public virtual void AddTypeContainer (TypeContainer tc)
198 AddTypeContainerMember (tc);
200 var tparams = tc.MemberName.TypeParameters;
201 if (tparams != null && tc.PartialContainer != null) {
202 var td = (TypeDefinition) tc;
203 for (int i = 0; i < tparams.Count; ++i) {
205 if (tp.MemberName == null)
208 td.AddNameToContainer (tp, tp.Name);
213 protected virtual void AddTypeContainerMember (TypeContainer tc)
218 public virtual void CloseContainer ()
220 if (containers != null) {
221 foreach (TypeContainer tc in containers) {
222 tc.CloseContainer ();
227 public virtual void CreateMetadataName (StringBuilder sb)
229 if (Parent != null && Parent.MemberName != null)
230 Parent.CreateMetadataName (sb);
232 MemberName.CreateMetadataName (sb);
235 public virtual bool CreateContainer ()
237 if (containers != null) {
238 foreach (TypeContainer tc in containers) {
239 tc.CreateContainer ();
246 public override bool Define ()
248 if (containers != null) {
249 foreach (TypeContainer tc in containers) {
254 // Release cache used by parser only
255 if (Module.Evaluator == null) {
256 defined_names = null;
258 defined_names.Clear ();
264 public virtual void PrepareEmit ()
266 if (containers != null) {
267 foreach (var t in containers) {
270 } catch (Exception e) {
271 if (MemberName == MemberName.Null)
274 throw new InternalErrorException (t, e);
280 public virtual bool DefineContainer ()
287 DoDefineContainer ();
289 if (containers != null) {
290 foreach (TypeContainer tc in containers) {
292 tc.DefineContainer ();
293 } catch (Exception e) {
294 if (MemberName == MemberName.Null)
297 throw new InternalErrorException (tc, e);
305 public virtual void ExpandBaseInterfaces ()
307 if (containers != null) {
308 foreach (TypeContainer tc in containers) {
309 tc.ExpandBaseInterfaces ();
314 protected virtual void DefineNamespace ()
316 if (containers != null) {
317 foreach (var tc in containers) {
319 tc.DefineNamespace ();
320 } catch (Exception e) {
321 throw new InternalErrorException (tc, e);
327 protected virtual void DoDefineContainer ()
331 public virtual void EmitContainer ()
333 if (containers != null) {
334 for (int i = 0; i < containers.Count; ++i)
335 containers[i].EmitContainer ();
339 protected void Error_MissingPartialModifier (MemberCore type)
341 Report.Error (260, type.Location,
342 "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
343 type.GetSignatureForError ());
346 public override string GetSignatureForDocumentation ()
348 if (Parent != null && Parent.MemberName != null)
349 return Parent.GetSignatureForDocumentation () + "." + MemberName.GetSignatureForDocumentation ();
351 return MemberName.GetSignatureForDocumentation ();
354 public override string GetSignatureForError ()
356 if (Parent != null && Parent.MemberName != null)
357 return Parent.GetSignatureForError () + "." + MemberName.GetSignatureForError ();
359 return MemberName.GetSignatureForError ();
362 public virtual string GetSignatureForMetadata ()
364 var sb = new StringBuilder ();
365 CreateMetadataName (sb);
366 return sb.ToString ();
369 public virtual void RemoveContainer (TypeContainer cont)
371 if (containers != null)
372 containers.Remove (cont);
374 var tc = Parent == Module ? Module : this;
375 tc.defined_names.Remove (cont.MemberName.Basename);
378 public virtual void VerifyMembers ()
380 if (containers != null) {
381 foreach (TypeContainer tc in containers)
386 public override void WriteDebugSymbol (MonoSymbolFile file)
388 if (containers != null) {
389 foreach (TypeContainer tc in containers) {
390 tc.WriteDebugSymbol (file);
396 public abstract class TypeDefinition : TypeContainer, ITypeDefinition
399 // Different context is needed when resolving type container base
400 // types. Type names come from the parent scope but type parameter
401 // names from the container scope.
403 public struct BaseContext : IMemberContext
407 public BaseContext (TypeContainer tc)
412 #region IMemberContext Members
414 public CompilerContext Compiler {
415 get { return tc.Compiler; }
418 public TypeSpec CurrentType {
419 get { return tc.PartialContainer.CurrentType; }
422 public TypeParameters CurrentTypeParameters {
423 get { return tc.PartialContainer.CurrentTypeParameters; }
426 public MemberCore CurrentMemberDefinition {
430 public bool IsObsolete {
431 get { return tc.IsObsolete; }
434 public bool IsUnsafe {
435 get { return tc.IsUnsafe; }
438 public bool IsStatic {
439 get { return tc.IsStatic; }
442 public ModuleContainer Module {
443 get { return tc.Module; }
446 public string GetSignatureForError ()
448 return tc.GetSignatureForError ();
451 public ExtensionMethodCandidates LookupExtensionMethod (string name, int arity)
456 public FullNamedExpression LookupNamespaceAlias (string name)
458 return tc.Parent.LookupNamespaceAlias (name);
461 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
464 var tp = CurrentTypeParameters;
466 TypeParameter t = tp.Find (name);
468 return new TypeParameterExpr (t, loc);
472 return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc);
482 GetHashCode = 1 << 1,
483 HasStaticFieldInitializer = 1 << 2
486 readonly List<MemberCore> members;
488 // Holds a list of fields that have initializers
489 protected List<FieldInitializer> initialized_fields;
491 // Holds a list of static fields that have initializers
492 protected List<FieldInitializer> initialized_static_fields;
494 Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
496 Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
499 // Points to the first non-static field added to the container.
501 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
502 // and the first one's as good as any.
504 protected FieldBase first_nonstatic_field;
507 // This one is computed after we can distinguish interfaces
508 // from classes from the arraylist `type_bases'
510 protected TypeSpec base_type;
511 FullNamedExpression base_type_expr; // TODO: It's temporary variable
512 protected TypeSpec[] iface_exprs;
514 protected List<FullNamedExpression> type_bases;
516 // Partial parts for classes only
517 List<TypeDefinition> class_partial_parts;
519 TypeDefinition InTransit;
521 public TypeBuilder TypeBuilder;
522 GenericTypeParameterBuilder[] all_tp_builders;
524 // All recursive type parameters put together sharing same
525 // TypeParameter instances
527 TypeParameters all_type_parameters;
529 public const string DefaultIndexerName = "Item";
531 bool has_normal_indexers;
533 protected bool requires_delayed_unmanagedtype_check;
535 bool members_defined;
536 bool members_defined_ok;
537 protected bool has_static_constructor;
539 private CachedMethods cached_method;
541 protected TypeSpec spec;
542 TypeSpec current_type;
544 public int DynamicSitesCounter;
545 public int AnonymousMethodsCounter;
546 public int MethodGroupsCounter;
548 static readonly string[] attribute_targets = new [] { "type" };
549 static readonly string[] attribute_targets_primary = new [] { "type", "method" };
552 /// The pending methods that need to be implemented
553 // (interfaces or abstract methods)
555 PendingImplementation pending;
557 protected TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
558 : base (parent, name, attrs, kind)
560 PartialContainer = this;
561 members = new List<MemberCore> ();
566 public List<FullNamedExpression> BaseTypeExpressions {
572 public override TypeSpec CurrentType {
574 if (current_type == null) {
575 if (IsGenericOrParentIsGeneric) {
577 // Switch to inflated version as it's used by all expressions
579 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Types;
580 current_type = spec.MakeGenericType (this, targs);
590 public override TypeParameters CurrentTypeParameters {
592 return PartialContainer.MemberName.TypeParameters;
596 int CurrentTypeParametersStartIndex {
598 int total = all_tp_builders.Length;
599 if (CurrentTypeParameters != null) {
600 return total - CurrentTypeParameters.Count;
606 public virtual AssemblyDefinition DeclaringAssembly {
608 return Module.DeclaringAssembly;
612 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
614 return Module.DeclaringAssembly;
618 public TypeSpec Definition {
624 public bool HasMembersDefined {
626 return members_defined;
630 public bool HasInstanceConstructor {
632 return (caching_flags & Flags.HasInstanceConstructor) != 0;
635 caching_flags |= Flags.HasInstanceConstructor;
639 // Indicated whether container has StructLayout attribute set Explicit
640 public bool HasExplicitLayout {
641 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
642 set { caching_flags |= Flags.HasExplicitLayout; }
645 public bool HasOperators {
647 return (caching_flags & Flags.HasUserOperators) != 0;
650 caching_flags |= Flags.HasUserOperators;
654 public bool HasStructLayout {
655 get { return (caching_flags & Flags.HasStructLayout) != 0; }
656 set { caching_flags |= Flags.HasStructLayout; }
659 public TypeSpec[] Interfaces {
665 public bool IsGenericOrParentIsGeneric {
667 return all_type_parameters != null;
671 public bool IsTopLevel {
673 return !(Parent is TypeDefinition);
677 public bool IsPartial {
679 return (ModFlags & Modifiers.PARTIAL) != 0;
683 bool ITypeDefinition.IsTypeForwarder {
689 bool ITypeDefinition.IsCyclicTypeForwarder {
696 // Returns true for secondary partial containers
700 return PartialContainer != this;
704 public MemberCache MemberCache {
706 return spec.MemberCache;
710 public List<MemberCore> Members {
716 string ITypeDefinition.Namespace {
719 while (p.Kind != MemberKind.Namespace)
722 return p.MemberName == null ? null : p.GetSignatureForError ();
726 public ParametersCompiled PrimaryConstructorParameters { get; set; }
728 public Arguments PrimaryConstructorBaseArguments { get; set; }
730 public Location PrimaryConstructorBaseArgumentsStart { get; set; }
732 public TypeParameters TypeParametersAll {
734 return all_type_parameters;
738 public override string[] ValidAttributeTargets {
740 return PrimaryConstructorParameters != null ? attribute_targets_primary : attribute_targets;
746 public override void Accept (StructuralVisitor visitor)
748 visitor.Visit (this);
751 public void AddMember (MemberCore symbol)
753 if (symbol.MemberName.ExplicitInterface != null) {
754 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
755 Report.Error (541, symbol.Location,
756 "`{0}': explicit interface declaration can only be declared in a class or struct",
757 symbol.GetSignatureForError ());
761 AddNameToContainer (symbol, symbol.MemberName.Name);
762 members.Add (symbol);
765 public override void AddTypeContainer (TypeContainer tc)
767 AddNameToContainer (tc, tc.MemberName.Basename);
769 base.AddTypeContainer (tc);
772 protected override void AddTypeContainerMember (TypeContainer tc)
776 if (containers == null)
777 containers = new List<TypeContainer> ();
779 base.AddTypeContainerMember (tc);
783 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
785 public virtual void AddNameToContainer (MemberCore symbol, string name)
787 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
791 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
792 PartialContainer.defined_names.Add (name, symbol);
796 if (symbol.EnableOverloadChecks (mc))
799 InterfaceMemberBase im = mc as InterfaceMemberBase;
800 if (im != null && im.IsExplicitImpl)
803 Report.SymbolRelatedToPreviousError (mc);
804 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
805 Error_MissingPartialModifier (symbol);
809 if (symbol is TypeParameter) {
810 Report.Error (692, symbol.Location,
811 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
813 Report.Error (102, symbol.Location,
814 "The type `{0}' already contains a definition for `{1}'",
815 GetSignatureForError (), name);
821 public void AddConstructor (Constructor c)
823 AddConstructor (c, false);
826 public void AddConstructor (Constructor c, bool isDefault)
828 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
830 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
832 if (is_static && c.ParameterInfo.IsEmpty) {
833 PartialContainer.has_static_constructor = true;
835 PartialContainer.HasInstanceConstructor = true;
841 public bool AddField (FieldBase field)
845 if ((field.ModFlags & Modifiers.STATIC) != 0)
848 var first_field = PartialContainer.first_nonstatic_field;
849 if (first_field == null) {
850 PartialContainer.first_nonstatic_field = field;
854 if (Kind == MemberKind.Struct && first_field.Parent != field.Parent) {
855 Report.SymbolRelatedToPreviousError (first_field.Parent);
856 Report.Warning (282, 3, field.Location,
857 "struct instance field `{0}' found in different declaration from instance field `{1}'",
858 field.GetSignatureForError (), first_field.GetSignatureForError ());
864 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
866 public void AddIndexer (Indexer i)
871 public void AddOperator (Operator op)
873 PartialContainer.HasOperators = true;
877 public void AddPartialPart (TypeDefinition part)
879 if (Kind != MemberKind.Class)
882 if (class_partial_parts == null)
883 class_partial_parts = new List<TypeDefinition> ();
885 class_partial_parts.Add (part);
888 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
890 if (a.Target == AttributeTargets.Method) {
891 foreach (var m in members) {
892 var c = m as Constructor;
896 if (c.IsPrimaryConstructor) {
897 c.ApplyAttributeBuilder (a, ctor, cdata, pa);
902 throw new InternalErrorException ();
905 if (has_normal_indexers && a.Type == pa.DefaultMember) {
906 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
910 if (a.Type == pa.Required) {
911 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
915 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
918 public override AttributeTargets AttributeTargets {
920 throw new NotSupportedException ();
924 public TypeSpec BaseType {
926 return spec.BaseType;
930 protected virtual TypeAttributes TypeAttr {
932 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
936 public int TypeParametersCount {
938 return MemberName.Arity;
942 TypeParameterSpec[] ITypeDefinition.TypeParameters {
944 return PartialContainer.CurrentTypeParameters.Types;
948 public string GetAttributeDefaultMember ()
950 return indexer_name ?? DefaultIndexerName;
953 public bool IsComImport {
955 if (OptAttributes == null)
958 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
962 public void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
965 PartialContainer.RegisterFieldForInitialization (field, expression);
967 if ((field.ModFlags & Modifiers.STATIC) != 0){
968 if (initialized_static_fields == null) {
969 HasStaticFieldInitializer = true;
970 initialized_static_fields = new List<FieldInitializer> (4);
973 initialized_static_fields.Add (expression);
975 if (Kind == MemberKind.Struct) {
976 if (Compiler.Settings.Version != LanguageVersion.Experimental) {
977 Report.Error (573, expression.Location, "'{0}': Structs cannot have instance property or field initializers",
978 GetSignatureForError ());
982 if (initialized_fields == null)
983 initialized_fields = new List<FieldInitializer> (4);
985 initialized_fields.Add (expression);
989 public void ResolveFieldInitializers (BlockContext ec)
991 Debug.Assert (!IsPartialPart);
994 if (initialized_static_fields == null)
997 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
999 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
1000 for (i = 0; i < initialized_static_fields.Count; ++i) {
1001 FieldInitializer fi = initialized_static_fields [i];
1002 ExpressionStatement s = fi.ResolveStatement (ec);
1004 s = EmptyExpressionStatement.Instance;
1005 } else if (!fi.IsSideEffectFree) {
1006 has_complex_initializer = true;
1012 for (i = 0; i < initialized_static_fields.Count; ++i) {
1013 FieldInitializer fi = initialized_static_fields [i];
1015 // Need special check to not optimize code like this
1016 // static int a = b = 5;
1017 // static int b = 0;
1019 if (!has_complex_initializer && fi.IsDefaultInitializer)
1022 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1023 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
1029 if (initialized_fields == null)
1032 for (int i = 0; i < initialized_fields.Count; ++i) {
1033 FieldInitializer fi = initialized_fields [i];
1036 // Clone before resolving otherwise when field initializer is needed
1037 // in more than 1 constructor any resolve after the initial one would
1038 // only took the resolved expression which is problem for expressions
1039 // that generate extra expressions or code during Resolve phase
1041 var cloned = fi.Clone (new CloneContext ());
1043 ExpressionStatement s = fi.ResolveStatement (ec);
1045 initialized_fields [i] = new FieldInitializer (fi.Field, ErrorExpression.Instance, Location.Null);
1050 // Field is re-initialized to its default value => removed
1052 if (fi.IsDefaultInitializer && Kind != MemberKind.Struct && ec.Module.Compiler.Settings.Optimize)
1055 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1056 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
1057 initialized_fields [i] = (FieldInitializer) cloned;
1061 public override string DocComment {
1073 public PendingImplementation PendingImplementations {
1074 get { return pending; }
1077 internal override void GenerateDocComment (DocumentationBuilder builder)
1082 base.GenerateDocComment (builder);
1084 foreach (var member in members)
1085 member.GenerateDocComment (builder);
1088 public TypeSpec GetAttributeCoClass ()
1090 if (OptAttributes == null)
1093 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
1097 return a.GetCoClassAttributeValue ();
1100 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1103 if (OptAttributes != null) {
1104 a = OptAttributes.Search (pa);
1110 return a.GetAttributeUsageAttribute ();
1113 public virtual CompilationSourceFile GetCompilationSourceFile ()
1115 TypeContainer ns = Parent;
1117 var sf = ns as CompilationSourceFile;
1125 public override string GetSignatureForMetadata ()
1127 if (Parent is TypeDefinition) {
1128 return Parent.GetSignatureForMetadata () + "+" + TypeNameParser.Escape (FilterNestedName (MemberName.Basename));
1131 return base.GetSignatureForMetadata ();
1134 public virtual void SetBaseTypes (List<FullNamedExpression> baseTypes)
1136 type_bases = baseTypes;
1140 /// This function computes the Base class and also the
1141 /// list of interfaces that the class or struct @c implements.
1143 /// The return value is an array (might be null) of
1144 /// interfaces implemented (as Types).
1146 /// The @base_class argument is set to the base object or null
1147 /// if this is `System.Object'.
1149 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1152 if (type_bases == null)
1155 int count = type_bases.Count;
1156 TypeSpec[] ifaces = null;
1157 var base_context = new BaseContext (this);
1158 for (int i = 0, j = 0; i < count; i++){
1159 FullNamedExpression fne = type_bases [i];
1161 var fne_resolved = fne.ResolveAsType (base_context);
1162 if (fne_resolved == null)
1165 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1166 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1167 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1168 GetSignatureForError ());
1173 base_type = fne_resolved;
1179 ifaces = new TypeSpec [count - i];
1181 if (fne_resolved.IsInterface) {
1182 for (int ii = 0; ii < j; ++ii) {
1183 if (fne_resolved == ifaces [ii]) {
1184 Report.Error (528, Location, "`{0}' is already listed in interface list",
1185 fne_resolved.GetSignatureForError ());
1190 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1191 Report.Error (61, fne.Location,
1192 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1193 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1196 Report.SymbolRelatedToPreviousError (fne_resolved);
1197 if (Kind != MemberKind.Class) {
1198 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1199 } else if (base_class != null)
1200 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1201 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1203 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1204 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1208 ifaces [j++] = fne_resolved;
1215 // Checks that some operators come in pairs:
1221 // They are matched based on the return type and the argument types
1223 void CheckPairedOperators ()
1225 bool has_equality_or_inequality = false;
1226 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1228 for (int i = 0; i < members.Count; ++i) {
1229 var o_a = members[i] as Operator;
1233 var o_type = o_a.OperatorType;
1234 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1235 has_equality_or_inequality = true;
1237 if (found_matched.Contains (o_type))
1240 var matching_type = o_a.GetMatchingOperator ();
1241 if (matching_type == Operator.OpType.TOP) {
1245 bool pair_found = false;
1246 for (int ii = 0; ii < members.Count; ++ii) {
1247 var o_b = members[ii] as Operator;
1248 if (o_b == null || o_b.OperatorType != matching_type)
1251 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1254 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1257 found_matched.Add (matching_type);
1263 Report.Error (216, o_a.Location,
1264 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1265 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1269 if (has_equality_or_inequality) {
1271 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1272 GetSignatureForError ());
1274 if (!HasGetHashCode)
1275 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1276 GetSignatureForError ());
1280 public override void CreateMetadataName (StringBuilder sb)
1282 if (Parent.MemberName != null) {
1283 Parent.CreateMetadataName (sb);
1285 if (sb.Length != 0) {
1290 sb.Append (MemberName.Basename);
1293 bool CreateTypeBuilder ()
1296 // Sets .size to 1 for structs with no instance fields
1298 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null && !(this is StateMachine) ? 1 : 0;
1300 var parent_def = Parent as TypeDefinition;
1301 if (parent_def == null) {
1302 var sb = new StringBuilder ();
1303 CreateMetadataName (sb);
1304 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1306 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (FilterNestedName (MemberName.Basename), TypeAttr, null, type_size);
1309 if (DeclaringAssembly.Importer != null)
1310 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1312 spec.SetMetaInfo (TypeBuilder);
1313 spec.MemberCache = new MemberCache (this);
1315 TypeParameters parentAllTypeParameters = null;
1316 if (parent_def != null) {
1317 spec.DeclaringType = Parent.CurrentType;
1318 parent_def.MemberCache.AddMember (spec);
1319 parentAllTypeParameters = parent_def.all_type_parameters;
1322 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1323 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1325 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1327 if (CurrentTypeParameters != null) {
1328 CurrentTypeParameters.Create (spec, CurrentTypeParametersStartIndex, this);
1329 CurrentTypeParameters.Define (all_tp_builders);
1336 public static string FilterNestedName (string name)
1339 // SRE API does not handle namespaces and types separately but
1340 // determine that from '.' in name. That's problematic because
1341 // dot is valid character for type name. By replacing any '.'
1342 // in name we avoid any ambiguities and never emit metadata
1343 // namespace for nested types
1345 return name.Replace ('.', '_');
1348 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1351 int parent_offset = 0;
1352 if (parentAllTypeParameters != null) {
1353 if (CurrentTypeParameters == null) {
1354 all_type_parameters = parentAllTypeParameters;
1355 return parentAllTypeParameters.GetAllNames ();
1358 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1359 all_type_parameters = new TypeParameters (names.Length);
1360 all_type_parameters.Add (parentAllTypeParameters);
1362 parent_offset = all_type_parameters.Count;
1363 for (int i = 0; i < parent_offset; ++i)
1364 names[i] = all_type_parameters[i].MemberName.Name;
1367 names = new string[CurrentTypeParameters.Count];
1370 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1371 if (all_type_parameters != null)
1372 all_type_parameters.Add (MemberName.TypeParameters[i]);
1374 var name = CurrentTypeParameters[i].MemberName.Name;
1375 names[parent_offset + i] = name;
1376 for (int ii = 0; ii < parent_offset + i; ++ii) {
1377 if (names[ii] != name)
1380 var tp = CurrentTypeParameters[i];
1381 var conflict = all_type_parameters[ii];
1383 tp.WarningParentNameConflict (conflict);
1387 if (all_type_parameters == null)
1388 all_type_parameters = CurrentTypeParameters;
1394 public SourceMethodBuilder CreateMethodSymbolEntry ()
1396 if (Module.DeclaringAssembly.SymbolWriter == null || (ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1399 var source_file = GetCompilationSourceFile ();
1400 if (source_file == null)
1403 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1407 // Creates a proxy base method call inside this container for hoisted base member calls
1409 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1411 Method proxy_method;
1414 // One proxy per base method is enough
1416 if (hoisted_base_call_proxies == null) {
1417 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1418 proxy_method = null;
1420 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1423 if (proxy_method == null) {
1424 string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1426 MemberName member_name;
1427 TypeArguments targs = null;
1428 TypeSpec return_type = method.ReturnType;
1429 var local_param_types = method.Parameters.Types;
1431 if (method.IsGeneric) {
1433 // Copy all base generic method type parameters info
1435 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1436 var tparams = new TypeParameters ();
1438 targs = new TypeArguments ();
1439 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1440 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1441 var tp = hoisted_tparams[i];
1442 var local_tp = new TypeParameter (tp, null, new MemberName (tp.Name, Location), null);
1443 tparams.Add (local_tp);
1445 targs.Add (new SimpleName (tp.Name, Location));
1446 targs.Arguments[i] = local_tp.Type;
1449 member_name = new MemberName (name, tparams, Location);
1452 // Mutate any method type parameters from original
1453 // to newly created hoisted version
1455 var mutator = new TypeParameterMutator (hoisted_tparams, tparams);
1456 return_type = mutator.Mutate (return_type);
1457 local_param_types = mutator.Mutate (local_param_types);
1459 member_name = new MemberName (name);
1462 var base_parameters = new Parameter[method.Parameters.Count];
1463 for (int i = 0; i < base_parameters.Length; ++i) {
1464 var base_param = method.Parameters.FixedParameters[i];
1465 base_parameters[i] = new Parameter (new TypeExpression (local_param_types [i], Location),
1466 base_param.Name, base_param.ModFlags, null, Location);
1467 base_parameters[i].Resolve (this, i);
1470 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
1471 if (method.Parameters.HasArglist) {
1472 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1473 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1476 // Compiler generated proxy
1477 proxy_method = new Method (this, new TypeExpression (return_type, Location),
1478 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1479 member_name, cloned_params, null);
1481 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1482 IsCompilerGenerated = true
1485 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1486 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1488 mg.SetTypeArguments (rc, targs);
1490 // Get all the method parameters and pass them as arguments
1491 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1492 Statement statement;
1493 if (method.ReturnType.Kind == MemberKind.Void)
1494 statement = new StatementExpression (real_base_call);
1496 statement = new Return (real_base_call, Location);
1498 block.AddStatement (statement);
1499 proxy_method.Block = block;
1501 members.Add (proxy_method);
1502 proxy_method.Define ();
1503 proxy_method.PrepareEmit ();
1505 hoisted_base_call_proxies.Add (method, proxy_method);
1508 return proxy_method.Spec;
1511 protected bool DefineBaseTypes ()
1513 if (IsPartialPart && Kind == MemberKind.Class)
1516 return DoDefineBaseType ();
1519 bool DoDefineBaseType ()
1521 iface_exprs = ResolveBaseTypes (out base_type_expr);
1524 if (IsPartialPart) {
1525 set_base_type = false;
1527 if (base_type_expr != null) {
1528 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1529 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1530 Report.Error (263, Location,
1531 "Partial declarations of `{0}' must not specify different base classes",
1532 GetSignatureForError ());
1534 PartialContainer.base_type_expr = base_type_expr;
1535 PartialContainer.base_type = base_type;
1536 set_base_type = true;
1540 if (iface_exprs != null) {
1541 if (PartialContainer.iface_exprs == null)
1542 PartialContainer.iface_exprs = iface_exprs;
1544 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1545 foreach (var iface_partial in iface_exprs) {
1546 if (ifaces.Contains (iface_partial))
1549 ifaces.Add (iface_partial);
1552 PartialContainer.iface_exprs = ifaces.ToArray ();
1556 PartialContainer.members.AddRange (members);
1557 if (containers != null) {
1558 if (PartialContainer.containers == null)
1559 PartialContainer.containers = new List<TypeContainer> ();
1561 PartialContainer.containers.AddRange (containers);
1564 if (PrimaryConstructorParameters != null) {
1565 if (PartialContainer.PrimaryConstructorParameters != null) {
1566 Report.Error (8036, Location, "Only one part of a partial type can declare primary constructor parameters");
1568 PartialContainer.PrimaryConstructorParameters = PrimaryConstructorParameters;
1572 members_defined = members_defined_ok = true;
1573 caching_flags |= Flags.CloseTypeCreated;
1575 set_base_type = true;
1578 var cycle = CheckRecursiveDefinition (this);
1579 if (cycle != null) {
1580 Report.SymbolRelatedToPreviousError (cycle);
1581 if (this is Interface) {
1582 Report.Error (529, Location,
1583 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1584 GetSignatureForError (), cycle.GetSignatureForError ());
1587 PartialContainer.iface_exprs = null;
1589 Report.Error (146, Location,
1590 "Circular base class dependency involving `{0}' and `{1}'",
1591 GetSignatureForError (), cycle.GetSignatureForError ());
1594 PartialContainer.base_type = null;
1598 if (iface_exprs != null) {
1599 if (!PrimaryConstructorBaseArgumentsStart.IsNull) {
1600 Report.Error (8049, PrimaryConstructorBaseArgumentsStart, "Implemented interfaces cannot have arguments");
1603 foreach (var iface_type in iface_exprs) {
1604 // Prevents a crash, the interface might not have been resolved: 442144
1605 if (iface_type == null)
1608 if (!spec.AddInterfaceDefined (iface_type))
1611 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1615 if (Kind == MemberKind.Interface) {
1616 spec.BaseType = Compiler.BuiltinTypes.Object;
1620 if (set_base_type) {
1625 // Base type of partial container has to be resolved before we
1626 // resolve any nested types of the container. We need to know
1627 // partial parts because the base type can be specified in file
1628 // defined after current container
1630 if (class_partial_parts != null) {
1631 foreach (var pp in class_partial_parts) {
1632 if (pp.PrimaryConstructorBaseArguments != null)
1633 PrimaryConstructorBaseArguments = pp.PrimaryConstructorBaseArguments;
1635 pp.DoDefineBaseType ();
1645 if (base_type == null) {
1646 TypeBuilder.SetParent (null);
1650 if (spec.BaseType == base_type)
1653 spec.BaseType = base_type;
1656 spec.UpdateInflatedInstancesBaseType ();
1658 // Set base type after type creation
1659 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1662 public override void ExpandBaseInterfaces ()
1665 DoExpandBaseInterfaces ();
1667 base.ExpandBaseInterfaces ();
1670 public void DoExpandBaseInterfaces ()
1672 if ((caching_flags & Flags.InterfacesExpanded) != 0)
1675 caching_flags |= Flags.InterfacesExpanded;
1678 // Expand base interfaces. It cannot be done earlier because all partial
1679 // interface parts need to be defined before the type they are used from
1681 if (iface_exprs != null) {
1682 foreach (var iface in iface_exprs) {
1686 var td = iface.MemberDefinition as TypeDefinition;
1688 td.DoExpandBaseInterfaces ();
1690 if (iface.Interfaces == null)
1693 foreach (var biface in iface.Interfaces) {
1694 if (spec.AddInterfaceDefined (biface)) {
1695 TypeBuilder.AddInterfaceImplementation (biface.GetMetaInfo ());
1702 // Include all base type interfaces too, see ImportTypeBase for details
1704 if (base_type != null) {
1705 var td = base_type.MemberDefinition as TypeDefinition;
1707 td.DoExpandBaseInterfaces ();
1710 // Simply use base interfaces only, they are all expanded which makes
1711 // it easy to handle generic type argument propagation with single
1714 // interface IA<T> : IB<T>
1715 // interface IB<U> : IC<U>
1718 if (base_type.Interfaces != null) {
1719 foreach (var iface in base_type.Interfaces) {
1720 spec.AddInterfaceDefined (iface);
1726 public override void PrepareEmit ()
1728 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1731 foreach (var member in members) {
1732 var pbm = member as MemberBase;
1737 base.PrepareEmit ();
1741 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1743 public override bool CreateContainer ()
1745 if (TypeBuilder != null)
1751 if (IsPartialPart) {
1752 spec = PartialContainer.spec;
1753 TypeBuilder = PartialContainer.TypeBuilder;
1754 all_tp_builders = PartialContainer.all_tp_builders;
1755 all_type_parameters = PartialContainer.all_type_parameters;
1757 if (!CreateTypeBuilder ()) {
1763 return base.CreateContainer ();
1766 protected override void DoDefineContainer ()
1770 DoResolveTypeParameters ();
1774 // Replaces normal spec with predefined one when compiling corlib
1775 // and this type container defines predefined type
1777 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1779 // When compiling build-in types we start with two
1780 // version of same type. One is of BuiltinTypeSpec and
1781 // second one is ordinary TypeSpec. The unification
1782 // happens at later stage when we know which type
1783 // really matches the builtin type signature. However
1784 // that means TypeSpec create during CreateType of this
1785 // type has to be replaced with builtin one
1787 spec.SetMetaInfo (TypeBuilder);
1788 spec.MemberCache = this.spec.MemberCache;
1789 spec.DeclaringType = this.spec.DeclaringType;
1792 current_type = null;
1793 if (class_partial_parts != null) {
1794 foreach (var part in class_partial_parts)
1799 public override void RemoveContainer (TypeContainer cont)
1801 base.RemoveContainer (cont);
1802 Members.Remove (cont);
1803 Cache.Remove (cont.MemberName.Basename);
1806 protected virtual bool DoResolveTypeParameters ()
1808 var tparams = MemberName.TypeParameters;
1809 if (tparams == null)
1812 var base_context = new BaseContext (this);
1813 for (int i = 0; i < tparams.Count; ++i) {
1814 var tp = tparams[i];
1816 if (!tp.ResolveConstraints (base_context)) {
1821 if (IsPartialPart) {
1822 var pc_tp = PartialContainer.CurrentTypeParameters [i];
1824 tp.Create (spec, this);
1827 if (tp.OptAttributes != null) {
1828 if (pc_tp.OptAttributes == null)
1829 pc_tp.OptAttributes = tp.OptAttributes;
1831 pc_tp.OptAttributes.Attrs.AddRange (tp.OptAttributes.Attrs);
1836 if (IsPartialPart) {
1837 PartialContainer.CurrentTypeParameters.UpdateConstraints (this);
1843 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1845 if (InTransit != null)
1850 if (base_type != null) {
1851 var ptc = base_type.MemberDefinition as TypeDefinition;
1852 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1856 if (iface_exprs != null) {
1857 foreach (var iface in iface_exprs) {
1858 // the interface might not have been resolved, prevents a crash, see #442144
1861 var ptc = iface.MemberDefinition as Interface;
1862 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1867 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1875 /// Populates our TypeBuilder with fields and methods
1877 public sealed override bool Define ()
1879 if (members_defined)
1880 return members_defined_ok;
1882 members_defined_ok = DoDefineMembers ();
1883 members_defined = true;
1887 return members_defined_ok;
1890 protected virtual bool DoDefineMembers ()
1892 Debug.Assert (!IsPartialPart);
1894 if (iface_exprs != null) {
1895 foreach (var iface_type in iface_exprs) {
1896 if (iface_type == null)
1899 // Ensure the base is always setup
1900 var compiled_iface = iface_type.MemberDefinition as Interface;
1901 if (compiled_iface != null)
1902 compiled_iface.Define ();
1904 iface_type.CheckObsoleteness (this, Location);
1906 if (iface_type.Arity > 0) {
1907 // TODO: passing `this' is wrong, should be base type iface instead
1908 VarianceDecl.CheckTypeVariance (iface_type, Variance.Covariant, this);
1910 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1911 Report.Error (1966, Location,
1912 "`{0}': cannot implement a dynamic interface `{1}'",
1913 GetSignatureForError (), iface_type.GetSignatureForError ());
1918 if (iface_type.IsGenericOrParentIsGeneric) {
1919 foreach (var prev_iface in iface_exprs) {
1920 if (prev_iface == iface_type || prev_iface == null)
1923 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1926 Report.Error (695, Location,
1927 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1928 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1933 if (Kind == MemberKind.Interface) {
1934 foreach (var iface in spec.Interfaces) {
1935 MemberCache.AddInterface (iface);
1940 if (base_type != null) {
1942 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1944 if (base_type_expr != null) {
1945 base_type.CheckObsoleteness (this, base_type_expr.Location);
1947 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1948 Report.Error (698, base_type_expr.Location,
1949 "A generic type cannot derive from `{0}' because it is an attribute class",
1950 base_type.GetSignatureForError ());
1954 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1955 if (baseContainer != null) {
1956 baseContainer.Define ();
1959 // It can trigger define of this type (for generic types only)
1961 if (HasMembersDefined)
1966 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1967 pending = PendingImplementation.GetPendingImplementations (this);
1970 var count = members.Count;
1971 for (int i = 0; i < count; ++i) {
1972 var mc = members[i] as InterfaceMemberBase;
1973 if (mc == null || !mc.IsExplicitImpl)
1978 } catch (Exception e) {
1979 throw new InternalErrorException (mc, e);
1983 for (int i = 0; i < count; ++i) {
1984 var mc = members[i] as InterfaceMemberBase;
1985 if (mc != null && mc.IsExplicitImpl)
1988 if (members[i] is TypeContainer)
1992 members[i].Define ();
1993 } catch (Exception e) {
1994 throw new InternalErrorException (members[i], e);
1999 CheckPairedOperators ();
2002 if (requires_delayed_unmanagedtype_check) {
2003 requires_delayed_unmanagedtype_check = false;
2004 foreach (var member in members) {
2005 var f = member as Field;
2006 if (f != null && f.MemberType != null && f.MemberType.IsPointer)
2007 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
2011 ComputeIndexerName();
2013 if (HasEquals && !HasGetHashCode) {
2014 Report.Warning (659, 3, Location,
2015 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
2018 if (Kind == MemberKind.Interface && iface_exprs != null) {
2019 MemberCache.RemoveHiddenMembers (spec);
2025 void ComputeIndexerName ()
2027 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
2028 if (indexers == null)
2031 string class_indexer_name = null;
2034 // Check normal indexers for consistent name, explicit interface implementation
2035 // indexers are ignored
2037 foreach (var indexer in indexers) {
2039 // FindMembers can return unfiltered full hierarchy names
2041 if (indexer.DeclaringType != spec)
2044 has_normal_indexers = true;
2046 if (class_indexer_name == null) {
2047 indexer_name = class_indexer_name = indexer.Name;
2051 if (indexer.Name != class_indexer_name)
2052 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
2053 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
2057 void EmitIndexerName ()
2059 if (!has_normal_indexers)
2062 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
2066 var encoder = new AttributeEncoder ();
2067 encoder.Encode (GetAttributeDefaultMember ());
2068 encoder.EncodeEmptyNamedArguments ();
2070 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2073 public override void VerifyMembers ()
2076 // Check for internal or private fields that were never assigned
2078 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
2079 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
2080 foreach (var member in members) {
2081 if (member is Event) {
2083 // An event can be assigned from same class only, report
2084 // this warning for all accessibility modes
2086 if (!member.IsUsed && !PartialContainer.HasStructLayout)
2087 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
2092 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
2093 if (is_type_exposed)
2096 member.SetIsUsed ();
2099 var f = member as Field;
2103 if (!member.IsUsed) {
2104 if (!PartialContainer.HasStructLayout) {
2105 if ((member.caching_flags & Flags.IsAssigned) == 0) {
2106 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
2108 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
2109 member.GetSignatureForError ());
2116 if ((f.caching_flags & Flags.IsAssigned) != 0)
2120 // Only report 649 on level 4
2122 if (Compiler.Settings.WarningLevel < 4)
2126 // Don't be pedantic when type requires specific layout
2128 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2131 Constant c = New.Constantify (f.MemberType, f.Location);
2134 value = c.GetValueAsLiteral ();
2135 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
2142 value = " `" + value + "'";
2144 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
2145 f.GetSignatureForError (), value);
2149 base.VerifyMembers ();
2152 public override void Emit ()
2154 if (OptAttributes != null)
2155 OptAttributes.Emit ();
2157 if (!IsCompilerGenerated) {
2159 MemberSpec candidate;
2160 bool overrides = false;
2161 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
2162 if (conflict_symbol == null && candidate == null) {
2163 if ((ModFlags & Modifiers.NEW) != 0)
2164 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
2165 GetSignatureForError ());
2167 if ((ModFlags & Modifiers.NEW) == 0) {
2168 if (candidate == null)
2169 candidate = conflict_symbol;
2171 Report.SymbolRelatedToPreviousError (candidate);
2172 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
2173 GetSignatureForError (), candidate.GetSignatureForError ());
2178 // Run constraints check on all possible generic types
2179 if (base_type != null && base_type_expr != null) {
2180 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
2183 if (iface_exprs != null) {
2184 foreach (var iface_type in iface_exprs) {
2185 if (iface_type == null)
2188 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2193 if (all_tp_builders != null) {
2194 int current_starts_index = CurrentTypeParametersStartIndex;
2195 for (int i = 0; i < all_tp_builders.Length; i++) {
2196 if (i < current_starts_index) {
2197 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2199 var tp = CurrentTypeParameters [i - current_starts_index];
2200 tp.CheckGenericConstraints (!IsObsolete);
2206 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2207 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2210 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2211 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2216 for (int i = 0; i < members.Count; i++) {
2218 if ((m.caching_flags & Flags.CloseTypeCreated) != 0)
2225 CheckAttributeClsCompliance ();
2227 if (pending != null)
2228 pending.VerifyPendingMethods ();
2232 void CheckAttributeClsCompliance ()
2234 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2237 foreach (var m in members) {
2238 var c = m as Constructor;
2242 if (c.HasCompliantArgs)
2246 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2249 public sealed override void EmitContainer ()
2251 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2257 public override void CloseContainer ()
2259 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2262 // Close base type container first to avoid TypeLoadException
2263 if (spec.BaseType != null) {
2264 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2265 if (btype != null) {
2266 btype.CloseContainer ();
2268 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2274 caching_flags |= Flags.CloseTypeCreated;
2275 TypeBuilder.CreateType ();
2276 } catch (TypeLoadException) {
2278 // This is fine, the code still created the type
2280 } catch (Exception e) {
2281 throw new InternalErrorException (this, e);
2284 base.CloseContainer ();
2287 initialized_fields = null;
2288 initialized_static_fields = null;
2290 OptAttributes = null;
2294 // Performs the validation on a Method's modifiers (properties have
2295 // the same properties).
2297 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2299 public bool MethodModifiersValid (MemberCore mc)
2301 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2302 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2304 var flags = mc.ModFlags;
2307 // At most one of static, virtual or override
2309 if ((flags & Modifiers.STATIC) != 0){
2310 if ((flags & vao) != 0){
2311 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2312 mc.GetSignatureForError ());
2317 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2318 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2319 mc.GetSignatureForError ());
2324 // If the declaration includes the abstract modifier, then the
2325 // declaration does not include static, virtual or extern
2327 if ((flags & Modifiers.ABSTRACT) != 0){
2328 if ((flags & Modifiers.EXTERN) != 0){
2330 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2334 if ((flags & Modifiers.SEALED) != 0) {
2335 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2339 if ((flags & Modifiers.VIRTUAL) != 0){
2340 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2344 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2345 Report.SymbolRelatedToPreviousError (this);
2346 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2347 mc.GetSignatureForError (), GetSignatureForError ());
2352 if ((flags & Modifiers.PRIVATE) != 0){
2353 if ((flags & vao) != 0){
2354 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2359 if ((flags & Modifiers.SEALED) != 0){
2360 if ((flags & Modifiers.OVERRIDE) == 0){
2361 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2369 protected override bool VerifyClsCompliance ()
2371 if (!base.VerifyClsCompliance ())
2374 // Check all container names for user classes
2375 if (Kind != MemberKind.Delegate)
2376 MemberCache.VerifyClsCompliance (Definition, Report);
2378 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2379 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2380 GetSignatureForError (), BaseType.GetSignatureForError ());
2386 /// Performs checks for an explicit interface implementation. First it
2387 /// checks whether the `interface_type' is a base inteface implementation.
2388 /// Then it checks whether `name' exists in the interface type.
2390 public bool VerifyImplements (InterfaceMemberBase mb)
2392 var ifaces = PartialContainer.Interfaces;
2393 if (ifaces != null) {
2394 foreach (TypeSpec t in ifaces){
2395 if (t == mb.InterfaceType)
2398 var expanded_base = t.Interfaces;
2399 if (expanded_base == null)
2402 foreach (var bt in expanded_base) {
2403 if (bt == mb.InterfaceType)
2409 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2410 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2411 mb.GetSignatureForError (), mb.InterfaceType.GetSignatureForError ());
2416 // Used for visiblity checks to tests whether this definition shares
2417 // base type baseType, it does member-definition search
2419 public bool IsBaseTypeDefinition (TypeSpec baseType)
2421 // RootContext check
2422 if (TypeBuilder == null)
2427 if (type.MemberDefinition == baseType.MemberDefinition)
2430 type = type.BaseType;
2431 } while (type != null);
2436 public override bool IsClsComplianceRequired ()
2439 return PartialContainer.IsClsComplianceRequired ();
2441 return base.IsClsComplianceRequired ();
2444 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2446 return Module.DeclaringAssembly == assembly;
2449 public virtual bool IsUnmanagedType ()
2454 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2456 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2460 // Public function used to locate types.
2462 // Returns: Type or null if they type can not be found.
2464 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2466 FullNamedExpression e;
2467 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2473 var tp = CurrentTypeParameters;
2475 TypeParameter tparam = tp.Find (name);
2477 e = new TypeParameterExpr (tparam, Location.Null);
2482 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2484 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2485 e = new TypeExpression (t, Location.Null);
2487 var errors = Compiler.Report.Errors;
2488 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2490 // TODO: LookupNamespaceOrType does more than just lookup. The result
2491 // cannot be cached or the error reporting won't happen
2492 if (errors != Compiler.Report.Errors)
2497 // TODO MemberCache: How to cache arity stuff ?
2498 if (arity == 0 && mode == LookupMode.Normal)
2504 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2506 // Has any nested type
2507 // Does not work, because base type can have
2508 //if (PartialContainer.Types == null)
2511 var container = PartialContainer.CurrentType;
2512 return MemberCache.FindNestedType (container, name, arity);
2515 public void Mark_HasEquals ()
2517 cached_method |= CachedMethods.Equals;
2520 public void Mark_HasGetHashCode ()
2522 cached_method |= CachedMethods.GetHashCode;
2525 public override void WriteDebugSymbol (MonoSymbolFile file)
2530 foreach (var m in members) {
2531 m.WriteDebugSymbol (file);
2536 /// Method container contains Equals method
2538 public bool HasEquals {
2540 return (cached_method & CachedMethods.Equals) != 0;
2545 /// Method container contains GetHashCode method
2547 public bool HasGetHashCode {
2549 return (cached_method & CachedMethods.GetHashCode) != 0;
2553 public bool HasStaticFieldInitializer {
2555 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2559 cached_method |= CachedMethods.HasStaticFieldInitializer;
2561 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2565 public override string DocCommentHeader {
2566 get { return "T:"; }
2570 public abstract class ClassOrStruct : TypeDefinition
2572 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2574 SecurityType declarative_security;
2575 protected Constructor generated_primary_constructor;
2577 protected ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2578 : base (parent, name, attrs, kind)
2582 public ToplevelBlock PrimaryConstructorBlock { get; set; }
2584 protected override TypeAttributes TypeAttr {
2586 TypeAttributes ta = base.TypeAttr;
2587 if (!has_static_constructor)
2588 ta |= TypeAttributes.BeforeFieldInit;
2590 if (Kind == MemberKind.Class) {
2591 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2593 ta |= StaticClassAttribute;
2595 ta |= TypeAttributes.SequentialLayout;
2602 public override void AddNameToContainer (MemberCore symbol, string name)
2604 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2605 if (symbol is TypeParameter) {
2606 Report.Error (694, symbol.Location,
2607 "Type parameter `{0}' has same name as containing type, or method",
2608 symbol.GetSignatureForError ());
2612 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2613 if (imb == null || !imb.IsExplicitImpl) {
2614 Report.SymbolRelatedToPreviousError (this);
2615 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2616 symbol.GetSignatureForError ());
2621 base.AddNameToContainer (symbol, name);
2624 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2626 if (a.IsValidSecurityAttribute ()) {
2627 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2631 if (a.Type == pa.StructLayout) {
2632 PartialContainer.HasStructLayout = true;
2633 if (a.IsExplicitLayoutKind ())
2634 PartialContainer.HasExplicitLayout = true;
2637 if (a.Type == pa.Dynamic) {
2638 a.Error_MisusedDynamicAttribute ();
2642 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2646 /// Defines the default constructors
2648 protected virtual Constructor DefineDefaultConstructor (bool is_static)
2650 // The default instance constructor is public
2651 // If the class is abstract, the default constructor is protected
2652 // The default static constructor is private
2655 ParametersCompiled parameters = null;
2657 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2658 parameters = ParametersCompiled.EmptyReadOnlyParameters;
2660 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2661 parameters = PrimaryConstructorParameters ?? ParametersCompiled.EmptyReadOnlyParameters;
2664 var c = new Constructor (this, MemberName.Name, mods, null, parameters, Location);
2665 if (Kind == MemberKind.Class)
2666 c.Initializer = new GeneratedBaseInitializer (Location, PrimaryConstructorBaseArguments);
2668 if (PrimaryConstructorParameters != null && !is_static) {
2669 c.IsPrimaryConstructor = true;
2670 c.caching_flags |= Flags.MethodOverloadsExist;
2673 AddConstructor (c, true);
2674 if (PrimaryConstructorBlock == null) {
2675 c.Block = new ToplevelBlock (Compiler, parameters, Location) {
2676 IsCompilerGenerated = true
2679 c.Block = PrimaryConstructorBlock;
2685 protected override bool DoDefineMembers ()
2687 CheckProtectedModifier ();
2689 if (PrimaryConstructorParameters != null) {
2691 foreach (Parameter p in PrimaryConstructorParameters.FixedParameters) {
2692 if (p.Name == MemberName.Name) {
2693 Report.Error (8039, p.Location, "Primary constructor of type `{0}' has parameter of same name as containing type",
2694 GetSignatureForError ());
2697 if (CurrentTypeParameters != null) {
2698 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
2699 var tp = CurrentTypeParameters [i];
2700 if (p.Name == tp.Name) {
2701 Report.Error (8038, p.Location, "Primary constructor of type `{0}' has parameter of same name as type parameter `{1}'",
2702 GetSignatureForError (), p.GetSignatureForError ());
2709 base.DoDefineMembers ();
2714 public override void Emit ()
2716 if (!has_static_constructor && HasStaticFieldInitializer) {
2717 var c = DefineDefaultConstructor (true);
2723 if (declarative_security != null) {
2724 foreach (var de in declarative_security) {
2726 TypeBuilder.__AddDeclarativeSecurity (de);
2728 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2736 public sealed class Class : ClassOrStruct
2738 const Modifiers AllowedModifiers =
2741 Modifiers.PROTECTED |
2742 Modifiers.INTERNAL |
2744 Modifiers.ABSTRACT |
2749 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2750 : base (parent, name, attrs, MemberKind.Class)
2752 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2753 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2754 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2757 public override void Accept (StructuralVisitor visitor)
2759 visitor.Visit (this);
2762 public override void SetBaseTypes (List<FullNamedExpression> baseTypes)
2764 var pmn = MemberName;
2765 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2766 Report.Error (537, Location,
2767 "The class System.Object cannot have a base class or implement an interface.");
2769 base.SetBaseTypes (baseTypes);
2772 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2774 if (a.Type == pa.AttributeUsage) {
2775 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2776 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2780 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2781 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2785 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2786 a.Error_MissingGuidAttribute ();
2790 if (a.Type == pa.Extension) {
2791 a.Error_MisusedExtensionAttribute ();
2795 if (a.Type.IsConditionallyExcluded (this))
2798 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2801 public override AttributeTargets AttributeTargets {
2803 return AttributeTargets.Class;
2807 protected override bool DoDefineMembers ()
2809 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2810 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2813 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2814 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2818 if (PrimaryConstructorParameters != null) {
2819 Report.Error (-800, Location, "`{0}': Static classes cannot have primary constructor", GetSignatureForError ());
2820 PrimaryConstructorParameters = null;
2823 foreach (var m in Members) {
2824 if (m is Operator) {
2825 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2829 if (m is Destructor) {
2830 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2835 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2839 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2842 if (m is Constructor) {
2843 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2847 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2850 if (!PartialContainer.HasInstanceConstructor || PrimaryConstructorParameters != null)
2851 generated_primary_constructor = DefineDefaultConstructor (false);
2854 return base.DoDefineMembers ();
2857 public override void Emit ()
2861 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2862 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2864 if (base_type != null && base_type.HasDynamicElement) {
2865 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2869 public override void GetCompletionStartingWith (string prefix, List<string> results)
2871 base.GetCompletionStartingWith (prefix, results);
2874 while (bt != null) {
2875 results.AddRange (MemberCache.GetCompletitionMembers (this, bt, prefix).Where (l => l.IsStatic).Select (l => l.Name));
2880 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2882 var ifaces = base.ResolveBaseTypes (out base_class);
2884 if (base_class == null) {
2885 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2886 base_type = Compiler.BuiltinTypes.Object;
2888 if (base_type.IsGenericParameter){
2889 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2890 GetSignatureForError (), base_type.GetSignatureForError ());
2891 } else if (base_type.IsStatic) {
2892 Report.SymbolRelatedToPreviousError (base_type);
2893 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2894 GetSignatureForError (), base_type.GetSignatureForError ());
2895 } else if (base_type.IsSealed) {
2896 Report.SymbolRelatedToPreviousError (base_type);
2897 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2898 GetSignatureForError (), base_type.GetSignatureForError ());
2899 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2900 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2901 GetSignatureForError (), base_type.GetSignatureForError ());
2904 switch (base_type.BuiltinType) {
2905 case BuiltinTypeSpec.Type.Enum:
2906 case BuiltinTypeSpec.Type.ValueType:
2907 case BuiltinTypeSpec.Type.MulticastDelegate:
2908 case BuiltinTypeSpec.Type.Delegate:
2909 case BuiltinTypeSpec.Type.Array:
2910 if (!(spec is BuiltinTypeSpec)) {
2911 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2912 GetSignatureForError (), base_type.GetSignatureForError ());
2914 base_type = Compiler.BuiltinTypes.Object;
2919 if (!IsAccessibleAs (base_type)) {
2920 Report.SymbolRelatedToPreviousError (base_type);
2921 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2922 base_type.GetSignatureForError (), GetSignatureForError ());
2926 if (PartialContainer.IsStatic && ifaces != null) {
2927 foreach (var t in ifaces)
2928 Report.SymbolRelatedToPreviousError (t);
2929 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2935 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2936 /// Valid only for attribute classes.
2937 public override string[] ConditionalConditions ()
2939 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2942 caching_flags &= ~Flags.Excluded_Undetected;
2944 if (OptAttributes == null)
2947 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2951 string[] conditions = new string[attrs.Length];
2952 for (int i = 0; i < conditions.Length; ++i)
2953 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2955 caching_flags |= Flags.Excluded;
2960 public sealed class Struct : ClassOrStruct
2962 bool is_unmanaged, has_unmanaged_check_done;
2966 // Modifiers allowed in a struct declaration
2968 const Modifiers AllowedModifiers =
2971 Modifiers.PROTECTED |
2972 Modifiers.INTERNAL |
2976 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2977 : base (parent, name, attrs, MemberKind.Struct)
2979 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2980 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2981 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2984 public override AttributeTargets AttributeTargets {
2986 return AttributeTargets.Struct;
2990 public override void Accept (StructuralVisitor visitor)
2992 visitor.Visit (this);
2995 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2997 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3000 // When struct constains fixed fixed and struct layout has explicitly
3001 // set CharSet, its value has to be propagated to compiler generated
3004 if (a.Type == pa.StructLayout) {
3005 var value = a.GetNamedValue ("CharSet");
3009 for (int i = 0; i < Members.Count; ++i) {
3010 FixedField ff = Members [i] as FixedField;
3014 ff.CharSetValue = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
3019 bool CheckStructCycles ()
3025 foreach (var member in Members) {
3026 var field = member as Field;
3030 TypeSpec ftype = field.Spec.MemberType;
3031 if (!ftype.IsStruct)
3034 if (ftype is BuiltinTypeSpec)
3037 foreach (var targ in ftype.TypeArguments) {
3038 if (!CheckFieldTypeCycle (targ)) {
3039 Report.Error (523, field.Location,
3040 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3041 field.GetSignatureForError (), ftype.GetSignatureForError ());
3047 // Static fields of exactly same type are allowed
3049 if (field.IsStatic && ftype == CurrentType)
3052 if (!CheckFieldTypeCycle (ftype)) {
3053 Report.Error (523, field.Location,
3054 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3055 field.GetSignatureForError (), ftype.GetSignatureForError ());
3064 static bool CheckFieldTypeCycle (TypeSpec ts)
3066 var fts = ts.MemberDefinition as Struct;
3070 return fts.CheckStructCycles ();
3073 protected override bool DoDefineMembers ()
3075 var res = base.DoDefineMembers ();
3077 if (PrimaryConstructorParameters != null || (initialized_fields != null && !HasUserDefaultConstructor ())) {
3078 generated_primary_constructor = DefineDefaultConstructor (false);
3079 generated_primary_constructor.Define ();
3085 public override void Emit ()
3087 CheckStructCycles ();
3092 bool HasUserDefaultConstructor ()
3094 foreach (var m in PartialContainer.Members) {
3095 var c = m as Constructor;
3099 if (!c.IsStatic && c.ParameterInfo.IsEmpty)
3106 public override bool IsUnmanagedType ()
3108 if (has_unmanaged_check_done)
3109 return is_unmanaged;
3111 if (requires_delayed_unmanagedtype_check)
3114 var parent_def = Parent.PartialContainer;
3115 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
3116 has_unmanaged_check_done = true;
3120 if (first_nonstatic_field != null) {
3121 requires_delayed_unmanagedtype_check = true;
3123 foreach (var member in Members) {
3124 var f = member as Field;
3131 // It can happen when recursive unmanaged types are defined
3132 // struct S { S* s; }
3133 TypeSpec mt = f.MemberType;
3141 has_unmanaged_check_done = true;
3145 has_unmanaged_check_done = true;
3148 is_unmanaged = true;
3152 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
3154 var ifaces = base.ResolveBaseTypes (out base_class);
3155 base_type = Compiler.BuiltinTypes.ValueType;
3163 public sealed class Interface : TypeDefinition {
3166 /// Modifiers allowed in a class declaration
3168 const Modifiers AllowedModifiers =
3171 Modifiers.PROTECTED |
3172 Modifiers.INTERNAL |
3176 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
3177 : base (parent, name, attrs, MemberKind.Interface)
3179 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3181 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
3182 spec = new TypeSpec (Kind, null, this, null, ModFlags);
3187 public override AttributeTargets AttributeTargets {
3189 return AttributeTargets.Interface;
3193 protected override TypeAttributes TypeAttr {
3195 const TypeAttributes DefaultTypeAttributes =
3196 TypeAttributes.AutoLayout |
3197 TypeAttributes.Abstract |
3198 TypeAttributes.Interface;
3200 return base.TypeAttr | DefaultTypeAttributes;
3206 public override void Accept (StructuralVisitor visitor)
3208 visitor.Visit (this);
3211 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3213 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3214 a.Error_MissingGuidAttribute ();
3218 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3221 protected override bool VerifyClsCompliance ()
3223 if (!base.VerifyClsCompliance ())
3226 if (iface_exprs != null) {
3227 foreach (var iface in iface_exprs) {
3228 if (iface.IsCLSCompliant ())
3231 Report.SymbolRelatedToPreviousError (iface);
3232 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3233 GetSignatureForError (), iface.GetSignatureForError ());
3241 public abstract class InterfaceMemberBase : MemberBase
3244 // Common modifiers allowed in a class declaration
3246 protected const Modifiers AllowedModifiersClass =
3249 Modifiers.PROTECTED |
3250 Modifiers.INTERNAL |
3255 Modifiers.OVERRIDE |
3256 Modifiers.ABSTRACT |
3261 // Common modifiers allowed in a struct declaration
3263 protected const Modifiers AllowedModifiersStruct =
3266 Modifiers.PROTECTED |
3267 Modifiers.INTERNAL |
3270 Modifiers.OVERRIDE |
3275 // Common modifiers allowed in a interface declaration
3277 protected const Modifiers AllowedModifiersInterface =
3282 // Whether this is an interface member.
3284 public bool IsInterface;
3287 // If true, this is an explicit interface implementation
3289 public readonly bool IsExplicitImpl;
3291 protected bool is_external_implementation;
3294 // The interface type we are explicitly implementing
3296 public TypeSpec InterfaceType;
3299 // The method we're overriding if this is an override method.
3301 protected MethodSpec base_method;
3303 readonly Modifiers explicit_mod_flags;
3304 public MethodAttributes flags;
3306 protected InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3307 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3309 IsInterface = parent.Kind == MemberKind.Interface;
3310 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3311 explicit_mod_flags = mod;
3314 public abstract Variance ExpectedMemberTypeVariance { get; }
3316 protected override bool CheckBase ()
3318 if (!base.CheckBase ())
3321 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3322 CheckForDuplications ();
3327 // For System.Object only
3328 if (Parent.BaseType == null)
3331 MemberSpec candidate;
3332 bool overrides = false;
3333 var base_member = FindBaseMember (out candidate, ref overrides);
3335 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3336 if (base_member == null) {
3337 if (candidate == null) {
3338 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3339 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3340 "object.Finalize()");
3342 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3343 GetSignatureForError (), SimpleName.GetMemberType (this));
3346 Report.SymbolRelatedToPreviousError (candidate);
3348 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3349 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3350 else if (this is PropertyBase)
3351 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3352 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3354 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3355 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3362 // Handles ambiguous overrides
3364 if (candidate != null) {
3365 Report.SymbolRelatedToPreviousError (candidate);
3366 Report.SymbolRelatedToPreviousError (base_member);
3368 // Get member definition for error reporting
3369 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3370 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3372 Report.Error (462, Location,
3373 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3374 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3377 if (!CheckOverrideAgainstBase (base_member))
3380 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3382 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3383 Report.SymbolRelatedToPreviousError (base_member);
3384 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3385 GetSignatureForError (), base_member.GetSignatureForError ());
3388 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3389 Report.SymbolRelatedToPreviousError (base_member);
3390 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3391 GetSignatureForError (), base_member.GetSignatureForError ());
3395 base_method = base_member as MethodSpec;
3399 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3400 base_member = candidate;
3402 if (base_member == null) {
3403 if ((ModFlags & Modifiers.NEW) != 0) {
3404 if (base_member == null) {
3405 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3406 GetSignatureForError ());
3410 if ((ModFlags & Modifiers.NEW) == 0) {
3411 ModFlags |= Modifiers.NEW;
3412 if (!IsCompilerGenerated) {
3413 Report.SymbolRelatedToPreviousError (base_member);
3414 if ((base_member.Kind & MemberKind.NestedMask) == 0 && !IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3415 Report.Warning (114, 2, Location, "`{0}' hides inherited member `{1}'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword",
3416 GetSignatureForError (), base_member.GetSignatureForError ());
3418 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3419 GetSignatureForError (), base_member.GetSignatureForError ());
3424 if (!IsInterface && base_member.IsAbstract && !overrides && !IsStatic) {
3425 switch (base_member.Kind) {
3426 case MemberKind.Event:
3427 case MemberKind.Indexer:
3428 case MemberKind.Method:
3429 case MemberKind.Property:
3430 Report.SymbolRelatedToPreviousError (base_member);
3431 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3432 GetSignatureForError (), base_member.GetSignatureForError ());
3441 protected virtual bool CheckForDuplications ()
3443 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3447 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3448 // that have been defined.
3450 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3454 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3455 Report.SymbolRelatedToPreviousError (base_member);
3456 Report.Error (506, Location,
3457 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3458 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3462 // Now we check that the overriden method is not final
3463 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3464 Report.SymbolRelatedToPreviousError (base_member);
3465 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3466 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3470 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3471 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3472 Report.SymbolRelatedToPreviousError (base_member);
3473 if (this is PropertyBasedMember) {
3474 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3475 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3477 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3478 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3486 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3488 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3489 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3491 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3493 // It must be at least "protected"
3495 if ((thisp & Modifiers.PROTECTED) == 0) {
3500 // when overriding protected internal, the method can be declared
3501 // protected internal only within the same assembly or assembly
3502 // which has InternalsVisibleTo
3504 if ((thisp & Modifiers.INTERNAL) != 0) {
3505 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3509 // protected overriding protected internal inside same assembly
3510 // requires internal modifier as well
3512 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3519 return thisp == base_classp;
3522 public override bool Define ()
3525 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3526 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3528 flags = MethodAttributes.Public |
3529 MethodAttributes.Abstract |
3530 MethodAttributes.HideBySig |
3531 MethodAttributes.NewSlot |
3532 MethodAttributes.Virtual;
3534 Parent.PartialContainer.MethodModifiersValid (this);
3536 flags = ModifiersExtensions.MethodAttr (ModFlags);
3539 if (IsExplicitImpl) {
3540 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3541 if (InterfaceType == null)
3544 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3545 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3546 GetSignatureForError ());
3549 if (!InterfaceType.IsInterface) {
3550 Report.SymbolRelatedToPreviousError (InterfaceType);
3551 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3552 InterfaceType.GetSignatureForError ());
3554 Parent.PartialContainer.VerifyImplements (this);
3557 Modifiers allowed_explicit = Modifiers.AllowedExplicitImplFlags;
3559 allowed_explicit |= Modifiers.ASYNC;
3561 ModifiersExtensions.Check (allowed_explicit, explicit_mod_flags, 0, Location, Report);
3564 return base.Define ();
3567 protected bool DefineParameters (ParametersCompiled parameters)
3569 if (!parameters.Resolve (this))
3573 for (int i = 0; i < parameters.Count; ++i) {
3574 Parameter p = parameters [i];
3576 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3577 p.Warning_UselessOptionalParameter (Report);
3579 if (p.CheckAccessibility (this))
3582 TypeSpec t = parameters.Types [i];
3583 Report.SymbolRelatedToPreviousError (t);
3584 if (this is Indexer)
3585 Report.Error (55, Location,
3586 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3587 t.GetSignatureForError (), GetSignatureForError ());
3588 else if (this is Operator)
3589 Report.Error (57, Location,
3590 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3591 t.GetSignatureForError (), GetSignatureForError ());
3593 Report.Error (51, Location,
3594 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3595 t.GetSignatureForError (), GetSignatureForError ());
3601 protected override void DoMemberTypeDependentChecks ()
3603 base.DoMemberTypeDependentChecks ();
3605 VarianceDecl.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3608 public override void Emit()
3610 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3611 // We are more strict than csc and report this as an error because SRE does not allow emit that
3612 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3613 if (this is Constructor) {
3614 Report.Warning (824, 1, Location,
3615 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3617 Report.Warning (626, 1, Location,
3618 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3619 GetSignatureForError ());
3626 public override bool EnableOverloadChecks (MemberCore overload)
3629 // Two members can differ in their explicit interface
3630 // type parameter only
3632 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3633 if (imb != null && imb.IsExplicitImpl) {
3634 if (IsExplicitImpl) {
3635 caching_flags |= Flags.MethodOverloadsExist;
3640 return IsExplicitImpl;
3643 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3645 var base_modifiers = base_member.Modifiers;
3647 // Remove internal modifier from types which are not internally accessible
3648 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3649 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3650 base_modifiers = Modifiers.PROTECTED;
3652 Report.SymbolRelatedToPreviousError (base_member);
3653 Report.Error (507, member.Location,
3654 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3655 member.GetSignatureForError (),
3656 ModifiersExtensions.AccessibilityName (base_modifiers),
3657 base_member.GetSignatureForError ());
3660 protected void Error_StaticReturnType ()
3662 Report.Error (722, Location,
3663 "`{0}': static types cannot be used as return types",
3664 MemberType.GetSignatureForError ());
3668 /// Gets base method and its return type
3670 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3672 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3676 // The "short" name of this property / indexer / event. This is the
3677 // name without the explicit interface.
3679 public string ShortName {
3680 get { return MemberName.Name; }
3684 // Returns full metadata method name
3686 public string GetFullName (MemberName name)
3688 return GetFullName (name.Name);
3691 public string GetFullName (string name)
3693 if (!IsExplicitImpl)
3697 // When dealing with explicit members a full interface type
3698 // name is added to member name to avoid possible name conflicts
3700 // We use CSharpName which gets us full name with benefit of
3701 // replacing predefined names which saves some space and name
3704 return InterfaceType.GetSignatureForError () + "." + name;
3707 public override string GetSignatureForDocumentation ()
3710 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetSignatureForDocumentation (true) + "#" + ShortName;
3712 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3715 public override bool IsUsed
3717 get { return IsExplicitImpl || base.IsUsed; }
3720 public override void SetConstraints (List<Constraints> constraints_list)
3722 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3723 Report.Error (460, Location,
3724 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3725 GetSignatureForError ());
3728 base.SetConstraints (constraints_list);
3732 public abstract class MemberBase : MemberCore
3734 protected FullNamedExpression type_expr;
3735 protected TypeSpec member_type;
3736 public new TypeDefinition Parent;
3738 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3739 : base (parent, name, attrs)
3741 this.Parent = parent;
3742 this.type_expr = type;
3744 if (name != MemberName.Null)
3745 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3750 public TypeSpec MemberType {
3756 public FullNamedExpression TypeExpression {
3768 // Main member define entry
3770 public override bool Define ()
3772 DoMemberTypeIndependentChecks ();
3775 // Returns false only when type resolution failed
3777 if (!ResolveMemberType ())
3780 DoMemberTypeDependentChecks ();
3785 // Any type_name independent checks
3787 protected virtual void DoMemberTypeIndependentChecks ()
3789 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3790 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3791 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3792 GetSignatureForError (), Parent.GetSignatureForError ());
3797 // Any type_name dependent checks
3799 protected virtual void DoMemberTypeDependentChecks ()
3801 // verify accessibility
3802 if (!IsAccessibleAs (MemberType)) {
3803 Report.SymbolRelatedToPreviousError (MemberType);
3804 if (this is Property)
3805 Report.Error (53, Location,
3806 "Inconsistent accessibility: property type `" +
3807 MemberType.GetSignatureForError () + "' is less " +
3808 "accessible than property `" + GetSignatureForError () + "'");
3809 else if (this is Indexer)
3810 Report.Error (54, Location,
3811 "Inconsistent accessibility: indexer return type `" +
3812 MemberType.GetSignatureForError () + "' is less " +
3813 "accessible than indexer `" + GetSignatureForError () + "'");
3814 else if (this is MethodCore) {
3815 if (this is Operator)
3816 Report.Error (56, Location,
3817 "Inconsistent accessibility: return type `" +
3818 MemberType.GetSignatureForError () + "' is less " +
3819 "accessible than operator `" + GetSignatureForError () + "'");
3821 Report.Error (50, Location,
3822 "Inconsistent accessibility: return type `" +
3823 MemberType.GetSignatureForError () + "' is less " +
3824 "accessible than method `" + GetSignatureForError () + "'");
3825 } else if (this is Event) {
3826 Report.Error (7025, Location,
3827 "Inconsistent accessibility: event type `{0}' is less accessible than event `{1}'",
3828 MemberType.GetSignatureForError (), GetSignatureForError ());
3830 Report.Error (52, Location,
3831 "Inconsistent accessibility: field type `" +
3832 MemberType.GetSignatureForError () + "' is less " +
3833 "accessible than field `" + GetSignatureForError () + "'");
3838 protected void IsTypePermitted ()
3840 if (MemberType.IsSpecialRuntimeType) {
3841 if (Parent is StateMachine) {
3842 Report.Error (4012, Location,
3843 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3844 MemberType.GetSignatureForError ());
3845 } else if (Parent is HoistedStoreyClass) {
3846 Report.Error (4013, Location,
3847 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3848 MemberType.GetSignatureForError ());
3850 Report.Error (610, Location,
3851 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3856 protected virtual bool CheckBase ()
3858 CheckProtectedModifier ();
3863 public override string GetSignatureForDocumentation ()
3865 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3868 public virtual void PrepareEmit ()
3870 if (member_type != null && type_expr != null)
3871 member_type.CheckObsoleteness (this, type_expr.Location);
3874 protected virtual bool ResolveMemberType ()
3876 if (member_type != null)
3877 throw new InternalErrorException ("Multi-resolve");
3879 member_type = type_expr.ResolveAsType (this);
3880 return member_type != null;