2 // decl.cs: Declaration base class for structs, classes, enums and interfaces.
4 // Author: Miguel de Icaza (miguel@gnu.org)
6 // Licensed under the terms of the GNU GPL
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
10 // TODO: Move the method verification stuff from the class.cs and interface.cs here
14 using System.Collections;
15 using System.Reflection.Emit;
16 using System.Reflection;
18 namespace Mono.CSharp {
21 /// Base representation for members. This is only used to keep track
22 /// of Name, Location and Modifier flags.
24 public abstract class MemberCore {
31 /// Modifier flags that the user specified in the source code
36 /// Location where this declaration happens
38 public readonly Location Location;
40 public MemberCore (string name, Location loc)
46 protected void WarningNotHiding (TypeContainer parent)
50 "The member `" + parent.Name + "." + Name + "' does not hide an " +
51 "inherited member. The keyword new is not required");
55 static string MethodBaseName (MethodBase mb)
57 return "`" + mb.ReflectedType.Name + "." + mb.Name + "'";
60 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method)
63 // FIXME: report the old/new permissions?
66 507, "`" + parent_method + "." + Name +
67 ": can't change the access modifiers from `" +
68 parent_method.DeclaringType.Name + "." + parent_method.Name + "'");
72 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
73 // that have been defined.
75 // `name' is the user visible name for reporting errors (this is used to
76 // provide the right name regarding method names and properties)
78 protected bool CheckMethodAgainstBase (TypeContainer parent,
79 MethodAttributes my_attrs, MethodInfo mb)
83 if ((ModFlags & Modifiers.OVERRIDE) != 0){
84 if (!(mb.IsAbstract || mb.IsVirtual)){
86 506, Location, parent.MakeName (Name) +
87 ": cannot override inherited member " +
88 MethodBaseName (mb) + " because it is not " +
89 "virtual, abstract or override");
93 // Now we check that the overriden method is not final
96 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
97 "override inherited member " + MethodBaseName (mb) +
98 " because it is sealed.");
103 // Check that the permissions are not being changed
105 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
106 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
108 if (thisp != parentp){
109 Error_CannotChangeAccessModifiers (parent, mb);
114 if (mb.IsVirtual || mb.IsAbstract){
115 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
116 if (Name != "Finalize" && (RootContext.WarningLevel >= 2)){
118 114, Location, parent.MakeName (Name) +
119 " hides inherited member " + MethodBaseName (mb) +
120 ". To make the current member override that " +
121 "implementation, add the override keyword, " +
122 "otherwise use the new keyword");
130 public abstract bool Define (TypeContainer parent);
133 // Whehter is it ok to use an unsafe pointer in this type container
135 public bool UnsafeOK (DeclSpace parent)
138 // First check if this MemberCore modifier flags has unsafe set
140 if ((ModFlags & Modifiers.UNSAFE) != 0)
143 if (parent.UnsafeContext)
146 Expression.UnsafeError (Location);
152 // FIXME: This is temporary outside DeclSpace, because I have to fix a bug
153 // in MCS that makes it fail the lookup for the enum
157 /// The result value from adding an declaration into
158 /// a struct or a class
160 public enum AdditionResult {
162 /// The declaration has been successfully
163 /// added to the declation space.
168 /// The symbol has already been defined.
173 /// Returned if the declation being added to the
174 /// name space clashes with its container name.
176 /// The only exceptions for this are constructors
177 /// and static constructors
182 /// Returned if a constructor was created (because syntactically
183 /// it looked like a constructor) but was not (because the name
184 /// of the method is not the same as the container class
189 /// This is only used by static constructors to emit the
190 /// error 111, but this error for other things really
191 /// happens at another level for other functions.
197 /// Base class for structs, classes, enumerations and interfaces.
200 /// They all create new declaration spaces. This
201 /// provides the common foundation for managing those name
204 public abstract class DeclSpace : MemberCore {
206 /// this points to the actual definition that is being
207 /// created with System.Reflection.Emit
209 public TypeBuilder TypeBuilder;
212 /// This variable tracks whether we have Closed the type
214 public bool Created = false;
217 // This is the namespace in which this typecontainer
218 // was declared. We use this to resolve names.
220 public Namespace Namespace;
222 public string Basename;
225 /// defined_names is used for toplevel objects
227 protected Hashtable defined_names;
229 TypeContainer parent;
231 public DeclSpace (TypeContainer parent, string name, Location l)
234 Basename = name.Substring (1 + name.LastIndexOf ('.'));
235 defined_names = new Hashtable ();
236 this.parent = parent;
240 /// Returns a status code based purely on the name
241 /// of the member being added
243 protected AdditionResult IsValid (string name)
245 if (name == Basename)
246 return AdditionResult.EnclosingClash;
248 if (defined_names.Contains (name))
249 return AdditionResult.NameExists;
251 return AdditionResult.Success;
255 /// Introduce @name into this declaration space and
256 /// associates it with the object @o. Note that for
257 /// methods this will just point to the first method. o
259 protected void DefineName (string name, object o)
261 defined_names.Add (name, o);
265 /// Returns the object associated with a given name in the declaration
266 /// space. This is the inverse operation of `DefineName'
268 public object GetDefinition (string name)
270 return defined_names [name];
273 bool in_transit = false;
276 /// This function is used to catch recursive definitions
279 public bool InTransit {
289 public TypeContainer Parent {
296 // root_types contains all the types. All TopLevel types
297 // hence have a parent that points to `root_types', that is
298 // why there is a non-obvious test down here.
300 public bool IsTopLevel {
303 if (parent.parent == null)
310 public virtual void CloseType ()
314 TypeBuilder.CreateType ();
317 // The try/catch is needed because
318 // nested enumerations fail to load when they
321 // Even if this is the right order (enumerations
322 // declared after types).
324 // Note that this still creates the type and
325 // it is possible to save it
332 /// Should be overriten by the appropriate declaration space
334 public abstract TypeBuilder DefineType ();
337 // Whether this is an `unsafe context'
339 public bool UnsafeContext {
341 if ((ModFlags & Modifiers.UNSAFE) != 0)
344 return parent.UnsafeContext;
349 public static string MakeFQN (string nsn, string name)
351 string prefix = (nsn == "" ? "" : nsn + ".");
353 return prefix + name;
356 Type LookupInterfaceOrClass (string ns, string name, out bool error)
362 name = MakeFQN (ns, name);
364 t = TypeManager.LookupType (name);
368 parent = (DeclSpace) RootContext.Tree.Decls [name];
372 t = parent.DefineType ();
374 Report.Error (146, "Class definition is circular: `"+name+"'");
382 /// GetType is used to resolve type names at the DeclSpace level.
383 /// Use this to lookup class/struct bases, interface bases or
384 /// delegate type references
388 /// Contrast this to LookupType which is used inside method bodies to
389 /// lookup types that have already been defined. GetType is used
390 /// during the tree resolution process and potentially define
391 /// recursively the type
393 public Type FindType (string name)
399 // For the case the type we are looking for is nested within this one
400 // or is in any base class
402 DeclSpace containing_ds = this;
404 while (containing_ds != null){
405 Type current_type = containing_ds.TypeBuilder;
407 while (current_type != null) {
408 string pre = current_type.FullName;
410 t = LookupInterfaceOrClass (pre, name, out error);
417 current_type = current_type.BaseType;
419 containing_ds = containing_ds.Parent;
423 // Attempt to lookup the class on our namespace and all it's implicit parents
425 for (string ns = Namespace.Name; ns != null; ns = RootContext.ImplicitParent (ns)) {
427 t = LookupInterfaceOrClass (ns, name, out error);
436 // Attempt to do a direct unqualified lookup
438 t = LookupInterfaceOrClass ("", name, out error);
446 // Attempt to lookup the class on any of the `using'
450 for (Namespace ns = Namespace; ns != null; ns = ns.Parent){
452 t = LookupInterfaceOrClass (ns.Name, name, out error);
460 // Now check the using clause list
462 ArrayList using_list = ns.UsingTable;
464 if (using_list == null)
467 foreach (string n in using_list){
468 t = LookupInterfaceOrClass (n, name, out error);
478 Report.Error (246, Location, "Can not find type `"+name+"'");