+
//
// class.cs: Class and Struct handlers
//
-// Author: Miguel de Icaza (miguel@gnu.org)
+// Authors: Miguel de Icaza (miguel@gnu.org)
+// Martin Baulig (martin@gnome.org)
+// Anirban Bhattacharjee (banirban@novell.com)
//
// Licensed under the terms of the GNU GPL
//
-// (C) 2001 Ximian, Inc (http://www.ximian.com)
+// (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)
//
//
-
+// 2002-10-11 Miguel de Icaza <miguel@ximian.com>
+//
+// * class.cs: Following the comment from 2002-09-26 to AddMethod, I
+// have fixed a remaining problem: not every AddXXXX was adding a
+// fully qualified name.
+//
+// Now everyone registers a fully qualified name in the DeclSpace as
+// being defined instead of the partial name.
+//
+// Downsides: we are slower than we need to be due to the excess
+// copies and the names being registered this way.
+//
+// The reason for this is that we currently depend (on the corlib
+// bootstrap for instance) that types are fully qualified, because
+// we dump all the types in the namespace, and we should really have
+// types inserted into the proper namespace, so we can only store the
+// basenames in the defined_names array.
+//
+//
+#define CACHE
+using System;
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
-using System;
using System.Runtime.CompilerServices;
using System.Diagnostics.SymbolStore;
-namespace Mono.CSharp {
+namespace Mono.MonoBASIC {
/// <summary>
/// This is the base class for structs and classes.
/// </summary>
- public class TypeContainer : DeclSpace {
+ public class TypeContainer : DeclSpace, IMemberContainer {
// Holds a list of classes and structures
ArrayList types;
// Holds the events
ArrayList events;
- // Holds the indexers
- ArrayList indexers;
-
- // Holds the operators
- ArrayList operators;
+ // Holds AddHandlers stements for events
+ ArrayList handlers;
// The emit context for toplevel objects.
EmitContext ec;
-
+
//
// Pointers to the default constructor and the default static constructor
//
// Whether we have seen a static constructor for this class or not
//
bool have_static_constructor = false;
+
+ //
+ // Whether we have at least one non-static field
+ //
+ bool have_nonstatic_fields = false;
//
// This one is computed after we can distinguish interfaces
// from classes from the arraylist `type_bases'
//
string base_class_name;
-
+ public Type base_class_type;
+
ArrayList type_bases;
- // Attributes for this type
- protected Attributes attributes;
-
// Information in the case we are an attribute type
- public AttributeTargets Targets = AttributeTargets.All;
- public bool AllowMultiple = false;
- public bool Inherited;
+ AttributeUsageAttribute attribute_usage = new AttributeUsageAttribute (AttributeTargets.All);
+
+ public AttributeUsageAttribute AttributeUsage {
+ get {
+ return attribute_usage;
+ }
+
+ set {
+ attribute_usage = value;
+ }
+ }
+
+ // The interfaces we implement.
+ Type [] ifaces;
+ // The parent member container and our member cache
+ IMemberContainer parent_container;
+ MemberCache member_cache;
+
//
// The indexer name for this class
//
- public string IndexerName;
+ public string DefaultPropName;
- public TypeContainer (TypeContainer parent, string name, Location l)
- : base (parent, name, l)
+ public TypeContainer (TypeContainer parent, string name, Attributes attrs, Location l)
+ : base (parent, name, attrs, l)
{
- string n;
types = new ArrayList ();
+
+ base_class_name = null;
+ /* string n;
+
if (parent == null)
n = "";
else
n = parent.Name;
- base_class_name = null;
-
- //Console.WriteLine ("New class " + name + " inside " + n);
+ Console.WriteLine ("New class " + name + " inside " + n);*/
}
public AdditionResult AddConstant (Const constant)
{
AdditionResult res;
- string name = constant.Name;
+ string basename = constant.Name;
- if ((res = IsValid (name)) != AdditionResult.Success)
+ if ((res = IsValid (basename)) != AdditionResult.Success)
return res;
if (constants == null)
constants = new ArrayList ();
constants.Add (constant);
- DefineName (name, constant);
+ DefineName (Name + "." + basename, constant);
return AdditionResult.Success;
}
- public AdditionResult AddEnum (Mono.CSharp.Enum e)
+ public AdditionResult AddEnum (Mono.MonoBASIC.Enum e)
{
AdditionResult res;
- string name = e.Name;
- if ((res = IsValid (name)) != AdditionResult.Success)
+ if ((res = IsValid (e.Basename)) != AdditionResult.Success)
return res;
if (enums == null)
enums = new ArrayList ();
enums.Add (e);
- DefineName (name, e);
+ DefineName (e.Name, e);
return AdditionResult.Success;
}
public AdditionResult AddClass (Class c)
{
AdditionResult res;
- string name = c.Name;
-
-
- if ((res = IsValid (name)) != AdditionResult.Success)
+
+ if ((res = IsValid (c.Basename)) != AdditionResult.Success)
return res;
-
- DefineName (name, c);
+
+
+
+ DefineName (c.Name, c);
types.Add (c);
-
+
+ // FIXME: Do we really need to explicitly add an empty default static constructor?
+ // Apparently we don't
+/* if (c.default_static_constructor == null)
+ {
+ bool isModule = c is Mono.MonoBASIC.Module;
+ Constructor dc = new Constructor ("New", Parameters.EmptyReadOnlyParameters, null, c.Location);
+ dc.ModFlags = isModule ? Modifiers.PUBLIC | Modifiers.STATIC : Modifiers.PUBLIC;
+ c.AddConstructor (dc);
+ }
+*/
+ //--------------------------------------------------------------
+
return AdditionResult.Success;
}
public AdditionResult AddStruct (Struct s)
{
AdditionResult res;
- string name = s.Name;
- if ((res = IsValid (name)) != AdditionResult.Success)
+ if ((res = IsValid (s.Basename)) != AdditionResult.Success)
return res;
- DefineName (name, s);
+ DefineName (s.Name, s);
types.Add (s);
return AdditionResult.Success;
public AdditionResult AddDelegate (Delegate d)
{
AdditionResult res;
- string name = d.Name;
- if ((res = IsValid (name)) != AdditionResult.Success)
+ if ((res = IsValid (d.Basename)) != AdditionResult.Success)
return res;
if (delegates == null)
delegates = new ArrayList ();
- DefineName (name, d);
+ DefineName (d.Name, d);
delegates.Add (d);
return AdditionResult.Success;
public AdditionResult AddMethod (Method method)
{
- string name = method.Name;
- Object value = defined_names [name];
-
+ string basename = method.Name;
+ string fullname = Name + "." + basename;
+
+ Object value = defined_names [fullname];
+
if (value != null && (!(value is Method)))
return AdditionResult.NameExists;
+ if (basename == Basename)
+ return AdditionResult.EnclosingClash;
+
if (methods == null)
methods = new ArrayList ();
- methods.Add (method);
- if (value != null)
- DefineName (name, method);
+ if (method.Name.IndexOf (".") != -1)
+ methods.Insert (0, method);
+ else
+ methods.Add (method);
+
+ if (value == null)
+ DefineName (fullname, method);
return AdditionResult.Success;
}
public AdditionResult AddConstructor (Constructor c)
{
- if (c.Name != Basename)
+ if (c.Name != "New")
return AdditionResult.NotAConstructor;
bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
-
+
if (is_static){
have_static_constructor = true;
if (default_static_constructor != null){
default_static_constructor = c;
} else {
if (c.IsDefault ()){
- if (default_constructor != null)
- return AdditionResult.MethodExists;
+ /*if (default_constructor != null)
+ return AdditionResult.MethodExists;*/
default_constructor = c;
}
public AdditionResult AddInterface (Interface iface)
{
AdditionResult res;
- string name = iface.Name;
- if ((res = IsValid (name)) != AdditionResult.Success)
+ if ((res = IsValid (iface.Basename)) != AdditionResult.Success)
return res;
if (interfaces == null)
interfaces = new ArrayList ();
interfaces.Add (iface);
- DefineName (name, iface);
+ DefineName (iface.Name, iface);
return AdditionResult.Success;
}
public AdditionResult AddField (Field field)
{
AdditionResult res;
- string name = field.Name;
-
- if ((res = IsValid (name)) != AdditionResult.Success)
- return res;
+ string basename = field.Name;
+ if ((res = IsValid (basename)) != AdditionResult.Success)
+ return res;
+
if (fields == null)
fields = new ArrayList ();
-
+
fields.Add (field);
- if (field.Initializer != null){
- if ((field.ModFlags & Modifiers.STATIC) != 0){
+ if (field.HasInitializer){
+ if ((field.ModFlags & Modifiers.STATIC) != 0) {
if (initialized_static_fields == null)
initialized_static_fields = new ArrayList ();
initialized_fields.Add (field);
}
}
-
- DefineName (name, field);
+
+ if ((field.ModFlags & Modifiers.STATIC) == 0)
+ have_nonstatic_fields = true;
+
+ DefineName (Name + "." + basename, field);
return AdditionResult.Success;
}
public AdditionResult AddProperty (Property prop)
{
AdditionResult res;
- string name = prop.Name;
+ string basename = prop.Name;
+
+ string fullname = Name + "." + basename;
- if ((res = IsValid (name)) != AdditionResult.Success)
+ Object value = defined_names [fullname];
+
+ if (value != null && (!(value is Property)))
+ return AdditionResult.NameExists;
+
+ if ((res = IsValid (basename)) != AdditionResult.Success)
return res;
if (properties == null)
properties = new ArrayList ();
- properties.Add (prop);
- DefineName (name, prop);
+ if (prop.Name.IndexOf (".") != -1)
+ properties.Insert (0, prop);
+ else
+ properties.Add (prop);
+
+ if (value == null)
+ DefineName (Name + "." + basename, prop);
return AdditionResult.Success;
}
public AdditionResult AddEvent (Event e)
{
AdditionResult res;
- string name = e.Name;
+ string basename = e.Name;
- if ((res = IsValid (name)) != AdditionResult.Success)
+ if ((res = IsValid (basename)) != AdditionResult.Success)
return res;
if (events == null)
events = new ArrayList ();
events.Add (e);
- DefineName (name, e);
-
- return AdditionResult.Success;
- }
-
- public AdditionResult AddIndexer (Indexer i)
- {
- if (indexers == null)
- indexers = new ArrayList ();
-
- indexers.Add (i);
+ DefineName (Name + "." + basename, e);
return AdditionResult.Success;
}
- public AdditionResult AddOperator (Operator op)
+ public AdditionResult AddEventHandler (Statement stmt)
{
- if (operators == null)
- operators = new ArrayList ();
-
- operators.Add (op);
+ if (handlers == null)
+ handlers = new ArrayList ();
+ handlers.Add (stmt);
return AdditionResult.Success;
}
interface_order.Add (iface);
}
-
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ {
+ base.ApplyAttributeBuilder (a, cb);
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ throw new NotSupportedException ();
+ }
+ }
+
public ArrayList Types {
get {
return types;
get {
return fields;
}
+
+ set {
+ fields = value;
+ }
}
public ArrayList InstanceConstructors {
}
}
- public ArrayList Indexers {
- get {
- return indexers;
- }
- }
-
- public ArrayList Operators {
- get {
- return operators;
- }
- }
-
public ArrayList Delegates {
get {
return delegates;
}
}
- public Attributes OptAttributes {
- get {
- return attributes;
- }
- }
-
public bool HaveStaticConstructor {
get {
return have_static_constructor;
}
}
+ public ArrayList EventHandlers {
+ get {
+ return handlers;
+ }
+ }
+
//
// Emits the instance field initializers
//
public bool EmitFieldInitializers (EmitContext ec)
{
ArrayList fields;
- ILGenerator ig = ec.ig;
+ //ILGenerator ig = ec.ig;
Expression instance_expr;
if (ec.IsStatic){
if (fields == null)
return true;
-
- foreach (Field f in fields){
- Object init = f.Initializer;
- Expression e;
- if (init is Expression)
- e = (Expression) init;
- else {
- string base_type = f.Type.Substring (0, f.Type.IndexOf ("["));
- string rank = f.Type.Substring (f.Type.IndexOf ("["));
- e = new ArrayCreation (base_type, rank, (ArrayList)init, f.Location);
- }
+ foreach (Field f in fields){
+ Expression e = f.GetInitializerExpression (ec);
+ if (e == null)
+ return false;
Location l = f.Location;
FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
}
}
-
+
return true;
}
Constructor c;
int mods = 0;
- c = new Constructor (Basename, Parameters.GetEmptyReadOnlyParameters (),
- new ConstructorBaseInitializer (null, new Location (-1)),
- new Location (-1));
+ c = new Constructor ("New", Parameters.EmptyReadOnlyParameters,
+ null,
+ Location.Null);
- if (is_static)
+ if (is_static) {
mods = Modifiers.STATIC;
-
- c.ModFlags = mods;
+ c.ModFlags = mods;
+ }
+ else
+ c.Initializer = new ConstructorBaseInitializer (
+ null, Parameters.EmptyReadOnlyParameters,
+ Location.Null);
AddConstructor (c);
foreach (Field f in initialized_fields){
Report.Error (
- 573, Location,
+ 31049, Location,
"`" + n + "." + f.Name + "': can not have " +
"instance field initializers in structs");
}
}
- struct TypeAndMethods {
- public Type type;
- public MethodInfo [] methods;
-
- // Far from ideal, but we want to avoid creating a copy
- // of methods above.
- public Type [][] args;
-
- //
- // This flag on the method says `We found a match, but
- // because it was private, we could not use the match
- //
- public bool [] found;
- }
-
- //
- // This array keeps track of the pending implementations
- //
- TypeAndMethods [] pending_implementations;
-
- //
- // Returns a list of the abstract methods that are exposed by all of our
- // parents that we must implement. Notice that this `flattens' the
- // method search space, and takes into account overrides.
- //
- ArrayList GetAbstractMethods (Type t)
- {
- ArrayList list = null;
- bool searching = true;
- Type current_type = t;
-
- do {
- MemberInfo [] mi;
-
- mi = FindMembers (
- current_type, MemberTypes.Method,
- BindingFlags.Public | BindingFlags.Instance |
- BindingFlags.DeclaredOnly,
- virtual_method_filter, null);
-
- if (current_type == TypeManager.object_type)
- searching = false;
- else {
- current_type = current_type.BaseType;
- if (!current_type.IsAbstract)
- searching = false;
- }
-
- if (mi == null)
- continue;
-
- int count = mi.Length;
- if (count == 0)
- continue;
-
- if (count == 1 && !(mi [0] is MethodBase))
- searching = false;
- else
- list = TypeManager.CopyNewMethods (list, mi);
- } while (searching);
-
- if (list == null)
- return null;
-
- for (int i = 0; i < list.Count; i++){
- while (list.Count > i && !((MethodInfo) list [i]).IsAbstract)
- list.RemoveAt (i);
- }
-
- if (list.Count == 0)
- return null;
-
- return list;
- }
-
- //
- // Registers the required method implementations for this class
- //
- // Register method implementations are either abstract methods
- // flagged as such on the base class or interface methods
- //
- public void RegisterRequiredImplementations ()
- {
- Type [] ifaces = TypeBuilder.GetInterfaces ();
- Type b = TypeBuilder.BaseType;
- int icount = 0;
-
-#if DEBUG
- {
- Type x = TypeBuilder;
-
- while (x != null){
- Type [] iff = x.GetInterfaces ();
- Console.WriteLine ("Type: " + x.Name);
-
- foreach (Type tt in iff){
- Console.WriteLine (" Iface: " + tt.Name);
- }
- x = x.BaseType;
- }
- }
-#endif
-
- icount = ifaces.Length;
-
- //
- // If we are implementing an abstract class, and we are not
- // ourselves abstract, and there are abstract methods (C# allows
- // abstract classes that have no abstract methods), then allocate
- // one slot.
- //
- // We also pre-compute the methods.
- //
- bool implementing_abstract = (b.IsAbstract && !TypeBuilder.IsAbstract);
- ArrayList abstract_methods = null;
-
- if (implementing_abstract){
- abstract_methods = GetAbstractMethods (b);
-
- if (abstract_methods == null)
- implementing_abstract = false;
- }
-
- int total = icount + (implementing_abstract ? 1 : 0);
- if (total == 0)
- return;
-
- pending_implementations = new TypeAndMethods [total];
-
- int i = 0;
- if (ifaces != null){
- foreach (Type t in ifaces){
- MethodInfo [] mi;
-
- if (t is TypeBuilder){
- Interface iface;
-
- iface = TypeManager.LookupInterface (t);
-
- mi = iface.GetMethods ();
- } else
- mi = t.GetMethods ();
-
- int count = mi.Length;
- pending_implementations [i].type = t;
- pending_implementations [i].methods = mi;
- pending_implementations [i].args = new Type [count][];
- pending_implementations [i].found = new bool [count];
-
- int j = 0;
- foreach (MethodInfo m in mi){
- Type [] types = TypeManager.GetArgumentTypes (m);
-
- pending_implementations [i].args [j] = types;
- j++;
- }
- i++;
- }
- }
-
- if (abstract_methods != null){
- int count = abstract_methods.Count;
- pending_implementations [i].methods = new MethodInfo [count];
-
- abstract_methods.CopyTo (pending_implementations [i].methods, 0);
- pending_implementations [i].found = new bool [count];
- pending_implementations [i].args = new Type [count][];
- pending_implementations [i].type = TypeBuilder;
-
- int j = 0;
- foreach (MemberInfo m in abstract_methods){
- MethodInfo mi = (MethodInfo) m;
-
- Type [] types = TypeManager.GetArgumentTypes (mi);
-
- pending_implementations [i].args [j] = types;
- j++;
- }
- }
- }
+ /// <remarks>
+ /// The pending methods that need to be implemented (interfaces or abstract methods)
+ /// </remarks>
+ public PendingImplementation Pending;
/// <summary>
/// This function computes the Base class and also the
//
count = bases.Count;
- if (is_class){
- string name = (string) bases [0];
- Type first = FindType (name);
+ if (is_class && (!(this is Interface))){
+ Expression name = (Expression) bases [0];
+ name = ResolveTypeExpr (name, false, Location);
- if (first == null){
+ if (name == null){
error = true;
return null;
}
+ Type first = name.Type;
+
if (first.IsClass){
parent = first;
start = 1;
start = 0;
}
+ if (parent.IsSealed )
+ Report.Error (30299, Location,
+ "Class " + Name + " cannot inherit " +
+ "'NotInheritable' class " + TypeManager.MonoBASIC_Name (parent));
+
+ if (!AsAccessible (parent, ModFlags))
+ Report.Error (30389, Location,
+ "Inconsistent accessibility: base class `" +
+ TypeManager.MonoBASIC_Name (parent) + "' is less " +
+ "accessible than class `" +
+ Name + "'");
+
} else {
start = 0;
}
Type [] ifaces = new Type [count-start];
for (i = start, j = 0; i < count; i++, j++){
- string name = (string) bases [i];
- Type t = FindType (name);
-
+ Expression name = (Expression) bases [i];
+ Expression resolved = ResolveTypeExpr (name, false, Location);
+ bases [i] = resolved;
+ Type t = resolved.Type;
if (t == null){
error = true;
return null;
error = true;
return null;
}
-
+
if (t.IsSealed) {
- string detail = "";
-
if (t.IsValueType)
- detail = " (a class can not inherit from a struct/enum)";
+ Report.Error (30258, "class `"+ Name +
+ "': a class can not inherit from a struct/enum");
- Report.Error (509, "class `"+ Name +
+ /*Report.Error (509, "class `"+ Name +
"': Cannot inherit from sealed class `"+
- bases [i]+"'"+detail);
+ bases [i]);*/
error = true;
return null;
}
if (t.IsClass) {
if (parent != null){
- Report.Error (527, "In Class `" + Name + "', type `"+
- name+"' is not an interface");
+ Report.Error (30121, Name + ": A class cannot inherit " +
+ "more than one class");
error = true;
return null;
}
}
-
+
+ for (int x = 0; x < j; x++) {
+ if (t == ifaces [x]) {
+ Report.Error (528, "`" + name + "' is already listed in interface list");
+ error = true;
+ return null;
+ }
+ }
+
ifaces [j] = t;
}
//
public override TypeBuilder DefineType ()
{
- Type parent;
- Type [] ifaces;
bool error;
bool is_class;
return null;
InTransit = true;
-
+
if (this is Class)
is_class = true;
else
is_class = false;
- ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
+ ec = new EmitContext (this, Mono.MonoBASIC.Location.Null, null, null, ModFlags);
- ifaces = GetClassBases (is_class, out parent, out error);
+ if (((ModFlags & Modifiers.ABSTRACT ) != 0) &&
+ ((ModFlags & Modifiers.SEALED) != 0)){
+ Report.Error (31408, Location,
+ "Class declared as 'MustInherit' cannot be declared as 'NotInheritable'");
+ }
+ ifaces = GetClassBases (is_class, out base_class_type, out error);
if (error)
return null;
- if (is_class && parent != null){
- if (parent == TypeManager.enum_type ||
- (parent == TypeManager.value_type && RootContext.StdLib) ||
- parent == TypeManager.delegate_type ||
- parent == TypeManager.array_type){
+ if (this is Interface)
+ base_class_type = null;
+
+ if (is_class && base_class_type != null){
+ if (base_class_type == TypeManager.enum_type ||
+ (base_class_type == TypeManager.value_type && RootContext.StdLib) ||
+ base_class_type == TypeManager.delegate_type ||
+ base_class_type == TypeManager.array_type){
Report.Error (
644, Location, "`" + Name + "' cannot inherit from " +
- "special class `" + TypeManager.CSharpName (parent) + "'");
+ "special class `" + TypeManager.MonoBASIC_Name (base_class_type) + "'");
return null;
}
}
if (!is_class && TypeManager.value_type == null)
throw new Exception ();
+ if (is_class && Parent.Parent == null && (!(this is Interface)))
+ {
+ if ((ModFlags & Modifiers.PRIVATE) != 0)
+ Report.Error (31089, Location,
+ "Only internal classes can be declared as 'Private'");
+
+ if ((ModFlags & Modifiers.PROTECTED) != 0)
+ Report.Error (31047, Location,
+ "Only internal classes can be declared as 'Protected'");
+ }
+
+ if ((Parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
+ Report.Error (30735, Location,
+ "'Type' inside a 'Module' can not be " +
+ "declared as 'Protected'");
+
+ if ((Parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
+ Report.Error (30435, Location,
+ "'Type' inside a 'Structure' can not be " +
+ "declared as 'Protected'");
+
TypeAttributes type_attributes = TypeAttr;
- // if (parent_builder is ModuleBuilder) {
if (IsTopLevel){
ModuleBuilder builder = CodeGen.ModuleBuilder;
+ TypeBuilder = builder.DefineType (
+ Name, type_attributes, base_class_type, ifaces);
- //
- // Structs with no fields need to have a ".size 1"
- // appended
- //
-
- if (!is_class && Fields == null)
- TypeBuilder = builder.DefineType (Name,
- type_attributes,
- parent,
- PackingSize.Unspecified, 1);
- else
- //
- // classes or structs with fields
- //
- TypeBuilder = builder.DefineType (Name,
- type_attributes,
- parent,
- ifaces);
} else {
TypeBuilder builder = Parent.TypeBuilder;
+ TypeBuilder = builder.DefineNestedType (
+ Basename, type_attributes, base_class_type, ifaces);
+ }
- //
- // Structs with no fields need to have a ".size 1"
- // appended
- //
- if (!is_class && Fields == null)
- TypeBuilder = builder.DefineNestedType (Basename,
- type_attributes,
- parent,
- PackingSize.Unspecified);
- else {
- //
- // classes or structs with fields
- //
- TypeBuilder = builder.DefineNestedType (Basename,
- type_attributes,
- parent,
- ifaces);
+ if (!is_class)
+ {
+ // structure must contain atleast one member variable
+ if(!have_nonstatic_fields){
+ Report.Error (
+ 30281, Location, "Structure `" + Name + "' do not " +
+ "contain any member Variable");
+
+ /*TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
+ FieldAttributes.Private);*/
+ }
+
+ // add interfaces that were not added at type creation (weird API issue)
+ if (!have_nonstatic_fields && (ifaces != null)) {
+ foreach (Type i in ifaces)
+ TypeBuilder.AddInterfaceImplementation (i);
}
}
+
//
// Finish the setup for the EmitContext
//
TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
- if (parent == TypeManager.attribute_type ||
- parent.IsSubclassOf (TypeManager.attribute_type)) {
+ if ((base_class_type != null) &&
+ (base_class_type == TypeManager.attribute_type ||
+ base_class_type.IsSubclassOf (TypeManager.attribute_type))) {
RootContext.RegisterAttribute (this);
- TypeManager.RegisterAttrType (TypeBuilder, this);
} else
RootContext.RegisterOrder (this);
void DefineMembers (ArrayList list, MemberInfo [] defined_names)
{
int idx;
-
+
+ // if one of the overloaded method is having
+ // Shadows or Overloads modifier all other should
+ // have the same modifier
+ Hashtable members = new Hashtable();
+ int modval;
+ foreach (MemberCore mc in list)
+ {
+ modval = 0;
+ if(members[mc.Name] == null)
+ {
+ foreach (MemberCore m in list)
+ {
+ if(m.Name == mc.Name)
+ {
+ if ((m.ModFlags & Modifiers.SHADOWS) != 0)
+ {
+ modval = Modifiers.SHADOWS;
+ break;
+ }
+ else if((m.ModFlags & Modifiers.NEW) != 0)
+ {
+ modval = Modifiers.NEW;
+ }
+ }
+ }
+ members.Add(mc.Name, modval);
+ }
+
+ modval = (int)members[mc.Name];
+ if(modval != 0)
+ {
+ if(((modval & Modifiers.SHADOWS) != 0) && ((mc.ModFlags & Modifiers.SHADOWS) == 0))
+ Report.Error (
+ 30695, mc.Location,
+ "Function '" + mc.Name + "': must be declared 'Shadows' " +
+ "because another '" + mc.Name + "' declared 'Shadows'");
+ else if(((modval & Modifiers.NEW) != 0) && ((mc.ModFlags & Modifiers.NEW) == 0))
+ Report.Error (
+ 31409, mc.Location,
+ "Function '" + mc.Name + "': must be declared 'Overloads' " +
+ "because another '" + mc.Name + "' declared 'Overloads'");
+ }
+ }
+ members.Clear ();
remove_list.Clear ();
foreach (MemberCore mc in list){
if (RootContext.WarningLevel >= 4){
if ((mc.ModFlags & Modifiers.NEW) != 0)
Warning_KewywordNewNotRequired (mc.Location, mc);
+ if ((mc.ModFlags & Modifiers.SHADOWS) != 0)
+ Warning_KewywordShadowsNotRequired (mc.Location, mc);
}
continue;
}
if (match is MethodBase && mc is MethodCore)
continue;
- if ((mc.ModFlags & Modifiers.NEW) == 0)
- Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
+ if (((mc.ModFlags & Modifiers.SHADOWS) == 0) && idx > 0)
+ Warning_KeywordShadowsRequired (mc.Location, defined_names [idx]);
+
}
foreach (object o in remove_list)
remove_list.Clear ();
}
- //
- // Defines the indexers, and also verifies that the IndexerNameAttribute in the
- // class is consisten. Either it is `Item' or it is the name defined by all the
- // indexers with the `IndexerName' attribute.
- //
- // Turns out that the IndexerNameAttribute is applied to each indexer,
- // but it is never emitted, instead a DefaultName attribute is attached
- // to the class.
- //
- void DefineIndexers ()
+ static void Error_KeywordNotAllowed (Location loc)
{
- string class_indexer_name = null;
-
- foreach (Indexer i in Indexers){
- string name;
-
- i.Define (this);
-
- name = i.IndexerName;
- if (class_indexer_name == null){
- class_indexer_name = name;
- continue;
- }
-
- if (name == class_indexer_name)
- continue;
-
- Report.Error (
- 668, "Two indexers have different names, " +
- " you should use the same name for all your indexers");
- }
- if (class_indexer_name == null)
- class_indexer_name = "Item";
- IndexerName = class_indexer_name;
+ Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
}
-
+
/// <summary>
/// Populates our TypeBuilder with fields and methods
/// </summary>
- public override bool Define (TypeContainer parent)
+ public override bool DefineMembers (TypeContainer parent)
{
MemberInfo [] defined_names = null;
- if (RootContext.WarningLevel > 1){
+ if (interface_order != null){
+ foreach (Interface iface in interface_order)
+ if ((iface.ModFlags & Modifiers.NEW) == 0)
+ iface.DefineMembers (this);
+ else
+ Error_KeywordNotAllowed (iface.Location);
+ }
+
+ if (RootContext.WarningLevel > 1){
Type ptype;
//
//
ptype = TypeBuilder.BaseType;
if (ptype != null){
- defined_names = FindMembers (
+ defined_names = (MemberInfo []) FindMembers (
ptype, MemberTypes.All & ~MemberTypes.Constructor,
BindingFlags.Public | BindingFlags.Instance |
BindingFlags.Static, null, null);
if (fields != null)
DefineMembers (fields, defined_names);
- if (this is Class){
+ if (this is Class && (!(this is Interface))){
if (instance_constructors == null){
- if (default_constructor == null)
+ if (default_constructor == null)
DefineDefaultConstructor (false);
}
ReportStructInitializedInstanceError ();
}
- RegisterRequiredImplementations ();
-
+ if (!(this is Interface))
+ Pending = PendingImplementation.GetPendingImplementations (this);
//
// Constructors are not in the defined_names array
//
if (events != null)
DefineMembers (events, defined_names);
- if (indexers != null) {
- DefineIndexers ();
- } else
- IndexerName = "Item";
-
- if (operators != null)
- DefineMembers (operators, null);
-
if (enums != null)
DefineMembers (enums, defined_names);
if (delegates != null)
DefineMembers (delegates, defined_names);
+#if CACHE
+ if (TypeBuilder.BaseType != null)
+ parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
+
+ member_cache = new MemberCache (this);
+#endif
+
return true;
}
- /// <summary>
- /// Looks up the alias for the name
- /// </summary>
- public string LookupAlias (string name)
+ public override bool Define (TypeContainer parent)
{
- if (Namespace != null)
- return Namespace.LookupAlias (name);
- else
- return null;
+ if (interface_order != null){
+ foreach (Interface iface in interface_order)
+ if ((iface.ModFlags & Modifiers.NEW) == 0)
+ iface.Define (this);
+ }
+
+ return true;
}
-
+
/// <summary>
/// This function is based by a delegate to the FindMembers routine
/// </summary>
/// </summary>
static MemberFilter accepting_filter;
- static bool IsVirtualFilter (MemberInfo m, object filterCriteria)
- {
- if (!(m is MethodInfo))
- return false;
-
- return ((MethodInfo) m).IsVirtual;
- }
-
- /// <summary>
- /// This filter is used by FindMembers, and it is used to
- /// extract only virtual/abstract fields
- /// </summary>
- static MemberFilter virtual_method_filter;
/// <summary>
/// A member comparission method based on name only
static TypeContainer ()
{
accepting_filter = new MemberFilter (AlwaysAccept);
- virtual_method_filter = new MemberFilter (IsVirtualFilter);
mif_compare = new MemberInfoCompare ();
}
//
// Since the whole process is a no-op, it is fine to check for null here.
//
- public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
- MemberFilter filter, object criteria)
+ public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+ MemberFilter filter, object criteria)
{
ArrayList members = new ArrayList ();
- bool priv = (bf & BindingFlags.NonPublic) != 0;
+
+ int modflags = 0;
+ if ((bf & BindingFlags.Public) != 0)
+ modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
+ Modifiers.INTERNAL;
+ if ((bf & BindingFlags.NonPublic) != 0)
+ modflags |= Modifiers.PRIVATE;
+
+ int static_mask = 0, static_flags = 0;
+ switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
+ case BindingFlags.Static:
+ static_mask = static_flags = Modifiers.STATIC;
+ break;
+
+ case BindingFlags.Instance:
+ static_mask = Modifiers.STATIC;
+ static_flags = 0;
+ break;
+
+ default:
+ static_mask = static_flags = 0;
+ break;
+ }
+
+ Timer.StartTimer (TimerType.TcFindMembers);
if (filter == null)
filter = accepting_filter;
-
+
if ((mt & MemberTypes.Field) != 0) {
if (fields != null) {
foreach (Field f in fields) {
- if ((f.ModFlags & Modifiers.PRIVATE) != 0)
- if (!priv)
- continue;
+ if ((f.ModFlags & modflags) == 0)
+ continue;
+ if ((f.ModFlags & static_mask) != static_flags)
+ continue;
FieldBuilder fb = f.FieldBuilder;
if (fb != null && filter (fb, criteria) == true)
if (constants != null) {
foreach (Const con in constants) {
- if ((con.ModFlags & Modifiers.PRIVATE) != 0)
- if (!priv)
- continue;
-
+ if ((con.ModFlags & modflags) == 0)
+ continue;
+ if ((con.ModFlags & static_mask) != static_flags)
+ continue;
+
FieldBuilder fb = con.FieldBuilder;
if (fb != null && filter (fb, criteria) == true)
members.Add (fb);
if ((mt & MemberTypes.Method) != 0) {
if (methods != null) {
foreach (Method m in methods) {
- if ((m.ModFlags & Modifiers.PRIVATE) != 0)
- if (!priv)
- continue;
+ if ((m.ModFlags & modflags) == 0)
+ continue;
+ if ((m.ModFlags & static_mask) != static_flags)
+ continue;
MethodBuilder mb = m.MethodBuilder;
}
}
- if (operators != null){
- foreach (Operator o in operators) {
- if ((o.ModFlags & Modifiers.PRIVATE) != 0)
- if (!priv)
- continue;
-
- MethodBuilder ob = o.OperatorMethodBuilder;
- if (ob != null && filter (ob, criteria) == true)
- members.Add (ob);
- }
- }
-
if (properties != null){
foreach (Property p in properties){
- if ((p.ModFlags & Modifiers.PRIVATE) != 0)
- if (!priv)
- continue;
+ if ((p.ModFlags & modflags) == 0)
+ continue;
+ if ((p.ModFlags & static_mask) != static_flags)
+ continue;
MethodBuilder b;
if ((mt & MemberTypes.Event) != 0) {
if (events != null)
foreach (Event e in events) {
- if ((e.ModFlags & Modifiers.PRIVATE) != 0)
- if (!priv)
- continue;
+ if ((e.ModFlags & modflags) == 0)
+ continue;
+ if ((e.ModFlags & static_mask) != static_flags)
+ continue;
MemberInfo eb = e.EventBuilder;
if (eb != null && filter (eb, criteria) == true)
if ((mt & MemberTypes.Property) != 0){
if (properties != null)
foreach (Property p in properties) {
- if ((p.ModFlags & Modifiers.PRIVATE) != 0)
- if (!priv)
- continue;
-
+ if ((p.ModFlags & modflags) == 0)
+ continue;
+ if ((p.ModFlags & static_mask) != static_flags)
+ continue;
+
MemberInfo pb = p.PropertyBuilder;
- if (pb != null && filter (pb, criteria) == true) {
- members.Add (p.PropertyBuilder);
- }
- }
- if (indexers != null)
- foreach (Indexer ix in indexers) {
- if ((ix.ModFlags & Modifiers.PRIVATE) != 0)
- if (!priv)
- continue;
-
- MemberInfo ib = ix.PropertyBuilder;
- if (ib != null && filter (ib, criteria) == true) {
- members.Add (ix.PropertyBuilder);
- }
+ if (pb != null && filter (pb, criteria) == true)
+ members.Add (p.PropertyBuilder);
}
}
if ((mt & MemberTypes.NestedType) != 0) {
+ if (types != null){
+ foreach (TypeContainer t in types) {
+ if ((t.ModFlags & modflags) == 0)
+ continue;
- if (Types != null)
- foreach (TypeContainer t in Types)
- if (filter (t.TypeBuilder, criteria) == true)
- members.Add (t.TypeBuilder);
+ TypeBuilder tb = t.TypeBuilder;
+ if (tb != null && (filter (tb, criteria) == true))
+ members.Add (tb);
+ }
+ }
+
+ if (enums != null){
+ foreach (Enum en in enums){
+ if ((en.ModFlags & modflags) == 0)
+ continue;
- if (Enums != null)
- foreach (Enum en in Enums)
- if (filter (en.TypeBuilder, criteria) == true)
- members.Add (en.TypeBuilder);
+ TypeBuilder tb = en.TypeBuilder;
+ if (tb != null && (filter (tb, criteria) == true))
+ members.Add (tb);
+ }
+ }
+ if (delegates != null){
+ foreach (Delegate d in delegates){
+ if ((d.ModFlags & modflags) == 0)
+ continue;
+
+ TypeBuilder tb = d.TypeBuilder;
+ if (tb != null && (filter (tb, criteria) == true))
+ members.Add (tb);
+ }
+ }
+
+ if (interfaces != null){
+ foreach (Interface iface in interfaces){
+ if ((iface.ModFlags & modflags) == 0)
+ continue;
+
+ TypeBuilder tb = iface.TypeBuilder;
+ if (tb != null && (filter (tb, criteria) == true))
+ members.Add (tb);
+ }
+ }
}
if ((mt & MemberTypes.Constructor) != 0){
- if (instance_constructors != null){
+ if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
foreach (Constructor c in instance_constructors){
- ConstructorBuilder cb = c.ConstructorBuilder;
+ if ((c.ModFlags & modflags) == 0)
+ continue;
+ ConstructorBuilder cb = c.ConstructorBuilder;
if (cb != null)
if (filter (cb, criteria) == true)
members.Add (cb);
}
}
- if (default_static_constructor != null){
+ if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null) &&
+ ((default_static_constructor.ModFlags & modflags) != 0)){
ConstructorBuilder cb =
default_static_constructor.ConstructorBuilder;
- if (filter (cb, criteria) == true)
- members.Add (cb);
+ if (cb != null)
+ if (filter (cb, criteria) == true)
+ members.Add (cb);
}
}
//
// Lookup members in parent if requested.
//
- if ((bf & BindingFlags.DeclaredOnly) == 0){
- MemberInfo [] mi;
-
- mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
- if (mi != null)
- members.AddRange (mi);
- }
-
- int count = members.Count;
- if (count > 0){
- MemberInfo [] mi = new MemberInfo [count];
- members.CopyTo (mi);
- return mi;
+ if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
+ if ((mt & ~MemberTypes.Constructor) != 0) {
+ MemberList list = FindMembers (TypeBuilder.BaseType, mt & ~MemberTypes.Constructor, bf, filter, criteria);
+ members.AddRange (list);
+ }
}
- return null;
- }
-
- public MemberInfo GetFieldFromEvent (EventExpr event_expr)
- {
- if (events == null)
- return null;
-
- EventInfo ei = event_expr.EventInfo;
+ Timer.StopTimer (TimerType.TcFindMembers);
- foreach (Event e in events) {
+ return new MemberList (members);
+ }
- if (e.FieldBuilder == null)
- continue;
-
- if (Type.FilterName (e.FieldBuilder, ei.Name))
- return e.FieldBuilder;
+ public override MemberCache MemberCache {
+ get {
+ return member_cache;
}
-
- return null;
}
- public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
- MemberFilter filter, object criteria)
+ public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
+ MemberFilter filter, object criteria)
{
TypeContainer tc = TypeManager.LookupTypeContainer (t);
if (tc != null)
return tc.FindMembers (mt, bf, filter, criteria);
else
- return t.FindMembers (mt, bf, filter, criteria);
+ return new MemberList (t.FindMembers (mt, bf, filter, criteria));
}
//
return null;
}
- /// <summary>
- /// Whether the specified method is an interface method implementation
- /// </summary>
- ///
- /// <remarks>
- /// If a method in Type `t' (or null to look in all interfaces
- /// and the base abstract class) with name `Name', return type `ret_type' and
- /// arguments `args' implements an interface, this method will
- /// return the MethodInfo that this method implements.
- ///
- /// This will remove the method from the list of "pending" methods
- /// that are required to be implemented for this class as a side effect.
- ///
- /// </remarks>
- public MethodInfo IsInterfaceMethod (Type t, string Name, Type ret_type, Type [] args,
- bool clear)
- {
- int arg_len = args.Length;
-
- if (pending_implementations == null)
- return null;
-
- foreach (TypeAndMethods tm in pending_implementations){
- if (!(t == null || tm.type == t))
- continue;
-
- int i = 0;
- foreach (MethodInfo m in tm.methods){
- if (m == null){
- i++;
- continue;
- }
-
- if (Name != m.Name){
- i++;
- continue;
- }
-
- if (ret_type != m.ReturnType){
- if (!((ret_type == null && m.ReturnType == TypeManager.void_type) ||
- (m.ReturnType == null && ret_type == TypeManager.void_type)))
- {
- i++;
- continue;
- }
- }
-
- //
- // Check if we have the same parameters
- //
- if (tm.args [i].Length != arg_len){
- i++;
- continue;
- }
-
- int j, top = args.Length;
- bool fail = false;
-
- for (j = 0; j < top; j++){
- if (tm.args [i][j] != args[j]){
- fail = true;
- break;
- }
- }
- if (fail){
- i++;
- continue;
- }
-
- if (clear)
- tm.methods [i] = null;
- tm.found [i] = true;
- return m;
- }
-
- // If a specific type was requested, we can stop now.
- if (tm.type == t)
- return null;
- }
- return null;
- }
-
- /// <summary>
- /// C# allows this kind of scenarios:
- /// interface I { void M (); }
- /// class X { public void M (); }
- /// class Y : X, I { }
- ///
- /// For that case, we create an explicit implementation function
- /// I.M in Y.
- /// </summary>
- void DefineProxy (Type iface, MethodInfo parent_method, MethodInfo iface_method,
- Type [] args)
- {
- MethodBuilder proxy;
-
- string proxy_name = iface.Name + "." + iface_method.Name;
-
- proxy = TypeBuilder.DefineMethod (
- proxy_name,
- MethodAttributes.HideBySig |
- MethodAttributes.NewSlot |
- MethodAttributes.Virtual,
- CallingConventions.Standard | CallingConventions.HasThis,
- parent_method.ReturnType, args);
-
- int top = args.Length;
- ILGenerator ig = proxy.GetILGenerator ();
-
- ig.Emit (OpCodes.Ldarg_0);
- for (int i = 0; i < top; i++){
- switch (i){
- case 0:
- ig.Emit (OpCodes.Ldarg_1); break;
- case 1:
- ig.Emit (OpCodes.Ldarg_2); break;
- case 2:
- ig.Emit (OpCodes.Ldarg_3); break;
- default:
- ig.Emit (OpCodes.Ldarg, i - 1); break;
- }
- }
- ig.Emit (OpCodes.Call, parent_method);
- ig.Emit (OpCodes.Ret);
-
- TypeBuilder.DefineMethodOverride (proxy, iface_method);
- }
-
- /// <summary>
- /// This function tells whether one of our parent classes implements
- /// the given method (which turns out, it is valid to have an interface
- /// implementation in a parent
- /// </summary>
- bool ParentImplements (Type iface_type, MethodInfo mi)
- {
- MethodSignature ms;
-
- Type [] args = TypeManager.GetArgumentTypes (mi);
- ms = new MethodSignature (mi.Name, mi.ReturnType, args);
- MemberInfo [] list = FindMembers (
- TypeBuilder.BaseType, MemberTypes.Method | MemberTypes.Property,
- BindingFlags.Public | BindingFlags.Instance,
- MethodSignature.method_signature_filter, ms);
-
- if (list == null || list.Length == 0)
- return false;
-
- DefineProxy (iface_type, (MethodInfo) list [0], mi, args);
- return true;
- }
-
- /// <summary>
- /// Verifies that any pending abstract methods or interface methods
- /// were implemented.
- /// </summary>
- bool VerifyPendingMethods ()
- {
- int top = pending_implementations.Length;
- bool errors = false;
- int i;
-
- for (i = 0; i < top; i++){
- Type type = pending_implementations [i].type;
- int j = 0;
-
- foreach (MethodInfo mi in pending_implementations [i].methods){
- if (mi == null)
- continue;
-
- if (type.IsInterface){
- if (ParentImplements (type, mi))
- continue;
-
- string extra = "";
-
- if (pending_implementations [i].found [j])
- extra = ". (method might be private or static)";
- Report.Error (
- 536, Location,
- "`" + Name + "' does not implement " +
- "interface member `" +
- type.FullName + "." + mi.Name + "'" + extra);
- } else {
- Report.Error (
- 534, Location,
- "`" + Name + "' does not implement " +
- "inherited abstract member `" +
- type.FullName + "." + mi.Name + "'");
- }
- errors = true;
- j++;
- }
- }
- return errors;
- }
-
/// <summary>
/// Emits the values for the constants
/// </summary>
foreach (Method m in methods)
m.Emit (this);
- if (operators != null)
- foreach (Operator o in operators)
- o.Emit (this);
-
if (properties != null)
foreach (Property p in properties)
p.Emit (this);
- if (indexers != null){
- foreach (Indexer ix in indexers)
- ix.Emit (this);
-
- CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
- this, IndexerName, ModFlags, Location);
+ if (this.DefaultPropName != null) {
+ CustomAttributeBuilder cb = new CustomAttributeBuilder (TypeManager.default_member_ctor, new string [] { DefaultPropName });
TypeBuilder.SetCustomAttribute (cb);
}
e.Emit (this);
}
- if (pending_implementations != null)
- if (!VerifyPendingMethods ())
+ if (Pending != null)
+ if (Pending.VerifyPendingMethods ())
return;
-
- Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
+ if (OptAttributes != null)
+ OptAttributes.Emit (ec, this);
+
//
// Check for internal or private fields that were never assigned
//
// foreach (TypeContainer tc in types)
// tc.Emit ();
}
-
+
public override void CloseType ()
{
try {
if (Delegates != null)
foreach (Delegate d in Delegates)
- d.CloseDelegate ();
+ d.CloseType ();
}
public string MakeName (string n)
return "`" + Name + "." + n + "'";
}
- public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
+ public void Warning_KeywordShadowsRequired (Location l, MemberInfo mi)
{
Report.Warning (
- 108, l, "The keyword new is required on " +
- MakeName (mi.Name) + " because it hides `" +
+ 108, l, "The keyword 'Shadows' is required on " +
+ MakeName (mi.Name) + " because it shadows `" +
mi.ReflectedType.Name + "." + mi.Name + "'");
}
+ public void Warning_KewywordShadowsNotRequired (Location l, MemberCore mc)
+ {
+ Report.Warning (
+ 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
+ "inherited member, the keyword shadows is not required");
+ }
+
public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
{
Report.Warning (
public bool MethodModifiersValid (int flags, string n, Location loc)
{
const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
- const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
+ const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
+ //const int nv = (Modifiers.SHADOWS | Modifiers.VIRTUAL);
bool ok = true;
string name = MakeName (n);
if ((flags & Modifiers.STATIC) != 0){
if ((flags & vao) != 0){
Report.Error (
- 112, loc, "static method " + name + "can not be marked " +
- "as virtual, abstract or override");
+ 30501, loc, "Shared method " + name + " can not be " +
+ "declared as Overridable");
+ ok = false;
+ }
+ }
+
+ if (this is Struct){
+ if ((flags & va) != 0){
+ Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
ok = false;
}
}
- if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
+ if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.VIRTUAL) != 0)
+ {
+ Report.Error (
+ 30730, loc, name +
+ ": Methods marked as Overrides cannot be made Overridable");
+ ok = false;
+ }
+
+ if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.SHADOWS) != 0){
Report.Error (
- 113, loc, name +
- " marked as override cannot be marked as new or virtual");
+ 31408, loc, name +
+ ": Methods marked as Overrides cannot be marked as Shadows");
ok = false;
}
ok = false;
}
- if ((ModFlags & Modifiers.ABSTRACT) == 0){
+ if((ModFlags & Modifiers.SEALED) != 0){
+ Report.Error (
+ 30607, loc,
+ "Class declared as 'NotInheritable' " +
+ "cannot have a 'MustOverride' member");
+ ok = false;
+ }
+ else if ((ModFlags & Modifiers.ABSTRACT) == 0){
Report.Error (
- 513, loc, name +
- " is abstract but its container class is not");
+ 31411, loc, name +
+ " is declared as 'MustOverride', hence its container " +
+ "class should be declared as 'MustInherit'");
ok = false;
}
if ((flags & Modifiers.PRIVATE) != 0){
if ((flags & vao) != 0){
Report.Error (
- 621, loc, name +
- " virtual or abstract members can not be private");
+ 31408, loc, name +
+ ": Members marked as Overridable or Overrides can not be Private");
ok = false;
}
}
if ((flags & Modifiers.OVERRIDE) == 0){
Report.Error (
238, loc, name +
- " cannot be sealed because it is not an override");
+ ": cannot be sealed because it is not an override");
+ ok = false;
+ }
+ }
+ if ((flags & Modifiers.NEW) != 0){
+ if ((flags & Modifiers.SHADOWS) != 0){
+ Report.Error (
+ 31408, loc,
+ " 'Overloads' and 'Shadows' cannot be combined ");
ok = false;
}
}
return ok;
}
+ // Access level of a type.
+ enum AccessLevel {
+ Public = 0,
+ ProtectedInternal = 1,
+ Internal = 2,
+ Protected = 3,
+ Private = 4
+ }
+
+ // Check whether `flags' denotes a more restricted access than `level'
+ // and return the new level.
+ static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
+ {
+ //AccessLevel old_level = level;
+
+ if ((flags & Modifiers.INTERNAL) != 0) {
+ if ((flags & Modifiers.PROTECTED) != 0) {
+ if ((int) level < (int) AccessLevel.ProtectedInternal)
+ level = AccessLevel.ProtectedInternal;
+ } else {
+ if ((int) level < (int) AccessLevel.Internal)
+ level = AccessLevel.Internal;
+ }
+ } else if ((flags & Modifiers.PROTECTED) != 0) {
+ if ((int) level < (int) AccessLevel.Protected)
+ level = AccessLevel.Protected;
+ } else if ((flags & Modifiers.PRIVATE) != 0)
+ level = AccessLevel.Private;
+
+ return level;
+ }
+
+ // Return the access level for a new member which is defined in the current
+ // TypeContainer with access modifiers `flags'.
+ AccessLevel GetAccessLevel (int flags)
+ {
+ if ((flags & Modifiers.PRIVATE) != 0)
+ return AccessLevel.Private;
+
+ AccessLevel level;
+ if (!IsTopLevel && (Parent != null))
+ level = Parent.GetAccessLevel (flags);
+ else
+ level = AccessLevel.Public;
+
+ return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
+ }
+
+ // Return the access level for type `t', but don't give more access than `flags'.
+ static AccessLevel GetAccessLevel (Type t, int flags)
+ {
+ if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
+ return AccessLevel.Private;
+
+ AccessLevel level;
+ if (TypeManager.IsBuiltinType (t))
+ return AccessLevel.Public;
+ else if ((t.DeclaringType != null) && (t != t.DeclaringType))
+ level = GetAccessLevel (t.DeclaringType, flags);
+ else {
+ level = CheckAccessLevel (AccessLevel.Public, flags);
+ }
+
+ if (t.IsNestedPublic)
+ return level;
+
+ if (t.IsNestedAssembly || t.IsNotPublic) {
+ if ((int) level < (int) AccessLevel.Internal)
+ level = AccessLevel.Internal;
+ }
+
+ if (t.IsNestedFamily) {
+ if ((int) level < (int) AccessLevel.Protected)
+ level = AccessLevel.Protected;
+ }
+
+ if (t.IsNestedFamORAssem) {
+ if ((int) level < (int) AccessLevel.ProtectedInternal)
+ level = AccessLevel.ProtectedInternal;
+ }
+
+ return level;
+ }
+
//
- // Returns true if `type' is as accessible as the flags `flags'
- // given for this member
+ // Returns true if `parent' is as accessible as the flags `flags'
+ // given for this member.
//
- static public bool AsAccessible (Type type, int flags)
+ public bool AsAccessible (Type parent, int flags)
{
- return true;
+ while (parent.IsArray || parent.IsPointer || parent.IsByRef)
+ parent = parent.GetElementType ();
+
+ AccessLevel level = GetAccessLevel (flags);
+ AccessLevel level2 = GetAccessLevel (parent, flags);
+
+ return (int) level >= (int) level2;
}
Hashtable builder_and_args;
builder_and_args = new Hashtable ();
return true;
}
- }
-
- public class Class : TypeContainer {
- // <summary>
- // Modifiers allowed in a class declaration
- // </summary>
- public const int AllowedModifiers =
- Modifiers.NEW |
- Modifiers.PUBLIC |
- Modifiers.PROTECTED |
- Modifiers.INTERNAL |
- Modifiers.PRIVATE |
- Modifiers.ABSTRACT |
- Modifiers.SEALED |
- Modifiers.UNSAFE;
- public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
- : base (parent, name, l)
+ /// <summary>
+ /// Performs checks for an explicit interface implementation. First it
+ /// checks whether the `interface_type' is a base inteface implementation.
+ /// Then it checks whether `name' exists in the interface type.
+ /// </summary>
+ public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
{
- int accmods;
+ bool found = false;
- if (parent.Parent == null)
- accmods = Modifiers.INTERNAL;
+ if (ifaces != null){
+ foreach (Type t in ifaces){
+ if (t == interface_type){
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found){
+ Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
+ return false;
+ }
+
+ return true;
+ }
+
+ public static void Error_NotInterfaceMember (Location loc, string member_name, string iface_name)
+ {
+ Report.Error (30401, loc, "'" + member_name + "' is not a member of the interface '" + iface_name + "'");
+ }
+
+ //
+ // IMemberContainer
+ //
+
+ string IMemberContainer.Name {
+ get {
+ return Name;
+ }
+ }
+
+ Type IMemberContainer.Type {
+ get {
+ return TypeBuilder;
+ }
+ }
+
+ IMemberContainer IMemberContainer.Parent {
+ get {
+ return parent_container;
+ }
+ }
+
+ MemberCache IMemberContainer.MemberCache {
+ get {
+ return member_cache;
+ }
+ }
+
+ bool IMemberContainer.IsInterface {
+ get {
+ return this is Interface;
+ }
+ }
+
+ MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
+ {
+ return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
+ }
+
+ }
+
+ public class Class : TypeContainer {
+ // <summary>
+ // Modifiers allowed in a class declaration
+ // </summary>
+ public const int AllowedModifiers =
+ Modifiers.NEW |
+ Modifiers.PUBLIC |
+ Modifiers.PROTECTED |
+ Modifiers.INTERNAL |
+ Modifiers.PRIVATE |
+ Modifiers.ABSTRACT |
+ Modifiers.SEALED ;
+
+ public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
+ : base (parent, name, attrs, l)
+ {
+ int accmods;
+
+ if (parent.Parent == null)
+ accmods = Modifiers.INTERNAL;
else
- accmods = Modifiers.PRIVATE;
+ accmods = Modifiers.PUBLIC;
this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
- this.attributes = attrs;
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Class;
+ }
+ }
+
+ public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.UsageAttribute != null) {
+ if (base_class_type != TypeManager.attribute_type && !base_class_type.IsSubclassOf (TypeManager.attribute_type) &&
+ TypeBuilder.FullName != "System.Attribute") {
+ Report.Error (641, a.Location, "Attribute '" + a.Name + "' is only valid on classes derived from System.Attribute");
+ }
+ AttributeUsage = a.UsageAttribute;
+ }
+ base.ApplyAttributeBuilder (a, cb);
}
//
Modifiers.PRIVATE;
public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
- : base (parent, name, l)
+ : base (parent, name, attrs, l)
{
int accmods;
if (parent.Parent == null)
accmods = Modifiers.INTERNAL;
else
- accmods = Modifiers.PRIVATE;
+ accmods = Modifiers.PUBLIC;
this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
this.ModFlags |= Modifiers.SEALED;
- this.attributes = attrs;
-
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Struct;
+ }
}
//
}
}
- public abstract class MethodCore : MemberCore {
- public readonly Parameters Parameters;
+ public abstract class MethodCore : MemberBase {
+ public /* readonly */ Parameters Parameters;
Block block;
//
// Parameters, cached for semantic analysis.
//
- InternalParameters parameter_info;
-
- public MethodCore (string name, Parameters parameters, Location l)
- : base (name, l)
+ protected InternalParameters parameter_info;
+ protected Type [] parameter_types;
+
+ // Whether this is an operator
+ public bool IsOperator;
+
+ public MethodCore (Expression type, int mod, int allowed_mod, string name,
+ Attributes attrs, Parameters parameters, Location loc)
+ : base (type, mod, allowed_mod, name, attrs, loc)
{
- Name = name;
Parameters = parameters;
}
//
// Returns the System.Type array for the parameters of this method
//
- Type [] parameter_types;
- public Type [] ParameterTypes (TypeContainer parent)
- {
- if (Parameters == null)
- return TypeManager.NoTypes;
-
- if (parameter_types == null)
- parameter_types = Parameters.GetParameterInfo (parent);
-
- return parameter_types;
+ public Type [] ParameterTypes {
+ get {
+ return parameter_types;
+ }
}
public InternalParameters ParameterInfo
get {
return parameter_info;
}
-
- set {
- parameter_info = value;
- }
}
public Block Block {
}
}
+ protected virtual bool DoDefineParameters (TypeContainer parent)
+ {
+ // Check if arguments were correct
+ parameter_types = Parameters.GetParameterInfo (parent);
+ if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
+ return false;
+
+ parameter_info = new InternalParameters (parent, Parameters);
+
+ return true;
+ }
+
public CallingConventions GetCallingConvention (bool is_class)
{
CallingConventions cc = 0;
return cc;
}
-
- public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
- {
- //
- // Define each type attribute (in/out/ref) and
- // the argument names.
- //
- Parameter [] p = Parameters.FixedParameters;
- int i = 0;
-
- MethodBuilder mb = null;
- ConstructorBuilder cb = null;
-
- if (builder is MethodBuilder)
- mb = (MethodBuilder) builder;
- else
- cb = (ConstructorBuilder) builder;
-
- if (p != null){
- for (i = 0; i < p.Length; i++) {
- ParameterBuilder pb;
-
- if (mb == null)
- pb = cb.DefineParameter (
- i + 1, p [i].Attributes, p [i].Name);
- else
- pb = mb.DefineParameter (
- i + 1, p [i].Attributes, p [i].Name);
-
- Attributes attr = p [i].OptAttributes;
- if (attr != null)
- Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
- }
- }
-
- if (Parameters.ArrayParameter != null){
- ParameterBuilder pb;
- Parameter array_param = Parameters.ArrayParameter;
-
- if (mb == null)
- pb = cb.DefineParameter (
- i + 1, array_param.Attributes,
- array_param.Name);
- else
- pb = mb.DefineParameter (
- i + 1, array_param.Attributes,
- array_param.Name);
-
- CustomAttributeBuilder a = new CustomAttributeBuilder (
- TypeManager.cons_param_array_attribute, new object [0]);
-
- pb.SetCustomAttribute (a);
- }
- }
}
public class Method : MethodCore {
- public readonly string ReturnType;
public MethodBuilder MethodBuilder;
- public readonly Attributes OptAttributes;
-
- MethodAttributes flags;
+ public MethodData MethodData;
/// <summary>
/// Modifiers allowed in a class declaration
Modifiers.PRIVATE |
Modifiers.STATIC |
Modifiers.VIRTUAL |
- Modifiers.SEALED |
+ Modifiers.NONVIRTUAL |
Modifiers.OVERRIDE |
Modifiers.ABSTRACT |
- Modifiers.UNSAFE |
- Modifiers.EXTERN;
+ Modifiers.UNSAFE |
+ Modifiers.EXTERN|
+ Modifiers.SHADOWS;
//
// return_type can be "null" for VOID values.
//
- public Method (string return_type, int mod, string name, Parameters parameters,
+ public Method (Expression return_type, int mod, string name, Parameters parameters,
Attributes attrs, Location l)
- : base (name, parameters, l)
- {
- ReturnType = return_type;
- ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, l);
- OptAttributes = attrs;
+ : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
+ {
+ Implements = null;
}
+ public Method (Expression return_type, int mod, string name, Parameters parameters,
+ Attributes attrs, ArrayList impl_what, Location l)
+ : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
+ {
+ Implements = impl_what;
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Method;
+ }
+ }
+
//
// Returns the `System.Type' for the ReturnType of this
// function. Provides a nice cache. (used between semantic analysis
// and actual code generation
//
- Type type_return_type;
-
- public Type GetReturnType (TypeContainer parent)
+ public Type GetReturnType ()
{
- if (type_return_type == null)
- type_return_type = RootContext.LookupType (
- parent, ReturnType, false, Location);
-
- return type_return_type;
+ return MemberType;
}
- void DuplicateEntryPoint (MethodInfo b, Location location)
- {
- Report.Error (
- 17, location,
- "Program `" + CodeGen.FileName +
- "' has more than one entry point defined: `" +
- TypeManager.CSharpSignature(b) + "'");
- }
+ void DuplicateEntryPoint (MethodInfo b, Location location)
+ {
+ Report.Error (
+ 30738, location,
+ "Program `" + CodeGen.FileName +
+ "' has more than one entry point defined: `" +
+ TypeManager.MonoBASIC_Signature(b) + "'");
+ }
- void Report28 (MethodInfo b)
- {
+ void Report28 (MethodInfo b)
+ {
if (RootContext.WarningLevel < 4)
return;
- Report.Warning (
- 28, Location,
- "`" + TypeManager.CSharpSignature(b) +
- "' has the wrong signature to be an entry point");
- }
-
- public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
- {
- if (b.ReturnType != TypeManager.void_type &&
- b.ReturnType != TypeManager.int32_type)
- return false;
-
- if (pinfo.Count == 0)
- return true;
-
- if (pinfo.Count > 1)
- return false;
-
- Type t = pinfo.ParameterType(0);
- if (t.IsArray &&
- (t.GetArrayRank() == 1) &&
- (t.GetElementType() == TypeManager.string_type) &&
- (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
- return true;
- else
- return false;
- }
+ Report.Warning (
+ 28, Location,
+ "`" + TypeManager.MonoBASIC_Signature(b) +
+ "' has the wrong signature to be an entry point");
+ }
+
+ public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
+ {
+ if (b.ReturnType != TypeManager.void_type &&
+ b.ReturnType != TypeManager.int32_type)
+ return false;
+
+ if (pinfo.Count == 0)
+ return true;
+
+ if (pinfo.Count > 1)
+ return false;
+
+ Type t = pinfo.ParameterType(0);
+ if (t.IsArray &&
+ (t.GetArrayRank() == 1) &&
+ (t.GetElementType() == TypeManager.string_type) &&
+ (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
+ return true;
+ else
+ return false;
+ }
//
- // Creates the type
+ // Checks our base implementation if any
//
- public override bool Define (TypeContainer parent)
+ protected override bool CheckBase (TypeContainer parent)
{
- Type ret_type = GetReturnType (parent);
- Type [] parameters = ParameterTypes (parent);
- bool error = false;
- MethodInfo implementing;
- Type iface_type = null;
- string iface = "", short_name;
- bool explicit_impl = false;
-
- // Check if the return type and arguments were correct
- if (ret_type == null || parameters == null)
- return false;
-
- if (!parent.MethodModifiersValid (ModFlags, Name, Location))
+ // Check whether arguments were correct.
+ if (!DoDefineParameters (parent))
return false;
- flags = Modifiers.MethodAttr (ModFlags);
+ MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
+ if (!IsOperator) {
+ MemberList mi_this;
- //
- // verify accessibility
- //
- if (!TypeContainer.AsAccessible (ret_type, ModFlags))
- return false;
+ mi_this = TypeContainer.FindMembers (
+ parent.TypeBuilder, MemberTypes.Method,
+ BindingFlags.NonPublic | BindingFlags.Public |
+ BindingFlags.Static | BindingFlags.Instance |
+ BindingFlags.DeclaredOnly,
+ MethodSignature.method_signature_filter, ms);
- if (ret_type.IsPointer && !UnsafeOK (parent))
- return false;
-
- foreach (Type partype in parameters){
- if (!TypeContainer.AsAccessible (partype, ModFlags))
- error = true;
- if (partype.IsPointer && !UnsafeOK (parent))
- error = true;
+ if (mi_this.Count > 0) {
+ Report.Error (111, Location, "Class `" + parent.Name + "' " +
+ "already defines a member called `" + Name + "' " +
+ "with the same parameter types");
+ return false;
+ }
}
- if (error)
- return false;
-
//
// Verify if the parent has a type with the same name, and then
// check whether we have to create a new slot for it or not.
// ptype is only null for System.Object while compiling corlib.
if (ptype != null){
- MethodSignature ms = new MethodSignature (Name, null, parameters);
- MemberInfo [] mi, mi_static, mi_instance;
+ MemberList mi, mi_static, mi_instance;
mi_static = TypeContainer.FindMembers (
ptype, MemberTypes.Method,
MethodSignature.inheritable_method_signature_filter,
ms);
- if (mi_instance != null && mi_instance.Length > 0){
+ if (mi_instance.Count > 0){
mi = mi_instance;
- } else if (mi_static != null && mi_static.Length > 0)
+ } else if (mi_static.Count > 0)
mi = mi_static;
else
mi = null;
- if (mi != null && mi.Length > 0){
- if (!CheckMethodAgainstBase (parent, flags, (MethodInfo) mi [0])){
+ if (mi != null && mi.Count > 0){
+ parent_method = (MethodInfo) mi [0];
+ string name = parent_method.DeclaringType.Name + "." +
+ parent_method.Name;
+
+ if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
return false;
+
+ if ((ModFlags & Modifiers.NEW) == 0) {
+ Type parent_ret = TypeManager.TypeToCoreType (
+ parent_method.ReturnType);
+
+ if (parent_ret != MemberType) {
+ Report.Error (
+ 508, parent.MakeName (Name) + ": cannot " +
+ "change return type when overriding " +
+ "inherited member " + name);
+ return false;
+ }
}
} else {
- if ((ModFlags & Modifiers.NEW) != 0)
- WarningNotHiding (parent);
+ /*if ((ModFlags & Modifiers.NEW) != 0)
+ WarningNotHiding (parent);*/
if ((ModFlags & Modifiers.OVERRIDE) != 0){
- Report.Error (115, Location,
+ Report.Error (30284, Location,
parent.MakeName (Name) +
- " no suitable methods found to override");
+ " : No suitable methods found to override");
+ }
+ if ((ModFlags & ( Modifiers.NEW | Modifiers.SHADOWS | Modifiers.OVERRIDE )) == 0)
+ {
+ if ((ModFlags & Modifiers.NONVIRTUAL) != 0)
+ {
+ Report.Error (31088, Location,
+ parent.MakeName (Name) + " : Cannot " +
+ "be declared NotOverridable since this method is " +
+ "not maked as Overrides");
+ }
}
+ // if a member of module is not inherited from Object class
+ // can not be declared protected
+ if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
+ Report.Error (31066, Location,
+ "'Sub' or 'Function' inside a 'Module' can not be declared as " +
+ "'Protected' or 'Protected Friend'");
}
- } else if ((ModFlags & Modifiers.NEW) != 0)
+ }
+ /* else if ((ModFlags & Modifiers.NEW) != 0)
WarningNotHiding (parent);
+ */
- //
- // If we implement an interface, extract the interface name.
- //
+ return true;
+ }
- if (Name.IndexOf (".") != -1){
- int pos = Name.LastIndexOf (".");
- iface = Name.Substring (0, pos);
+ //
+ // Creates the type
+ //
+ public override bool Define (TypeContainer parent)
+ {
+ if (!DoDefine (parent))
+ return false;
- iface_type = RootContext.LookupType (parent, iface, false, Location);
- short_name = Name.Substring (pos + 1);
+ if (!CheckBase (parent))
+ return false;
- if (iface_type == null)
- return false;
+ if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
+ Report.Error (31067, Location,
+ "'Sub' or 'Function' inside a 'Structure' can not be declared as " +
+ "'Protected' or 'Protected Friend'");
- // Compute the full name that we need to export
- Name = iface_type.FullName + "." + short_name;
- explicit_impl = true;
- } else
- short_name = Name;
+ CallingConventions cc = GetCallingConvention (parent is Class);
- //
- // Check if we are an implementation of an interface method or
- // a method
- //
- implementing = parent.IsInterfaceMethod (
- iface_type, short_name, ret_type, parameters, false);
-
- //
- // For implicit implementations, make sure we are public, for
- // explicit implementations, make sure we are private.
- //
- if (implementing != null){
- //
- // Setting null inside this block will trigger a more
- // verbose error reporting for missing interface implementations
- //
- // The "candidate" function has been flagged already
- // but it wont get cleared
- //
- if (iface_type == null){
- //
- // We already catch different accessibility settings
- // so we just need to check that we are not private
- //
- if ((ModFlags & Modifiers.PRIVATE) != 0)
- implementing = null;
+ MethodData = new MethodData (this, null, MemberType, ParameterTypes,
+ ParameterInfo, cc, OptAttributes,
+ ModFlags, flags, true);
- //
- // Static is not allowed
- //
- if ((ModFlags & Modifiers.STATIC) != 0)
- implementing = null;
- } else {
- if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
- Report.Error (
- 106, Location, "`public' or `abstract' modifiers "+
- "are not allowed in explicit interface declarations"
- );
- implementing = null;
- }
- }
- }
+ if (!MethodData.Define (parent))
+ return false;
+
+ MethodBuilder = MethodData.MethodBuilder;
//
- // If implementing is still valid, set flags
+ // This is used to track the Entry Point,
//
- if (implementing != null){
- if (implementing.DeclaringType.IsInterface)
- flags |= MethodAttributes.NewSlot;
-
- flags |=
- MethodAttributes.Virtual |
- MethodAttributes.HideBySig;
-
- //
- // clear the flag
- //
- parent.IsInterfaceMethod (
- iface_type, short_name, ret_type, parameters, true);
- }
-
- Attribute dllimport_attr = null;
- if (OptAttributes != null && OptAttributes.AttributeSections != null) {
- foreach (AttributeSection asec in OptAttributes.AttributeSections) {
- if (asec.Attributes == null)
- continue;
-
- foreach (Attribute a in asec.Attributes)
- if (a.Name.IndexOf ("DllImport") != -1) {
- flags |= MethodAttributes.PinvokeImpl;
- dllimport_attr = a;
- }
- }
- }
-
- //
- // Finally, define the method
- //
-
- if ((flags & MethodAttributes.PinvokeImpl) != 0) {
-
- if ((ModFlags & Modifiers.STATIC) == 0) {
- Report.Error (601, Location, "The DllImport attribute must be specified on " +
- "a method marked 'static' and 'extern'.");
- return false;
- }
-
- EmitContext ec = new EmitContext (
- parent, Location, null, GetReturnType (parent), ModFlags);
-
- MethodBuilder = dllimport_attr.DefinePInvokeMethod (
- ec, parent.TypeBuilder,
- Name, flags, ret_type, parameters);
- } else {
- MethodBuilder = parent.TypeBuilder.DefineMethod (
- Name, flags,
- GetCallingConvention (parent is Class),
- ret_type, parameters);
-
- if (implementing != null && explicit_impl)
- parent.TypeBuilder.DefineMethodOverride (
- MethodBuilder, implementing);
- }
-
- if (MethodBuilder == null)
- return false;
-
- //
- // HACK because System.Reflection.Emit is lame
- //
- ParameterInfo = new InternalParameters (parent, Parameters);
-
- if (!TypeManager.RegisterMethod (MethodBuilder, ParameterInfo,
- parameters)) {
- Report.Error (
- 111, Location,
- "Class `" + parent.Name + "' already contains a definition with " +
- " the same return value and parameter types for method `" +
- Name + "'");
- return false;
- }
-
- //
- // This is used to track the Entry Point,
- //
- if (Name == "Main" &&
- ((ModFlags & Modifiers.STATIC) != 0) &&
- (RootContext.MainClass == null ||
- RootContext.MainClass == parent.TypeBuilder.FullName)){
- if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
- if (RootContext.EntryPoint == null) {
- RootContext.EntryPoint = MethodBuilder;
- RootContext.EntryPointLocation = Location;
- } else {
- DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
- DuplicateEntryPoint (MethodBuilder, Location);
- }
- } else
- Report28(MethodBuilder);
+ if (Name.ToUpper() == "MAIN" &&
+ ((ModFlags & Modifiers.STATIC) != 0) &&
+ (RootContext.MainClass == null ||
+ RootContext.MainClass == parent.TypeBuilder.FullName ||
+ (RootContext.RootNamespace != null &&
+ RootContext.RootNamespace.Length > 0 &&
+ (RootContext.RootNamespace + "." + RootContext.MainClass) == parent.TypeBuilder.FullName))) {
+ if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
+ if (RootContext.EntryPoint == null) {
+ RootContext.EntryPoint = MethodBuilder;
+ RootContext.EntryPointLocation = Location;
+ } else {
+ DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
+ DuplicateEntryPoint (MethodBuilder, Location);
+ }
+ } else
+ Report28(MethodBuilder);
}
return true;
//
public void Emit (TypeContainer parent)
{
- ILGenerator ig;
- EmitContext ec;
-
- if ((flags & MethodAttributes.PinvokeImpl) == 0)
- ig = MethodBuilder.GetILGenerator ();
- else
- ig = null;
-
- ec = new EmitContext (parent, Location, ig, GetReturnType (parent), ModFlags);
-
- if (OptAttributes != null)
- Attribute.ApplyAttributes (ec, MethodBuilder, this, OptAttributes, Location);
-
-
- LabelParameters (ec, ParameterTypes (parent), MethodBuilder);
-
- //
- // abstract or extern methods have no bodies
- //
- if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
- if (Block != null){
- if ((ModFlags & Modifiers.ABSTRACT) != 0){
- Report.Error (
- 500, "Abstract method `" +
- TypeManager.CSharpSignature (MethodBuilder) +
- "' can not have a body");
- }
- }
- return;
- }
-
- //
- // Handle destructors specially
- //
- // FIXME: This code generates buggy code
- //
- if (Name == "Finalize" && type_return_type == TypeManager.void_type)
- EmitDestructor (ec);
- else {
- ISymbolWriter sw = CodeGen.SymbolWriter;
-
- if ((sw != null) && (!Location.IsNull (Location))) {
- MethodToken token = MethodBuilder.GetToken ();
- sw.OpenMethod (new SymbolToken (token.Token));
- sw.SetMethodSourceRange (Location.SymbolDocument,
- Location.Row, 0,
- Block.EndLocation.SymbolDocument,
- Block.EndLocation.Row, 0);
-
- ec.EmitTopBlock (Block, Location);
-
- sw.CloseMethod ();
- } else
- ec.EmitTopBlock (Block, Location);
- }
+ MethodData.Emit (parent, Block, this);
}
- void EmitDestructor (EmitContext ec)
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
{
- ILGenerator ig = ec.ig;
-
- Label finish = ig.DefineLabel ();
- bool old_in_try = ec.InTry;
- Expression member_lookup;
-
- ig.BeginExceptionBlock ();
- ec.InTry = true;
- ec.ReturnLabel = finish;
- ec.EmitTopBlock (Block, Location);
- ec.InTry = old_in_try;
-
- ig.MarkLabel (finish);
- bool old_in_finally = ec.InFinally;
- ec.InFinally = true;
- ig.BeginFinallyBlock ();
-
- member_lookup = Expression.MemberLookup (
- ec, ec.ContainerType.BaseType, "Finalize",
- MemberTypes.Method, Expression.AllBindingFlags, Location);
-
- if (member_lookup != null){
- MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
-
- ig.Emit (OpCodes.Ldarg_0);
- ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
- }
- ec.InFinally = old_in_finally;
-
- ig.EndExceptionBlock ();
- //ig.MarkLabel (ec.ReturnLabel);
- ig.Emit (OpCodes.Ret);
+ throw new Exception ("FIXME: I am just a placeholder implementation");
}
}
public abstract class ConstructorInitializer {
ArrayList argument_list;
ConstructorInfo parent_constructor;
- Location location;
+ Parameters parameters;
+ Location loc;
+ public bool implicit_initialization;
- public ConstructorInitializer (ArrayList argument_list, Location location)
+ public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
+ Location loc)
{
this.argument_list = argument_list;
- this.location = location;
+ this.parameters = parameters;
+ this.loc = loc;
+ this.implicit_initialization = false;
}
public ArrayList Arguments {
}
}
+ public ConstructorInfo ParentConstructor
+ {
+ get
+ {
+ return parent_constructor;
+ }
+ }
+
public bool Resolve (EmitContext ec)
{
Expression parent_constructor_group;
Type t;
-
+
+ ec.CurrentBlock = new Block (null, true, parameters);
+
if (argument_list != null){
foreach (Argument a in argument_list){
- if (!a.Resolve (ec, location))
+ if (!a.Resolve (ec, loc))
return false;
}
}
- if (this is ConstructorBaseInitializer)
+ ec.CurrentBlock = null;
+
+ if (this is ConstructorBaseInitializer) {
+ if (ec.ContainerType.BaseType == null)
+ return true;
+
t = ec.ContainerType.BaseType;
+ if (ec.ContainerType.IsValueType){
+ Report.Error (522, loc,
+ "structs cannot call base class constructors");
+ return false;
+ }
+ }
else
t = ec.ContainerType;
parent_constructor_group = Expression.MemberLookup (
- ec, t, ".ctor",
+ ec, t, t, ".ctor",
MemberTypes.Constructor,
BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
- location);
+ loc);
if (parent_constructor_group == null){
- Report.Error (1501, location,
- "Can not find a constructor for this argument list");
+ Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" );
return false;
}
-
+
parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
- (MethodGroupExpr) parent_constructor_group, argument_list, location);
-
- if (parent_constructor == null){
- Report.Error (1501, location,
- "Can not find a constructor for this argument list");
+ (MethodGroupExpr) parent_constructor_group, argument_list, loc);
+
+ if (parent_constructor == null) {
+ if (this.implicit_initialization)
+ Report.Error (30148, loc, "Must declare 'MyBase.New' in the constructor " +
+ "of the class '" + ec.TypeContainer.Name + "' with appropriate arguments, since the base class '" +
+ t.FullName + "' does not contain a definition of 'New' without any parameter");
+ else
+ Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" );
+
return false;
}
-
+
return true;
}
public void Emit (EmitContext ec)
{
- ec.ig.Emit (OpCodes.Ldarg_0);
- if (argument_list != null)
- Invocation.EmitArguments (ec, null, argument_list);
- ec.ig.Emit (OpCodes.Call, parent_constructor);
+ if (parent_constructor != null){
+ if (ec.IsStatic)
+ Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
+ else
+ Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
+ }
}
+
+
}
public class ConstructorBaseInitializer : ConstructorInitializer {
- public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
+ public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
+ base (argument_list, pars, l)
{
}
}
public class ConstructorThisInitializer : ConstructorInitializer {
- public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
+ public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
+ base (argument_list, pars, l)
{
}
}
public class Constructor : MethodCore {
public ConstructorBuilder ConstructorBuilder;
public ConstructorInitializer Initializer;
- public Attributes OptAttributes;
// <summary>
// Modifiers allowed for a constructor.
// </summary>
- const int AllowedModifiers =
+ public const int AllowedModifiers =
Modifiers.PUBLIC |
Modifiers.PROTECTED |
Modifiers.INTERNAL |
Modifiers.STATIC |
Modifiers.UNSAFE |
+ Modifiers.EXTERN |
Modifiers.PRIVATE;
//
// my very own code has static constructors.
//
public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
- : base (name, args, l)
+ : base (null, 0, AllowedModifiers, name, null, args, l)
{
Initializer = init;
}
+ public Constructor (string name, int mod, Parameters args, ConstructorInitializer init, Location l)
+ : base (null, mod, AllowedModifiers, name, null, args, l)
+ {
+ Initializer = init;
+ }
+
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ {
+ ConstructorBuilder.SetCustomAttribute (cb);
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Constructor;
+ }
+ }
+
//
// Returns true if this is a default constructor
//
MethodAttributes ca = (MethodAttributes.RTSpecialName |
MethodAttributes.SpecialName);
- Type [] parameters = ParameterTypes (parent);
+ if (parent.EventHandlers != null) {
+ ArrayList hdlrs = parent.EventHandlers;
+ foreach(Statement stmt in hdlrs)
+ this.Block.AddStatement (stmt);
+ }
+
- if (parameters == null)
+ // Check if arguments were correct.
+ if (!DoDefineParameters (parent))
return false;
-
- if ((ModFlags & Modifiers.STATIC) != 0)
+
+ if ((ModFlags & Modifiers.STATIC) != 0) {
ca |= MethodAttributes.Static;
+
+ if (this.Parameters != Parameters.EmptyReadOnlyParameters)
+ Report.Error (
+ 30479, Location,
+ "Shared constructor can not have parameters");
+
+ if ((ModFlags & Modifiers.Accessibility) != 0)
+ Report.Error (
+ 30480, Location,
+ "Shared constructor can not be declared " +
+ "explicitly as public, private, friend or protected");
+
+ if (this.Initializer != null)
+ Report.Error (
+ 30043, Location,
+ "Keywords like MyBase, MyClass, Me are not " +
+ "valid inside a Shared Constructor");
+ }
else {
- if (parent is Struct && parameters.Length == 0){
+ if (parent is Struct && ParameterTypes.Length == 0) {
Report.Error (
- 568, Location,
+ 30629, Location,
"Structs can not contain explicit parameterless " +
"constructors");
return false;
}
- ca |= MethodAttributes.Public | MethodAttributes.HideBySig;
- }
+ ca |= MethodAttributes.HideBySig;
- foreach (Type partype in parameters)
- if (!TypeContainer.AsAccessible (partype, ModFlags))
- return false;
+ if ((ModFlags & Modifiers.PUBLIC) != 0)
+ ca |= MethodAttributes.Public;
+ else if ((ModFlags & Modifiers.PROTECTED) != 0) {
+ if ((ModFlags & Modifiers.INTERNAL) != 0)
+ ca |= MethodAttributes.FamORAssem;
+ else
+ ca |= MethodAttributes.Family;
+ }
+ else if ((ModFlags & Modifiers.INTERNAL) != 0)
+ ca |= MethodAttributes.Assembly;
+ else if (IsDefault ())
+ ca |= MethodAttributes.Public;
+ else
+ ca |= MethodAttributes.Private;
+ }
ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
- ca, GetCallingConvention (parent is Class), parameters);
+ ca, GetCallingConvention (parent is Class), ParameterTypes);
//
// HACK because System.Reflection.Emit is lame
//
- ParameterInfo = new InternalParameters (parent, Parameters);
-
- if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, parameters)) {
+ if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
Report.Error (
111, Location,
"Class `" +parent.Name+ "' already contains a definition with the " +
ILGenerator ig = ConstructorBuilder.GetILGenerator ();
EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
- if (parent is Class && ((ModFlags & Modifiers.STATIC) == 0)){
- if (Initializer == null)
- Initializer = new ConstructorBaseInitializer (null, parent.Location);
-
+ if ((ModFlags & Modifiers.STATIC) == 0){
+ if (parent is Class && Initializer == null) {
+ Initializer = new ConstructorBaseInitializer (
+ null, Parameters.EmptyReadOnlyParameters, parent.Location);
+ Initializer.implicit_initialization = true;
+ }
//
// Spec mandates that Initializers will not have
// `this' access
//
ec.IsStatic = true;
- if (!Initializer.Resolve (ec))
+ if (Initializer != null && !Initializer.Resolve (ec))
return;
ec.IsStatic = false;
}
- LabelParameters (ec, ParameterTypes (parent), ConstructorBuilder);
+ Parameters.LabelParameters (ec, ConstructorBuilder, Location);
//
// Classes can have base initializers and instance field initializers.
//
if (parent is Class){
- if ((ModFlags & Modifiers.STATIC) == 0){
+ if ((ModFlags & Modifiers.STATIC) == 0)
parent.EmitFieldInitializers (ec);
+ }
- Initializer.Emit (ec);
- }
+ if (Initializer != null) {
+ if (this.ConstructorBuilder.Equals (Initializer.ParentConstructor))
+ Report.Error (
+ 30297, Location,
+ "A constructor can not call itself" );
+
+ Initializer.Emit (ec);
}
if ((ModFlags & Modifiers.STATIC) != 0)
parent.EmitFieldInitializers (ec);
- Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
+ if (OptAttributes != null)
+ OptAttributes.Emit (ec, this);
+
+ // If this is a non-static `struct' constructor and doesn't have any
+ // initializer, it must initialize all of the struct's fields.
+ if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
+ (Initializer == null))
+ Block.AddThisVariable (parent, Location);
- ec.EmitTopBlock (Block, Location);
+ ec.EmitTopBlock (Block, ParameterInfo, Location);
}
}
- //
- // Fields and Events both generate FieldBuilders, we use this to share
- // their common bits. This is also used to flag usage of the field
- //
- abstract public class FieldBase : MemberCore {
- public readonly string Type;
- public readonly Object Initializer;
+ public class MethodData {
+ //
+ // The return type of this method
+ //
+ public readonly Type ReturnType;
+ public readonly Type[] ParameterTypes;
+ public readonly InternalParameters ParameterInfo;
+ public readonly CallingConventions CallingConventions;
public readonly Attributes OptAttributes;
- public FieldBuilder FieldBuilder;
- public Status status;
-
- [Flags]
- public enum Status : byte { ASSIGNED = 1, USED = 2 }
+ public readonly Location Location;
//
- // The constructor is only exposed to our children
+ // Are we implementing an interface ?
//
- protected FieldBase (string type, int mod, int allowed_mod, string name,
- object init, Attributes attrs, Location loc)
- : base (name, loc)
- {
- Type = type;
- ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
- Initializer = init;
- OptAttributes = attrs;
- }
- }
+ public bool IsImplementing = false;
- //
- // The Field class is used to represents class/struct fields during parsing.
- //
- public class Field : FieldBase {
- // <summary>
- // Modifiers allowed in a class declaration
- // </summary>
- const int AllowedModifiers =
- Modifiers.NEW |
- Modifiers.PUBLIC |
- Modifiers.PROTECTED |
- Modifiers.INTERNAL |
- Modifiers.PRIVATE |
- Modifiers.STATIC |
- Modifiers.VOLATILE |
- Modifiers.UNSAFE |
- Modifiers.READONLY;
+ //
+ // Protected data.
+ //
+ readonly MemberBase member;
+ readonly int modifiers;
+ MethodAttributes flags;
+ readonly bool is_method;
+ readonly string accessor_name;
+ ArrayList conditionals;
- public Field (string type, int mod, string name, Object expr_or_array_init,
- Attributes attrs, Location loc)
- : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
- {
+ MethodBuilder builder = null;
+ public MethodBuilder MethodBuilder {
+ get {
+ return builder;
+ }
}
- public override bool Define (TypeContainer parent)
+ public MethodData (MemberBase member, string name, Type return_type,
+ Type [] parameter_types, InternalParameters parameters,
+ CallingConventions cc, Attributes opt_attrs,
+ int modifiers, MethodAttributes flags, bool is_method)
{
- Type t = RootContext.LookupType (parent, Type, false, Location);
-
- if (t == null)
- return false;
-
- if (!TypeContainer.AsAccessible (t, ModFlags))
- return false;
-
- if (t.IsPointer && !UnsafeOK (parent))
- return false;
-
- if (RootContext.WarningLevel > 1){
- Type ptype = parent.TypeBuilder.BaseType;
+ this.member = member;
+ this.accessor_name = name;
+ this.ReturnType = return_type;
+ this.ParameterTypes = parameter_types;
+ this.ParameterInfo = parameters;
+ this.CallingConventions = cc;
+ this.OptAttributes = opt_attrs;
+ this.modifiers = modifiers;
+ this.flags = flags;
+ this.is_method = is_method;
+ this.Location = member.Location;
+ this.conditionals = new ArrayList ();
+ }
- // ptype is only null for System.Object while compiling corlib.
- if (ptype != null){
- MemberInfo [] mi;
-
- mi = TypeContainer.FindMembers (
- ptype, MemberTypes.Method,
- BindingFlags.Public |
- BindingFlags.Static | BindingFlags.Instance,
- System.Type.FilterName, Name);
- }
- }
+ //
+ // Attributes.
+ //
+ Attribute dllimport_attribute = null;
+ string obsolete = null;
+ bool obsolete_error = false;
- if ((ModFlags & Modifiers.VOLATILE) != 0){
- if (!t.IsClass){
- if (TypeManager.IsEnumType (t))
- t = TypeManager.EnumToUnderlying (t);
+ public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
+ {
+ if ((opt_attrs == null) || (opt_attrs.Attrs == null))
+ return true;
- if (!((t == TypeManager.bool_type) ||
- (t == TypeManager.sbyte_type) ||
- (t == TypeManager.byte_type) ||
- (t == TypeManager.short_type) ||
- (t == TypeManager.ushort_type) ||
- (t == TypeManager.int32_type) ||
- (t == TypeManager.uint32_type) ||
- (t == TypeManager.char_type) ||
- (t == TypeManager.float_type))){
- Report.Error (
- 677, Location, parent.MakeName (Name) +
- " A volatile field can not be of type `" +
- TypeManager.CSharpName (t) + "'");
+ foreach (Attribute a in opt_attrs.Attrs) {
+ if (a.Name == "Conditional") {
+ if (!ApplyConditionalAttribute (a))
+ return false;
+ } else if (a.Name == "Obsolete") {
+ if (!ApplyObsoleteAttribute (a))
+ return false;
+ } else if (a.Name.IndexOf ("DllImport") != -1) {
+ if (!is_method) {
+ a.Type = TypeManager.dllimport_type;
+ Attribute.Error_AttributeNotValidForElement (a, Location);
return false;
}
+ if (!ApplyDllImportAttribute (a))
+ return false;
}
}
- FieldBuilder = parent.TypeBuilder.DefineField (
- Name, t, Modifiers.FieldAttr (ModFlags));
-
- TypeManager.RegisterFieldBase (FieldBuilder, this);
return true;
}
- public void Emit (TypeContainer tc)
+ //
+ // Applies the `DllImport' attribute to the method.
+ //
+ protected virtual bool ApplyDllImportAttribute (Attribute a)
{
- EmitContext ec = new EmitContext (tc, Location, null,
- FieldBuilder.FieldType, ModFlags);
+ const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
+ if ((modifiers & extern_static) != extern_static) {
+ Report.Error (601, Location,
+ "The DllImport attribute must be specified on a method " +
+ "marked `static' and `extern'.");
+ return false;
+ }
- Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
+ flags |= MethodAttributes.PinvokeImpl;
+ dllimport_attribute = a;
+ return true;
}
- }
- //
- // `set' and `get' accessors are represented with an Accessor.
- //
- public class Accessor {
//
- // Null if the accessor is empty, or a Block if not
+ // Applies the `Obsolete' attribute to the method.
//
- public Block Block;
-
- public Accessor (Block b)
+ protected virtual bool ApplyObsoleteAttribute (Attribute a)
{
- Block = b;
+ if (obsolete != null) {
+ Report.Error (579, Location, "Duplicate `Obsolete' attribute");
+ return false;
+ }
+
+ obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
+ return obsolete != null;
}
- }
-
- public class Property : MemberCore {
- public readonly string Type;
- public Accessor Get, Set;
- public PropertyBuilder PropertyBuilder;
- public Attributes OptAttributes;
- public MethodBuilder GetBuilder, SetBuilder;
//
- // The type, once we compute it.
-
- Type PropertyType;
+ // Applies the `Conditional' attribute to the method.
+ //
+ protected virtual bool ApplyConditionalAttribute (Attribute a)
+ {
+ // The Conditional attribute is only valid on methods.
+ if (!is_method) {
+ Attribute.Error_AttributeNotValidForElement (a, Location);
+ return false;
+ }
- const int AllowedModifiers =
- Modifiers.NEW |
- Modifiers.PUBLIC |
- Modifiers.PROTECTED |
- Modifiers.INTERNAL |
- Modifiers.PRIVATE |
- Modifiers.STATIC |
- Modifiers.SEALED |
- Modifiers.OVERRIDE |
- Modifiers.ABSTRACT |
- Modifiers.UNSAFE |
- Modifiers.EXTERN |
- Modifiers.VIRTUAL;
+ string condition = a.Conditional_GetConditionName ();
- public Property (string type, string name, int mod_flags,
- Accessor get_block, Accessor set_block,
- Attributes attrs, Location loc)
- : base (name, loc)
+ if (condition == null)
+ return false;
+
+ if (ReturnType != TypeManager.void_type) {
+ Report.Error (578, Location,
+ "Conditional not valid on `" + member.Name + "' " +
+ "because its return type is not void");
+ return false;
+ }
+
+ if ((modifiers & Modifiers.OVERRIDE) != 0) {
+ Report.Error (243, Location,
+ "Conditional not valid on `" + member.Name + "' " +
+ "because it is an override method");
+ return false;
+ }
+
+ if (member.IsExplicitImpl) {
+ Report.Error (577, Location,
+ "Conditional not valid on `" + member.Name + "' " +
+ "because it is an explicit interface implementation");
+ return false;
+ }
+
+ if (IsImplementing) {
+ Report.Error (623, Location,
+ "Conditional not valid on `" + member.Name + "' " +
+ "because it is an interface method");
+ return false;
+ }
+
+ conditionals.Add (condition);
+
+ return true;
+ }
+
+ //
+ // Checks whether this method should be ignored due to its Conditional attributes.
+ //
+ bool ShouldIgnore (Location loc)
{
- Type = type;
- ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);
- Get = get_block;
- Set = set_block;
- OptAttributes = attrs;
+ // When we're overriding a virtual method, we implicitly inherit the
+ // Conditional attributes from our parent.
+ if (member.ParentMethod != null) {
+ TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
+ member.ParentMethod, loc);
+
+ if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
+ return true;
+ }
+
+ foreach (string condition in conditionals)
+ if (RootContext.AllDefines [condition] == null)
+ return true;
+
+ return false;
}
//
- // Checks our base implementation if any
+ // Returns the TypeManager.MethodFlags for this method.
+ // This emits an error 619 / warning 618 if the method is obsolete.
+ // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
//
- bool CheckBase (MethodAttributes flags, TypeContainer parent)
+ public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
{
- //
- // Find properties with the same name on the base class
- //
+ TypeManager.MethodFlags flags = 0;
- MemberInfo [] props;
- MemberInfo [] props_static = TypeManager.MemberLookup (
- parent.TypeBuilder,
- parent.TypeBuilder.BaseType,
- MemberTypes.Property, BindingFlags.Public | BindingFlags.Static,
- Name);
+ if (obsolete != null) {
+ if (obsolete_error) {
+ Report.Error (619, loc, "Method `" + member.Name +
+ "' is obsolete: `" + obsolete + "'");
+ return TypeManager.MethodFlags.IsObsoleteError;
+ } else
+ Report.Warning (618, loc, "Method `" + member.Name +
+ "' is obsolete: `" + obsolete + "'");
- MemberInfo [] props_instance = TypeManager.MemberLookup (
- parent.TypeBuilder,
- parent.TypeBuilder.BaseType,
- MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance,
- Name);
+ flags |= TypeManager.MethodFlags.IsObsolete;
+ }
- //
- // Find if we have anything
- //
- if (props_static != null && props_static.Length > 0)
- props = props_static;
- else if (props_instance != null && props_instance.Length > 0)
- props = props_instance;
- else
- props = null;
+ if (ShouldIgnore (loc))
+ flags |= TypeManager.MethodFlags.ShouldIgnore;
- //
- // If we have something on the base.
- if (props != null && props.Length > 0){
- if (props.Length > 1)
- throw new Exception ("Should not happen");
-
- PropertyInfo pi = (PropertyInfo) props [0];
+ return flags;
+ }
+
+ //
+ // Search all the interface bases recursively for unimplemented methods
+ //
+ bool SearchBasesForAbstractMethods (
+ TypeContainer parent, Type iface_type,
+ string method_name, ref ArrayList implementing_list,
+ ref ArrayList implementing_iface)
+ {
+ MethodInfo implementing = null;
+ bool IsImplementing = false;
+ Type current_iface_type = iface_type;
- MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
- MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
+ implementing = parent.Pending.IsAbstractMethod (
+ current_iface_type, method_name, ReturnType, ParameterTypes);
- MethodInfo reference = inherited_get == null ?
- inherited_set : inherited_get;
-
- if (reference != null)
- if (!CheckMethodAgainstBase (parent, flags, reference))
- return false;
-
+ if (implementing != null) {
+ if (!implementing_list.Contains (implementing)) {
+ implementing_list.Add (implementing);
+ implementing_iface.Add(current_iface_type);
+ }
+ IsImplementing = true;
} else {
- if ((ModFlags & Modifiers.NEW) != 0)
- WarningNotHiding (parent);
-
- if ((ModFlags & Modifiers.OVERRIDE) != 0){
- Report.Error (115, Location,
- parent.MakeName (Name) +
- " no suitable properties found to override");
+ Type[] current_iface_types = current_iface_type.GetInterfaces();
+ if (current_iface_types.Length == 0)
return false;
+
+ foreach (Type curr_iface_type in current_iface_types) {
+ IsImplementing = SearchBasesForAbstractMethods (
+ parent, curr_iface_type, method_name,
+ ref implementing_list, ref implementing_iface);
+
+ if (IsImplementing)
+ break;
}
}
- return true;
+
+ return IsImplementing;
}
- bool DefineMethod (TypeContainer parent, Type iface_type, string short_name,
- MethodAttributes flags, bool is_get)
+ public virtual bool Define (TypeContainer parent)
{
- Type [] parameters = TypeManager.NoTypes;
- MethodInfo implementing;
- Type fn_type;
- string name;
+ MethodInfo implementing = null;
+ ArrayList implementing_list = null;
+ ArrayList implementing_iface = null;
+ string method_name, name, prefix, impl_method_name;
+ int pos = -1;
- if (is_get){
- fn_type = PropertyType;
- name = "get_" + short_name;
- } else {
- name = "set_" + short_name;
- parameters = new Type [1];
- parameters [0] = PropertyType;
- fn_type = TypeManager.void_type;
+ if (OptAttributes != null)
+ if (!ApplyAttributes (OptAttributes, is_method))
+ return false;
+
+ if (accessor_name != null)
+ name = accessor_name + "_" + member.ShortName;
+ else
+ name = member.ShortName;
+
+ method_name = name;
+ impl_method_name = name;
+
+ if ((member.ModFlags & Modifiers.OVERRIDE) != 0) {
+ if (parent.Pending == null)
+ implementing = null;
+ else
+ implementing = parent.Pending.IsAbstractMethod (
+ (Type) parent.TypeBuilder.BaseType, name,
+ ReturnType, ParameterTypes);
+
+ if (implementing != null)
+ IsImplementing = true;
}
- implementing = parent.IsInterfaceMethod (
- iface_type, name, fn_type, parameters, false);
+ if (member.Implements != null) {
+ implementing_list = new ArrayList();
+ implementing_iface = new ArrayList();
+
+ foreach (Expression Impl in member.Implements) {
+ name = Impl.ToString();
+ prefix = name.Substring(0, name.LastIndexOf("."));
+ name = name.Substring(name.LastIndexOf(".") + 1);
+
+ if (accessor_name != null)
+ impl_method_name = accessor_name + "_" + name;
+ else
+ impl_method_name = name;
+
+ Type current_iface_type = (Type) member.InterfaceTypes[++pos];
+ IsImplementing = SearchBasesForAbstractMethods (
+ parent, current_iface_type, impl_method_name,
+ ref implementing_list, ref implementing_iface);
+
+ if (IsImplementing == false) {
+ TypeContainer.Error_NotInterfaceMember (
+ Location, name, prefix);
+ return false;
+ }
+ }
+ }
//
// For implicit implementations, make sure we are public, for
// explicit implementations, make sure we are private.
//
- if (implementing != null){
+ //if (IsImplementing){
//
// Setting null inside this block will trigger a more
// verbose error reporting for missing interface implementations
// The "candidate" function has been flagged already
// but it wont get cleared
//
- if (iface_type == null){
+ /* if (!member.IsExplicitImpl){
//
// We already catch different accessibility settings
// so we just need to check that we are not private
//
- if ((ModFlags & Modifiers.PRIVATE) != 0)
+ if ((modifiers & Modifiers.PRIVATE) != 0)
implementing = null;
//
// Static is not allowed
//
- if ((ModFlags & Modifiers.STATIC) != 0)
+ if ((modifiers & Modifiers.STATIC) != 0)
implementing = null;
} else {
- if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
- Report.Error (
- 106, Location, "`public' or `abstract' modifiers "+
- "are not allowed in explicit interface declarations"
- );
+ if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
+ Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
implementing = null;
}
- }
- }
+ }*/
+ //}
//
// If implementing is still valid, set flags
//
- if (implementing != null){
+ if (IsImplementing){
//
// When implementing interface methods, set NewSlot.
//
- if (implementing.DeclaringType.IsInterface)
- flags |= MethodAttributes.NewSlot;
-
+ if (implementing_list != null && implementing_list.Count != 0)
+ flags |= MethodAttributes.NewSlot;
+
flags |=
MethodAttributes.Virtual |
MethodAttributes.HideBySig;
-
- //
- // clear the pending flag
- //
- parent.IsInterfaceMethod (
- iface_type, name, fn_type, parameters, true);
}
//
- // If this is not an explicit interface implementation,
- // clear implementing, as it is only used for explicit
- // interface implementation
+ // Create the MethodBuilder for the method
//
- if (Name.IndexOf (".") == -1)
- implementing = null;
-
- if (is_get){
- GetBuilder = parent.TypeBuilder.DefineMethod (
- name, flags, PropertyType, null);
- PropertyBuilder.SetGetMethod (GetBuilder);
-
- if (implementing != null)
- parent.TypeBuilder.DefineMethodOverride (
- GetBuilder, implementing);
+ if ((flags & MethodAttributes.PinvokeImpl) != 0) {
+ if ((modifiers & Modifiers.STATIC) == 0) {
+ Report.Error (601, Location,
+ "The DllImport attribute must be specified on " +
+ "a method marked 'static' and 'extern'.");
+ return false;
+ }
+ EmitContext ec = new EmitContext (
+ parent, Location, null, ReturnType, modifiers);
+
+ builder = dllimport_attribute.DefinePInvokeMethod (
+ ec, parent.TypeBuilder, method_name, flags,
+ ReturnType, ParameterTypes);
+ } else
+ builder = parent.TypeBuilder.DefineMethod (
+ method_name, flags, CallingConventions,
+ ReturnType, ParameterTypes);
+
+ if (builder == null)
+ return false;
+
+ if (IsImplementing) {
//
- // HACK because System.Reflection.Emit is lame
+ // implement abstract methods from abstract classes
//
- InternalParameters ip = new InternalParameters (
- parent, Parameters.GetEmptyReadOnlyParameters ());
-
- if (!TypeManager.RegisterMethod (GetBuilder, ip, null)) {
- Report.Error (111, Location,
- "Class `" + parent.Name +
- "' already contains a definition with the " +
- "same return value and parameter types as the " +
- "'get' method of property `" + Name + "'");
- return false;
+ if ((member.ModFlags & Modifiers.OVERRIDE) != 0) {
+ /*
+ if (member is Indexer)
+ parent.Pending.ImplementIndexer (
+ (Type) parent.TypeBuilder.BaseType,
+ builder, ReturnType,
+ ParameterTypes, true);
+ else
+ */
+ parent.Pending.ImplementMethod (
+ (Type) parent.TypeBuilder.BaseType,
+ name, ReturnType,
+ ParameterTypes, member.IsExplicitImpl);
}
- } else {
- SetBuilder = parent.TypeBuilder.DefineMethod (
- name, flags, null, parameters);
- if (implementing != null)
- parent.TypeBuilder.DefineMethodOverride (
- SetBuilder, implementing);
+ //
+ // implement abstract methods of interfaces
+ //
+ if (member.Implements != null) {
+ pos = 0;
+ foreach (MethodInfo Impl in implementing_list) {
+
+ /*
+ if (member is Indexer)
+ parent.Pending.ImplementIndexer (
+ (Type) implementing_iface[pos++],
+ builder, ReturnType,
+ ParameterTypes, true);
+ else
+ */
+ parent.Pending.ImplementMethod (
+ (Type) implementing_iface[pos++],
+ Impl.Name, ReturnType,
+ ParameterTypes, member.IsExplicitImpl);
+
+ parent.TypeBuilder.DefineMethodOverride (
+ builder, Impl);
+ }
+ }
- SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
- PropertyBuilder.SetSetMethod (SetBuilder);
+ }
+
+ if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
+ Report.Error (111, Location,
+ "Class `" + parent.Name +
+ "' already contains a definition with the " +
+ "same return value and parameter types as the " +
+ "'get' method of property `" + member.Name + "'");
+ return false;
+ }
+
+ TypeManager.AddMethod (builder, this);
+ return true;
+ }
+
+ //
+ // Emits the code
+ //
+ public virtual void Emit (TypeContainer parent, Block block, object kind)
+ {
+ ILGenerator ig;
+ EmitContext ec;
+
+ if ((flags & MethodAttributes.PinvokeImpl) == 0)
+ ig = builder.GetILGenerator ();
+ else
+ ig = null;
+
+ ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
+
+ if (OptAttributes != null)
+ Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
+
+ if (member is MethodCore)
+ ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder, ((MethodCore) member).Location);
+
+ //
+ // abstract or extern methods have no bodies
+ //
+ if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
+ if (block == null)
+ return;
//
- // HACK because System.Reflection.Emit is lame
+ // abstract or extern methods have no bodies.
//
- Parameter [] parms = new Parameter [1];
- parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
- InternalParameters ip = new InternalParameters (
- parent, new Parameters (parms, null, Location));
+ if ((modifiers & Modifiers.ABSTRACT) != 0)
+ Report.Error (
+ 500, Location, "Abstract method `" +
+ TypeManager.MonoBASIC_Signature (builder) +
+ "' can not have a body");
- if (!TypeManager.RegisterMethod (SetBuilder, ip, parameters)) {
+ if ((modifiers & Modifiers.EXTERN) != 0)
Report.Error (
- 111, Location,
- "Class `" + parent.Name +
- "' already contains a definition with the " +
- "same return value and parameter types as the " +
- "'set' method of property `" + Name + "'");
- return false;
+ 179, Location, "External method `" +
+ TypeManager.MonoBASIC_Signature (builder) +
+ "' can not have a body");
+
+ return;
+ }
+
+ //
+ // Methods must have a body unless they're extern or abstract
+ //
+ if (block == null) {
+ Report.Error (
+ 501, Location, "Method `" +
+ TypeManager.MonoBASIC_Signature (builder) +
+ "' must declare a body since it is not marked " +
+ "abstract or extern");
+ return;
+ }
+
+ //
+ // Handle destructors specially
+ //
+ // FIXME: This code generates buggy code
+ //
+ if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
+ EmitDestructor (ec, block);
+ else {
+ ISymbolWriter sw = CodeGen.SymbolWriter;
+
+ if ((sw != null) && !Location.IsNull (Location) &&
+ !Location.IsNull (block.EndLocation)) {
+ Location end = block.EndLocation;
+ MethodToken token = MethodBuilder.GetToken ();
+ sw.OpenMethod (new SymbolToken (token.Token));
+ // Avoid error if we don't support debugging for the platform
+ try {
+ sw.SetMethodSourceRange (Location.SymbolDocument,
+ Location.Row, 0,
+ end.SymbolDocument,
+ end.Row, 0);
+ } catch (Exception) {
+ }
+
+ ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
+
+ sw.CloseMethod ();
+ } else
+ ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
+ }
+ }
+
+ void EmitDestructor (EmitContext ec, Block block)
+ {
+ ILGenerator ig = ec.ig;
+
+ Label finish = ig.DefineLabel ();
+ bool old_in_try = ec.InTry;
+
+ ig.BeginExceptionBlock ();
+ ec.InTry = true;
+ ec.ReturnLabel = finish;
+ ec.HasReturnLabel = true;
+ ec.EmitTopBlock (block, null, Location);
+ ec.InTry = old_in_try;
+
+ // ig.MarkLabel (finish);
+ bool old_in_finally = ec.InFinally;
+ ec.InFinally = true;
+ ig.BeginFinallyBlock ();
+
+ if (ec.ContainerType.BaseType != null) {
+ Expression member_lookup = Expression.MemberLookup (
+ ec, ec.ContainerType.BaseType, ec.ContainerType.BaseType, "Finalize",
+ MemberTypes.Method, Expression.AllBindingFlags, Location);
+
+ if (member_lookup != null){
+ MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
+
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
}
}
+ ec.InFinally = old_in_finally;
+
+ ig.EndExceptionBlock ();
+ //ig.MarkLabel (ec.ReturnLabel);
+ ig.Emit (OpCodes.Ret);
+ }
+ }
+
+ abstract public class MemberBase : MemberCore {
+ public Expression Type;
+ public ArrayList Implements;
+
+ protected MethodAttributes flags;
+
+ //
+ // The "short" name of this property / indexer / event. This is the
+ // name without the explicit interface.
+ //
+ public string ShortName;
+
+ //
+ // The type of this property / indexer / event
+ //
+ public Type MemberType;
+
+ //
+ // If true, this is an explicit interface implementation
+ //
+ public bool IsExplicitImpl = false;
+
+ //
+ // The name of the interface we are explicitly implementing
+ //
+ public string ExplicitInterfaceName = null;
+
+ //
+ // If true, the interface type we are explicitly implementing
+ //
+ public Type InterfaceType = null;
+ public ArrayList InterfaceTypes = null;
+
+ //
+ // The method we're overriding if this is an override method.
+ //
+ protected MethodInfo parent_method = null;
+ public MethodInfo ParentMethod {
+ get {
+ return parent_method;
+ }
+ }
+
+ //
+ // The constructor is only exposed to our children
+ //
+ protected MemberBase (Expression type, int mod, int allowed_mod, string name,
+ Attributes attrs, Location loc)
+ : base (name, attrs, loc)
+ {
+ Type = type;
+ ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PUBLIC, loc);
+ }
+
+ protected virtual bool CheckBase (TypeContainer parent)
+ {
+ return true;
+ }
+
+ protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
+ {
+ bool error = false;
+
+ foreach (Type partype in parameters){
+ if (partype.IsPointer && !UnsafeOK (parent))
+ error = true;
+
+ if (parent.AsAccessible (partype, ModFlags))
+ continue;
+
+ Report.Error (51, Location,
+ "Inconsistent accessibility: parameter type `" +
+ TypeManager.MonoBASIC_Name (partype) + "' is less " +
+ "accessible than method `" + Name + "'");
+ error = true;
+ }
+
+ return !error;
+ }
+
+ protected virtual bool DoDefine (TypeContainer parent)
+ {
+ if (Name == null)
+ Name = "this";
+
+ if (!parent.MethodModifiersValid (ModFlags, Name, Location))
+ return false;
+
+ flags = Modifiers.MethodAttr (ModFlags);
+
+ // Lookup Type, verify validity
+ MemberType = parent.ResolveType (Type, false, Location);
+ if (MemberType == null)
+ return false;
+
+ // check for whether the Interface is implemented by the class
+ if (Implements != null) {
+ InterfaceTypes = new ArrayList ();
+ foreach (Expression Impls in Implements) {
+ string iname = Impls.ToString();
+ iname = iname.Substring(0, iname.LastIndexOf("."));
+ bool iface_found = false;
+
+ InterfaceType = RootContext.LookupType (
+ parent, iname, false, Location);
+ if (InterfaceType == null)
+ return false;
+
+ InterfaceTypes.Add (InterfaceType);
+ Type[] tbases = parent.TypeBuilder.GetInterfaces();
+
+ if (tbases.Length != 0) {
+ ArrayList bases = new ArrayList();
+ TypeManager.ExpandAllInterfaces (tbases, ref bases);
+
+ foreach (Type tbase in bases) {
+ string bname = tbase.Name;
+ if (bname.LastIndexOf(".") != -1)
+ bname = bname.Substring(bname.LastIndexOf("."));
+
+ if (bname == iname) {
+ iface_found = true;
+ break;
+ }
+ }
+ }
+
+ if (!iface_found) {
+ Report.Error (31035, Location,
+ "Class '" + parent.Name + "' doesn't implement interface '" + iname + "'");
+ return false;
+ }
+ }
+ }
+
+ // verify accessibility
+ if (!parent.AsAccessible (MemberType, ModFlags)) {
+ if (this is Property)
+ Report.Error (53, Location,
+ "Inconsistent accessibility: property type `" +
+ TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
+ "accessible than property `" + Name + "'");
+ else if (this is Method)
+ Report.Error (50, Location,
+ "Inconsistent accessibility: return type `" +
+ TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
+ "accessible than method `" + Name + "'");
+ else
+ Report.Error (52, Location,
+ "Inconsistent accessibility: field type `" +
+ TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
+ "accessible than field `" + Name + "'");
+ return false;
+ }
+
+ if (MemberType.IsPointer && !UnsafeOK (parent))
+ return false;
+
+ //
+ // Check for explicit interface implementation
+ //
+ if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)) {
+ int pos = Name.LastIndexOf (".");
+
+ ExplicitInterfaceName = Name.Substring (0, pos);
+ ShortName = Name.Substring (pos + 1);
+ } else
+ ShortName = Name;
+
+ return true;
+ }
+ }
+
+ //
+ // Fields and Events both generate FieldBuilders, we use this to share
+ // their common bits. This is also used to flag usage of the field
+ //
+ abstract public class FieldBase : MemberBase {
+ public FieldBuilder FieldBuilder;
+ public Status status;
+
+ [Flags]
+ public enum Status : byte { ASSIGNED = 1, USED = 2 }
+
+ //
+ // The constructor is only exposed to our children
+ //
+ protected FieldBase (Expression type, int mod, int allowed_mod, string name,
+ object init, Attributes attrs, Location loc)
+ : base (type, mod, allowed_mod, name, attrs, loc)
+ {
+ this.init = init;
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Field;
+ }
+ }
+
+
+ //
+ // Whether this field has an initializer.
+ //
+ public bool HasInitializer {
+ get {
+ return init != null;
+ }
+ }
+
+ // Private.
+ readonly Object init;
+ Expression init_expr;
+ bool init_expr_initialized = false;
+
+ //
+ // Resolves and returns the field initializer.
+ //
+ public Expression GetInitializerExpression (EmitContext ec)
+ {
+ if (init_expr_initialized)
+ return init_expr;
+
+ Expression e;
+ if (init is Expression)
+ e = (Expression) init;
+ else
+ e = new ArrayCreation (Type, "", (ArrayList)init, Location);
+
+ ec.IsFieldInitializer = true;
+ e = e.DoResolve (ec);
+ ec.IsFieldInitializer = false;
+
+ init_expr = e;
+ init_expr_initialized = true;
+
+ return init_expr;
+ }
+
+ }
+
+ //
+ // The Field class is used to represents class/struct fields during parsing.
+ //
+ public class Field : FieldBase {
+ // <summary>
+ // Modifiers allowed in a class declaration
+ // </summary>
+ const int AllowedModifiers =
+ Modifiers.SHADOWS |
+ Modifiers.PUBLIC |
+ Modifiers.PROTECTED |
+ Modifiers.INTERNAL |
+ Modifiers.PRIVATE |
+ Modifiers.STATIC |
+ // Modifiers.VOLATILE |
+ // Modifiers.UNSAFE |
+ Modifiers.READONLY;
+
+ public Field (Expression type, int mod, string name, Object expr_or_array_init,
+ Attributes attrs, Location loc)
+ : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
+ {
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Field;
+ }
+ }
+
+ public override bool Define (TypeContainer parent)
+ {
+ Type t = parent.ResolveType (Type, false, Location);
+
+ if (t == null)
+ return false;
+
+ if (!parent.AsAccessible (t, ModFlags)) {
+ Report.Error (52, Location,
+ "Inconsistent accessibility: field type `" +
+ TypeManager.MonoBASIC_Name (t) + "' is less " +
+ "accessible than field `" + Name + "'");
+ return false;
+ }
+
+ if (t.IsPointer && !UnsafeOK (parent))
+ return false;
+
+ Type ptype = parent.TypeBuilder.BaseType;
+
+ // ptype is only null for System.Object while compiling corlib.
+ if (ptype != null){
+ MemberList list = TypeContainer.FindMembers (
+ ptype, MemberTypes.Field,
+ BindingFlags.Public |
+ BindingFlags.Static | BindingFlags.Instance,
+ System.Type.FilterName, Name);
+
+ if (RootContext.WarningLevel > 1){
+ if ((list.Count > 0) && ((ModFlags & Modifiers.SHADOWS) == 0))
+ {
+ Report.Warning (
+ 40004, 2, Location,
+ "Variable '" + Name + "' should be declared " +
+ "Shadows since the base type '" + ptype.Name +
+ "' has a variable with same name");
+
+ ModFlags |= Modifiers.SHADOWS;
+ }
+ }
+ if (list.Count == 0)
+ // if a member of module is not inherited from Object class
+ // can not be declared protected
+ if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
+ Report.Error (30593, Location,
+ "'Variable' inside a 'Module' can not be " +
+ "declared as 'Protected'");
+ }
+
+ if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
+ Report.Error (30435, Location,
+ "'Variable' inside a 'Structure' can not be " +
+ "declared as 'Protected'");
+
+ if ((ModFlags & Modifiers.VOLATILE) != 0){
+ if (!t.IsClass){
+ if (TypeManager.IsEnumType (t))
+ t = TypeManager.EnumToUnderlying (t);
+
+ if (!((t == TypeManager.bool_type) ||
+ (t == TypeManager.sbyte_type) ||
+ (t == TypeManager.byte_type) ||
+ (t == TypeManager.short_type) ||
+ (t == TypeManager.ushort_type) ||
+ (t == TypeManager.int32_type) ||
+ (t == TypeManager.uint32_type) ||
+ (t == TypeManager.char_type) ||
+ (t == TypeManager.float_type))){
+ Report.Error (
+ 677, Location, parent.MakeName (Name) +
+ " A volatile field can not be of type `" +
+ TypeManager.MonoBASIC_Name (t) + "'");
+ return false;
+ }
+ }
+ }
+
+ FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
+
+ if (parent is Struct &&
+ ((fa & FieldAttributes.Static) == 0) &&
+ t == parent.TypeBuilder &&
+ !TypeManager.IsBuiltinType (t)){
+ Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name +
+ "' causes a cycle in the structure layout");
+ return false;
+ }
+ FieldBuilder = parent.TypeBuilder.DefineField (
+ Name, t, Modifiers.FieldAttr (ModFlags));
+
+ TypeManager.RegisterFieldBase (FieldBuilder, this);
+ return true;
+ }
+
+ public void Emit (TypeContainer tc)
+ {
+ EmitContext ec = new EmitContext (tc, Location, null,
+ FieldBuilder.FieldType, ModFlags);
+
+ if (OptAttributes != null)
+ OptAttributes.Emit (ec, this);
+ }
+
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ {
+ FieldBuilder.SetCustomAttribute (cb);
+ }
+
+ }
+
+ //
+ // `set' and `get' accessors are represented with an Accessor.
+ //
+ public class Accessor {
+ //
+ // Null if the accessor is empty, or a Block if not
+ //
+ public Block Block;
+ public Attributes OptAttributes;
+
+ public Accessor (Block b, Attributes attrs)
+ {
+ Block = b;
+ OptAttributes = attrs;
+ }
+ }
+
+ public class GetMethod {
+ private Accessor Get;
+ public MethodData GetData;
+ public MethodBuilder GetBuilder;
+
+ Property parent_property;
+ Location Location;
+
+ Parameters get_params;
+
+ public GetMethod (Property parent_property, Accessor get_block, Attributes attrs, Parameters p_get, Location loc)
+ {
+ this.parent_property = parent_property;
+ Get = get_block;
+ get_params = p_get;
+ Location = loc;
+ }
+
+ public MethodBuilder Define (TypeContainer parent)
+ {
+ Type [] g_parameters=null;
+ Parameter [] g_parms;
+ InternalParameters g_ip=null;
+
+ if (get_params == Parameters.EmptyReadOnlyParameters) {
+ g_parameters = TypeManager.NoTypes;
+ g_ip = new InternalParameters (parent, Parameters.EmptyReadOnlyParameters);
+ } else {
+ g_parameters = new Type [get_params.FixedParameters.Length];
+ for (int i = 0; i < get_params.FixedParameters.Length; i ++) {
+ g_parameters[i] = get_params.FixedParameters[i].ParameterType;
+ }
+ g_parms = new Parameter [get_params.FixedParameters.Length];
+ for (int i = 0; i < get_params.FixedParameters.Length; i ++) {
+ Parameter tp = get_params.FixedParameters[i];
+ g_parms[i] = new Parameter (tp.TypeName, tp.Name,
+ Parameter.Modifier.NONE, null);
+ }
+ g_ip = new InternalParameters (
+ parent, new Parameters (g_parms, null, Location));
+ }
+
+ GetData = new MethodData (parent_property, "get", parent_property.MemberType,
+ g_parameters, g_ip, CallingConventions.Standard,
+ Get.OptAttributes, parent_property.ModFlags, parent_property.MethodAttributeFlags, false);
+
+ if (!GetData.Define (parent))
+ return null;
+
+ GetBuilder = GetData.MethodBuilder;
+
+ return GetBuilder;
+ }
+
+ public void Emit (TypeContainer tc)
+ {
+ if (GetData != null)
+ {
+ parent_property.Parameters = get_params;
+ GetData.Emit (tc, Get.Block, Get);
+ }
+ }
+ }
+
+ public class SetMethod {
+ Accessor Set;
+ MethodData SetData;
+ MethodBuilder SetBuilder;
+
+ Property parent_property;
+ Location Location;
+
+ string set_parameter_name;
+ Parameters set_params;
+
+ public SetMethod (Property parent_property, Accessor set_block, string set_name,
+ Parameters p_set, Location loc)
+ {
+ this.parent_property = parent_property;
+ Set = set_block;
+ set_params = p_set;
+ set_parameter_name = set_name;
+ this.Location = loc;
+ }
+
+ public MethodBuilder Define (TypeContainer parent)
+ {
+ Type [] s_parameters=null;
+ Parameter [] s_parms;
+ InternalParameters s_ip=null;
+
+ if (set_params == Parameters.EmptyReadOnlyParameters)
+ {
+ s_parameters = new Type [1];
+ s_parameters [0] = parent_property.MemberType;
+
+ s_parms = new Parameter [1];
+ s_parms [0] = new Parameter (parent_property.Type, set_parameter_name,
+ Parameter.Modifier.NONE, null);
+ } else {
+ s_parameters = new Type [set_params.FixedParameters.Length];
+ for (int i = 0; i < set_params.FixedParameters.Length; i ++) {
+ s_parameters[i] = set_params.FixedParameters[i].ParameterType;
+ }
+
+ s_parms = new Parameter [set_params.FixedParameters.Length];
+ for (int i = 0; i < set_params.FixedParameters.Length; i ++) {
+ Parameter tp = set_params.FixedParameters[i];
+ s_parms[i] = new Parameter (tp.TypeName, tp.Name,
+ Parameter.Modifier.NONE, null);
+ }
+ }
+
+ s_ip = new InternalParameters (
+ parent, new Parameters (s_parms, null, Location));
+
+ SetData = new MethodData (parent_property, "set", TypeManager.void_type,
+ s_parameters, s_ip, CallingConventions.Standard,
+ Set.OptAttributes, parent_property.ModFlags, parent_property.MethodAttributeFlags, false);
+
+ if (!SetData.Define (parent))
+ return null;
+
+ SetBuilder = SetData.MethodBuilder;
+ SetBuilder.DefineParameter (1, ParameterAttributes.None,
+ set_parameter_name);
+
+ return SetBuilder;
+ }
+
+ public void Emit (TypeContainer tc)
+ {
+ if (SetData != null)
+ {
+ parent_property.Parameters = set_params;
+ SetData.Emit (tc, Set.Block, Set);
+ }
+ }
+ }
+
+ public class Property : MethodCore {
+ GetMethod GetMethod;
+ SetMethod SetMethod;
+
+ public Accessor Set;
+ public PropertyBuilder PropertyBuilder;
+ public MethodBuilder GetBuilder;
+ public MethodBuilder SetBuilder;
+ public MethodData SetData;
+
+ protected EmitContext ec;
+
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ {
+ PropertyBuilder.SetCustomAttribute (cb);
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Property;
+ }
+ }
+
+ protected override bool DoDefine (TypeContainer parent)
+ {
+ if (!base.DoDefine (parent))
+ return false;
+
+ ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
+
+ return true;
+ }
+
+ //
+ // Checks our base implementation if any
+ //
+ protected override bool CheckBase (TypeContainer container)
+ {
+ base.CheckBase (container);
+
+ // Check whether arguments were correct.
+ if (!DoDefineParameters (container))
+ return false;
+
+ if (IsExplicitImpl)
+ return true;
+
+ MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
+ if (!IsOperator)
+ {
+ MemberList mi_this;
+
+ mi_this = TypeContainer.FindMembers (
+ container.TypeBuilder, MemberTypes.Property,
+ BindingFlags.NonPublic | BindingFlags.Public |
+ BindingFlags.Static | BindingFlags.Instance |
+ BindingFlags.DeclaredOnly,
+ MethodSignature.method_signature_filter, ms);
+
+ if (mi_this.Count > 0) {
+ Report.Error (111, Location, "Class `" + container.Name + "' " +
+ "already defines a member called `" + Name + "' " +
+ "with the same parameter types");
+ return false;
+ }
+ }
+
+ if (container is Interface)
+ return true;
+
+ Type retval = null;
+ if ((ModFlags & Modifiers.READONLY) != 0)
+ retval = MemberType;
+
+ //string report_name;
+ MethodSignature base_ms;
+
+ /*
+ if (this is Indexer) {
+ string name, base_name;
+
+ report_name = "this";
+ name = TypeManager.IndexerPropertyName (container.TypeBuilder);
+ ms = new MethodSignature (name, null, ParameterTypes);
+ base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
+ base_ms = new MethodSignature (base_name, retval, ParameterTypes);
+ } else */ {
+ //report_name = Name;
+ ms = base_ms = new MethodSignature (Name, retval, ParameterTypes);
+ }
+
+ //
+ // Verify if the parent has a type with the same name, and then
+ // check whether we have to create a new slot for it or not.
+ //
+ Type ptype = container.TypeBuilder.BaseType;
+
+ MemberInfo parent_member = null;
+ MemberList mi, mi_static, mi_instance;
+
+ //
+ // Find properties with the same name on the base class
+ //
+ mi_static = TypeContainer.FindMembers (
+ ptype, MemberTypes.Property,
+ BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
+ MethodSignature.inheritable_property_signature_filter, base_ms);
+
+ mi_instance = TypeContainer.FindMembers (
+ ptype, MemberTypes.Property,
+ BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
+ MethodSignature.inheritable_property_signature_filter,
+ base_ms);
+
+ if (mi_instance.Count > 0)
+ mi = mi_instance;
+ else if (mi_static.Count > 0)
+ mi = mi_static;
+ else
+ mi = null;
+
+ if (mi != null && mi.Count > 0)
+ parent_member = (PropertyInfo) mi [0];
+
+ if (parent_member is PropertyInfo) {
+ PropertyInfo parent_property = (PropertyInfo)parent_member;
+
+ string name = parent_property.DeclaringType.Name + "." +
+ parent_property.Name;
+
+ MethodInfo get, set, parent_method;
+ get = parent_property.GetGetMethod (true);
+ set = parent_property.GetSetMethod (true);
+
+ if (get != null)
+ parent_method = get;
+ else if (set != null)
+ parent_method = set;
+ else
+ throw new Exception ("Internal error!");
+
+ if (!CheckMethodAgainstBase (container, flags, parent_method, name))
+ return false;
+
+ if ((ModFlags & Modifiers.NEW) == 0) {
+ Type parent_type = TypeManager.TypeToCoreType (
+ parent_property.PropertyType);
+
+ if (parent_type != MemberType) {
+ Report.Error (
+ 508, Location, container.MakeName (Name) + ": cannot " +
+ "change return type when overriding " +
+ "inherited member " + name);
+ return false;
+ }
+ }
+ } else if (parent_member == null) {
+ /*if ((ModFlags & Modifiers.NEW) != 0)
+ WarningNotHiding (container);
+ */
+ if ((ModFlags & Modifiers.OVERRIDE) != 0) {
+
+ /*
+ if (this is Indexer)
+ Report.Error (115, Location,
+ container.MakeName (Name) +
+ " no suitable indexers found to override");
+ else
+ */
+ Report.Error (115, Location,
+ container.MakeName (Name) +
+ " no suitable properties found to override");
+ return false;
+ }
+
+ if ((ModFlags & ( Modifiers.NEW | Modifiers.SHADOWS | Modifiers.OVERRIDE )) == 0) {
+ if ((ModFlags & Modifiers.NONVIRTUAL) != 0) {
+ Report.Error (31088, Location,
+ container.MakeName (Name) + " : Cannot " +
+ "be declared NotOverridable since this method is " +
+ "not maked as Overrides");
+ }
+ }
+ // if a member of module is not inherited from Object class
+ // can not be declared protected
+ if ((container is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
+ Report.Error (31066, Location,
+ "'Property' inside a 'Module' can not be declared as " +
+ "'Protected' or 'Protected Friend'");
+ }
+ return true;
+ }
+
+
+ const int AllowedModifiers =
+ Modifiers.NEW |
+ Modifiers.PUBLIC |
+ Modifiers.PROTECTED |
+ Modifiers.INTERNAL |
+ Modifiers.PRIVATE |
+ Modifiers.STATIC |
+ Modifiers.SEALED |
+ Modifiers.OVERRIDE |
+ Modifiers.ABSTRACT |
+ Modifiers.UNSAFE |
+ Modifiers.EXTERN |
+ Modifiers.VIRTUAL |
+ Modifiers.NONVIRTUAL |
+ Modifiers.DEFAULT |
+ Modifiers.READONLY |
+ Modifiers.WRITEONLY |
+ Modifiers.SHADOWS;
+
+ string set_parameter_name;
+ Parameters get_params;
+ Parameters set_params;
+
+ public Property (Expression type, string name, int mod_flags,
+ Accessor get_block, Accessor set_block,
+ Attributes attrs, Location loc, string set_name,
+ Parameters p_get, Parameters p_set, ArrayList impl_what)
+ : base (type, mod_flags, AllowedModifiers, name, attrs, p_set, loc)
+
+ {
+ if (get_block != null)
+ GetMethod = new GetMethod (this, get_block, attrs, p_get, loc);
- return true;
+ if (set_block != null)
+ SetMethod = new SetMethod (this, set_block, set_name, p_set, loc);
+
+ Implements = impl_what;
+ }
+
+ public Property (Expression type, string name, int mod_flags,
+ Accessor get_block, Accessor set_block,
+ Attributes attrs, Location loc)
+ : this (type, name, mod_flags, get_block, set_block, attrs, loc,
+ "Value", Parameters.EmptyReadOnlyParameters, Parameters.EmptyReadOnlyParameters, null)
+ {
}
public override bool Define (TypeContainer parent)
{
- Type iface_type = null;
- string short_name;
-
- if (!parent.MethodModifiersValid (ModFlags, Name, Location))
- return false;
-
- MethodAttributes flags = Modifiers.MethodAttr (ModFlags);
+ /*Type [] s_parameters=null;
+ Parameter [] s_parms;
+ InternalParameters s_ip=null;*/
- flags |= MethodAttributes.HideBySig |
- MethodAttributes.SpecialName;
-
- // Lookup Type, verify validity
- PropertyType = RootContext.LookupType (parent, Type, false, Location);
- if (PropertyType == null)
- return false;
+ if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
+ Report.Error (30435, Location,
+ "'Property' inside a 'Structure' can not be declared as " +
+ "'Protected' or 'Protected Friend'");
- // verify accessibility
- if (!TypeContainer.AsAccessible (PropertyType, ModFlags))
+ if (!DoDefine (parent))
return false;
- if (PropertyType.IsPointer && !UnsafeOK (parent))
- return false;
-
- if (!CheckBase (flags, parent))
+ if (!CheckBase (parent))
return false;
- //
- // Check for explicit interface implementation
- //
- if (Name.IndexOf (".") != -1){
- int pos = Name.LastIndexOf (".");
- string iface = Name.Substring (0, pos);
+ flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
- iface_type = RootContext.LookupType (parent, iface, false, Location);
- if (iface_type == null)
- return false;
-
- short_name = Name.Substring (pos + 1);
-
- // Compute the full name that we need to export.
- Name = iface_type.FullName + "." + short_name;
+ if (GetMethod == null) {
+ if ((ModFlags & Modifiers.WRITEONLY) == 0)
+ Report.Error (
+ 30124, Location,
+ "Property without 'Get' accessor must have a 'WriteOnly' modifier");
} else
- short_name = Name;
+ GetBuilder = GetMethod.Define (parent);
+
+ if (SetMethod== null) {
+ if ((ModFlags & Modifiers.READONLY) == 0)
+ Report.Error (
+ 30124, Location,
+ "Property without 'Set' accessor must have a 'ReadOnly' modifier");
+
+ }
+ else
+ SetBuilder = SetMethod.Define (parent);
// FIXME - PropertyAttributes.HasDefault ?
+
+ PropertyAttributes prop_attr =
+ PropertyAttributes.RTSpecialName |
+ PropertyAttributes.SpecialName;
- PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
- PropertyAttributes.SpecialName;
-
- PropertyBuilder = parent.TypeBuilder.DefineProperty (
- Name, prop_attr, PropertyType, null);
+ if (!IsExplicitImpl){
+ PropertyBuilder = parent.TypeBuilder.DefineProperty (
+ Name, prop_attr, MemberType, null);
+
+ PropertyBuilder.SetGetMethod (GetBuilder);
+ PropertyBuilder.SetSetMethod (SetBuilder);
- if (Get != null)
- if (!DefineMethod (parent, iface_type, short_name, flags, true))
- return false;
-
- if (Set != null)
- if (!DefineMethod (parent, iface_type, short_name, flags, false))
+ //
+ // HACK for the reasons exposed above
+ //
+ if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
+ Report.Error (
+ 111, Location,
+ "Class `" + parent.Name +
+ "' already contains a definition for the property `" +
+ Name + "'");
return false;
-
- //
- // HACK for the reasons exposed above
- //
- if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
- Report.Error (
- 111, Location,
- "Class `" + parent.Name +
- "' already contains a definition for the property `" +
- Name + "'");
- return false;
+ }
}
-
return true;
}
-
+
public void Emit (TypeContainer tc)
{
- ILGenerator ig;
- EmitContext ec;
-
- ec = new EmitContext (tc, Location, null, PropertyType, ModFlags);
- Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
-
-
//
- // abstract or extern properties have no bodies
+ // The PropertyBuilder can be null for explicit implementations, in that
+ // case, we do not actually emit the ".property", so there is nowhere to
+ // put the attribute
//
- if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
- return;
+
+ if (PropertyBuilder != null && OptAttributes != null)
+ OptAttributes.Emit (ec, this);
+
+ if (GetMethod != null)
+ {
+ GetMethod.Emit (tc);
+ }
- if (Get != null){
- ig = GetBuilder.GetILGenerator ();
- ec = new EmitContext (tc, Location, ig, PropertyType, ModFlags);
-
- ec.EmitTopBlock (Get.Block, Location);
+ if (SetMethod != null)
+ {
+ SetMethod.Emit (tc);
}
+ }
- if (Set != null){
- ig = SetBuilder.GetILGenerator ();
- ec = new EmitContext (tc, Location, ig, null, ModFlags);
-
- ec.EmitTopBlock (Set.Block, Location);
+ public MethodAttributes MethodAttributeFlags {
+ get {
+ return flags;
}
}
- }
+ }
/// </summary>
/// Gigantic workaround for lameness in SRE follows :
}
}
}
-
- public class Event : FieldBase {
- const int AllowedModifiers =
- Modifiers.NEW |
- Modifiers.PUBLIC |
- Modifiers.PROTECTED |
- Modifiers.INTERNAL |
- Modifiers.PRIVATE |
- Modifiers.STATIC |
- Modifiers.VIRTUAL |
- Modifiers.SEALED |
- Modifiers.OVERRIDE |
- Modifiers.UNSAFE |
- Modifiers.ABSTRACT;
-
- public readonly Block Add;
- public readonly Block Remove;
- public MyEventBuilder EventBuilder;
-
- Type EventType;
- MethodBuilder AddBuilder, RemoveBuilder;
-
- public Event (string type, string name, Object init, int mod, Block add_block,
- Block rem_block, Attributes attrs, Location loc)
- : base (type, mod, AllowedModifiers, name, init, attrs, loc)
- {
- Add = add_block;
- Remove = rem_block;
- }
-
- public override bool Define (TypeContainer parent)
- {
- if (!parent.MethodModifiersValid (ModFlags, Name, Location))
- return false;
-
- MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
- EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
-
- EventType = RootContext.LookupType (parent, Type, false, Location);
- if (EventType == null)
- return false;
-
- if (!TypeContainer.AsAccessible (EventType, ModFlags))
- return false;
-
- if (EventType.IsPointer && !UnsafeOK (parent))
- return false;
-
- if (!EventType.IsSubclassOf (TypeManager.delegate_type)) {
- Report.Error (66, Location, "'" + parent.Name + "." + Name +
- "' : event must be of a delegate type");
- return false;
- }
-
- Type [] parameters = new Type [1];
- parameters [0] = EventType;
-
- EventBuilder = new MyEventBuilder (parent.TypeBuilder, Name, e_attr, EventType);
-
- if (Add == null && Remove == null){
- FieldBuilder = parent.TypeBuilder.DefineField (
- Name, EventType, FieldAttributes.Private);
- TypeManager.RegisterFieldBase (FieldBuilder, this);
- }
-
- //
- // Now define the accessors
- //
- string add_name = "add_" + Name;
-
- AddBuilder = parent.TypeBuilder.DefineMethod (
- add_name, m_attr, null, parameters);
- AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
- EventBuilder.SetAddOnMethod (AddBuilder);
- parent.IsInterfaceMethod (null, add_name, null, parameters, true);
-
- //
- // HACK because System.Reflection.Emit is lame
- //
- Parameter [] parms = new Parameter [1];
- parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
- InternalParameters ip = new InternalParameters (
- parent, new Parameters (parms, null, Location));
-
- if (!TypeManager.RegisterMethod (AddBuilder, ip, parameters)) {
- Report.Error (111, Location,
- "Class `" + parent.Name + "' already contains a definition with the " +
- "same return value and parameter types for the " +
- "'add' method of event `" + Name + "'");
- return false;
- }
-
- string remove_name = "remove_" + Name;
- RemoveBuilder = parent.TypeBuilder.DefineMethod (
- remove_name, m_attr, null, parameters);
- RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
- EventBuilder.SetRemoveOnMethod (RemoveBuilder);
- parent.IsInterfaceMethod (null, remove_name, null, parameters, true);
-
- //
- // HACK because System.Reflection.Emit is lame
- //
-
- if (!TypeManager.RegisterMethod (RemoveBuilder, ip, parameters)) {
- Report.Error (111, Location,
- "Class `" + parent.Name + "' already contains a definition with the " +
- "same return value and parameter types for the " +
- "'remove' method of event `" + Name + "'");
- return false;
- }
-
- if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
- Report.Error (111, Location,
- "Class `" + parent.Name +
- "' already contains a definition for the event `" +
- Name + "'");
- return false;
- }
-
- return true;
- }
-
- void EmitDefaultMethod (EmitContext ec, bool is_add)
- {
- ILGenerator ig = ec.ig;
- MethodInfo method = null;
-
- if (is_add)
- method = TypeManager.delegate_combine_delegate_delegate;
- else
- method = TypeManager.delegate_remove_delegate_delegate;
-
- ig.Emit (OpCodes.Ldarg_0);
- ig.Emit (OpCodes.Ldarg_0);
- ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
- ig.Emit (OpCodes.Ldarg_1);
- ig.Emit (OpCodes.Call, method);
- ig.Emit (OpCodes.Castclass, EventType);
- ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
- ig.Emit (OpCodes.Ret);
- }
-
- public void Emit (TypeContainer tc)
- {
- EmitContext ec;
- ILGenerator ig;
-
- ig = AddBuilder.GetILGenerator ();
- ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
-
- if (Add != null)
- ec.EmitTopBlock (Add, Location);
- else
- EmitDefaultMethod (ec, true);
-
- ig = RemoveBuilder.GetILGenerator ();
- ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
-
- if (Remove != null)
- ec.EmitTopBlock (Remove, Location);
- else
- EmitDefaultMethod (ec, false);
-
- ec = new EmitContext (tc, Location, null, EventType, ModFlags);
- Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
-
- }
-
- }
-
- //
- // FIXME: This does not handle:
- //
- // int INTERFACENAME [ args ]
- //
- // Only:
- //
- // int this [ args ]
-
- public class Indexer : MemberCore {
-
- const int AllowedModifiers =
- Modifiers.NEW |
- Modifiers.PUBLIC |
- Modifiers.PROTECTED |
- Modifiers.INTERNAL |
- Modifiers.PRIVATE |
- Modifiers.VIRTUAL |
- Modifiers.SEALED |
- Modifiers.OVERRIDE |
- Modifiers.UNSAFE |
- Modifiers.EXTERN |
- Modifiers.ABSTRACT;
-
- public readonly string Type;
- public readonly string InterfaceType;
- public readonly Parameters FormalParameters;
- public readonly Accessor Get, Set;
- public Attributes OptAttributes;
- public MethodBuilder GetBuilder;
- public MethodBuilder SetBuilder;
- public PropertyBuilder PropertyBuilder;
- public Type IndexerType;
- public string IndexerName;
- EmitContext ec;
-
- public Indexer (string type, string int_type, int flags, Parameters parms,
- Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
- : base ("", loc)
- {
-
- Type = type;
- InterfaceType = int_type;
- ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE, loc);
- FormalParameters = parms;
- Get = get_block;
- Set = set_block;
- OptAttributes = attrs;
- }
-
- bool DefineMethod (TypeContainer parent, Type iface_type,
- Type ret_type, string name,
- Type [] parameters, MethodAttributes attr, bool is_get)
- {
- MethodInfo implementing;
- bool is_implementation;
-
- implementing = parent.IsInterfaceMethod (
- iface_type, name, ret_type, parameters, false);
-
- is_implementation = implementing != null;
-
- //
- // Setting null inside this block will trigger a more
- // verbose error reporting for missing interface implementations
- //
- // The "candidate" function has been flagged already
- // but it wont get cleared
- //
- if (implementing != null){
- if (iface_type == null){
- //
- // We already catch different accessibility settings
- // so we just need to check that we are not private
- //
- if ((ModFlags & Modifiers.PRIVATE) != 0)
- implementing = null;
-
- //
- // Static is not allowed
- //
- if ((ModFlags & Modifiers.STATIC) != 0)
- implementing = null;
- } else {
- if((ModFlags&(Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
- Report.Error (
- 106, Location,
- "`public' or `abstract' modifiers are not "+
- "allowed in explicit interface declarations"
- );
- implementing = null;
- }
- }
- }
- if (implementing != null){
- //
- // When implementing interface methods, set NewSlot.
- //
- if (implementing.DeclaringType.IsInterface)
- attr |= MethodAttributes.NewSlot;
-
- attr |=
- MethodAttributes.Virtual |
- MethodAttributes.HideBySig;
-
- //
- // clear the pending flag
- //
- parent.IsInterfaceMethod (
- iface_type, name, ret_type, parameters, true);
- }
-
- //
- // If this is not an explicit interface implementation,
- // clear implementing, as it is only used for explicit
- // interface implementation
- //
- if (InterfaceType == null)
- implementing = null;
-
- if (is_get){
- string meth_name = "get_" + IndexerName;
- if (iface_type != null)
- meth_name = iface_type + ".get_" + IndexerName;
-
- GetBuilder = parent.TypeBuilder.DefineMethod (
- meth_name, attr, IndexerType, parameters);
-
- if (implementing != null)
- parent.TypeBuilder.DefineMethodOverride (
- GetBuilder, implementing);
- } else {
- string meth_name = "set_" + IndexerName;
-
- if (iface_type != null)
- meth_name = iface_type + ".set_" + IndexerName;
-
- SetBuilder = parent.TypeBuilder.DefineMethod (
- meth_name, attr, null, parameters);
- if (implementing != null)
- parent.TypeBuilder.DefineMethodOverride (
- SetBuilder, implementing);
- }
-
- return is_implementation;
- }
-
- public override bool Define (TypeContainer parent)
- {
- PropertyAttributes prop_attr =
- PropertyAttributes.RTSpecialName |
- PropertyAttributes.SpecialName;
- bool error = false;
-
- IndexerType = RootContext.LookupType (parent, Type, false, Location);
- Type [] parameters = FormalParameters.GetParameterInfo (parent);
-
- // Check if the return type and arguments were correct
- if (IndexerType == null || parameters == null)
- return false;
-
- if (!parent.MethodModifiersValid (ModFlags, InterfaceType == null ?
- "this" : InterfaceType, Location))
- return false;
- //
- // verify accessibility and unsafe pointers
- //
- if (!TypeContainer.AsAccessible (IndexerType, ModFlags))
- return false;
+
+ public class AddDelegateMethod {
+ MethodBuilder AddBuilder;
+ MethodData AddData;
+ Event parent_event;
+ Location Location;
+
+ public AddDelegateMethod (Event parent_event, Location loc)
+ {
+ this.parent_event = parent_event;
+ Location = loc;
+ }
- if (IndexerType.IsPointer && !UnsafeOK (parent))
- return false;
+ public MethodBuilder Define (TypeContainer parent)
+ {
+ Type [] parameter_types = new Type [1];
+ parameter_types [0] = parent_event.MemberType;
- foreach (Type partype in parameters){
- if (!TypeContainer.AsAccessible (partype, ModFlags))
- error = true;
- if (partype.IsPointer && !UnsafeOK (parent))
- error = true;
- }
+ Parameter [] parms = new Parameter [1];
+ parms [0] = new Parameter (parent_event.Type, /* was "value" */ parent_event.Name, Parameter.Modifier.NONE, null);
+ InternalParameters ip = new InternalParameters (
+ parent, new Parameters (parms, null, Location));
- if (error)
- return false;
-
- Type iface_type = null;
+ AddData = new MethodData (parent_event, "add", TypeManager.void_type,
+ parameter_types, ip, CallingConventions.Standard, null,
+ parent_event.ModFlags, parent_event.MethodAttributeFlags, false);
- if (InterfaceType != null){
- iface_type = RootContext.LookupType (parent, InterfaceType, false, Location);
- if (iface_type == null)
- return false;
- }
+ if (!AddData.Define (parent))
+ return null;
- ec = new EmitContext (parent, Location, null, IndexerType, ModFlags);
+ AddBuilder = AddData.MethodBuilder;
+ AddBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ parent_event.Name);
- IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
- if (IndexerName == null)
- IndexerName = "Item";
-
- MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
- bool is_implementing = false;
-
- if (Get != null){
- is_implementing = DefineMethod (
- parent, iface_type, IndexerType, "get_" + IndexerName,
- parameters, attr, true);
- InternalParameters pi = new InternalParameters (parent, FormalParameters);
- if (!TypeManager.RegisterMethod (GetBuilder, pi, parameters)) {
- Report.Error (111, Location,
- "Class `" + parent.Name +
- "' already contains a definition with the " +
- "same return value and parameter types for the " +
- "'get' indexer");
- return false;
- }
- }
-
- if (Set != null){
- int top = parameters.Length;
- Type [] set_pars = new Type [top + 1];
- parameters.CopyTo (set_pars, 0);
- set_pars [top] = IndexerType;
-
- Parameter [] fixed_parms = FormalParameters.FixedParameters;
-
- if (fixed_parms == null){
- throw new Exception ("We currently do not support only array arguments in an indexer");
- // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
- // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
- //
- // Here is the problem: the `value' parameter has
- // to come *after* the array parameter in the declaration
- // like this:
- // X (object [] x, Type value)
- // .param [0]
- //
- // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
- // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
-
- }
-
- Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
+ return AddBuilder;
+ }
- fixed_parms.CopyTo (tmp, 0);
- tmp [fixed_parms.Length] = new Parameter (
- Type, "value", Parameter.Modifier.NONE, null);
+ public void Emit (TypeContainer tc)
+ {
+ ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
+ EmitContext ec = new EmitContext (tc, Location, ig, TypeManager.void_type, parent_event.ModFlags);
+ parent_event.EmitDefaultMethod (ec, true);
+ }
+ }
- Parameters set_formal_params = new Parameters (tmp, null, Location);
-
- is_implementing = DefineMethod (
- parent, iface_type, TypeManager.void_type,
- "set_" + IndexerName, set_pars, attr, false);
+ public class RemoveDelegateMethod {
+ MethodBuilder RemoveBuilder;
+ MethodData RemoveData;
+ Event parent_event;
+ Location Location;
+
+ public RemoveDelegateMethod (Event parent_event, Location loc)
+ {
+ this.parent_event = parent_event;
+ Location = loc;
+ }
- InternalParameters ip = new InternalParameters (parent, set_formal_params);
-
- if (!TypeManager.RegisterMethod (SetBuilder, ip, set_pars)) {
- Report.Error (
- 111, Location,
- "Class `" + parent.Name + "' already contains a " +
- "definition with the " +
- "same return value and parameter types for the " +
- "'set' indexer");
- return false;
- }
- }
+ public MethodBuilder Define (TypeContainer parent)
+ {
+ //EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
- //
- // Now name the parameters
- //
- Parameter [] p = FormalParameters.FixedParameters;
- if (p != null) {
- int i;
-
- for (i = 0; i < p.Length; ++i) {
- if (Get != null)
- GetBuilder.DefineParameter (
- i + 1, p [i].Attributes, p [i].Name);
-
- if (Set != null)
- SetBuilder.DefineParameter (
- i + 1, p [i].Attributes, p [i].Name);
- }
+ Type [] parameter_types = new Type [1];
+ parameter_types [0] = parent_event.MemberType;
- if (Set != null)
- SetBuilder.DefineParameter (
- i + 1, ParameterAttributes.None, "value");
-
- if (i != parameters.Length) {
- Parameter array_param = FormalParameters.ArrayParameter;
- SetBuilder.DefineParameter (i + 1, array_param.Attributes,
- array_param.Name);
- }
- }
+ Parameter [] parms = new Parameter [1];
+ parms [0] = new Parameter (parent_event.Type, /* was "value" */ parent_event.Name, Parameter.Modifier.NONE, null);
+ InternalParameters ip = new InternalParameters (
+ parent, new Parameters (parms, null, Location));
- //
- // Only define the PropertyBuilder if we are not implementing
- // an interface property.
- //
- if (!is_implementing){
- PropertyBuilder = parent.TypeBuilder.DefineProperty (
- IndexerName, prop_attr, IndexerType, parameters);
- TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
+ RemoveData = new MethodData (parent_event, "remove", TypeManager.void_type,
+ parameter_types, ip, CallingConventions.Standard, null,
+ parent_event.ModFlags, parent_event.MethodAttributeFlags, false);
- if (GetBuilder != null)
- PropertyBuilder.SetGetMethod (GetBuilder);
+ if (!RemoveData.Define (parent))
+ return null;
- if (SetBuilder != null)
- PropertyBuilder.SetSetMethod (SetBuilder);
- }
+ RemoveBuilder = RemoveData.MethodBuilder;
+ RemoveBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ parent_event.Name);
- return true;
+ return RemoveBuilder;
}
public void Emit (TypeContainer tc)
{
- ILGenerator ig;
-
- Attribute.ApplyAttributes (
- ec, PropertyBuilder, this, OptAttributes, Location);
-
- if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
- return;
-
- if (Get != null){
- ig = GetBuilder.GetILGenerator ();
- ec = new EmitContext (tc, Location, ig, IndexerType, ModFlags);
-
- ec.EmitTopBlock (Get.Block, Location);
- }
-
- if (Set != null){
- ig = SetBuilder.GetILGenerator ();
- ec = new EmitContext (tc, Location, ig, null, ModFlags);
-
- ec.EmitTopBlock (Set.Block, Location);
- }
+ ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
+ EmitContext ec = new EmitContext (tc, Location, ig, TypeManager.void_type, parent_event.ModFlags);
+ parent_event.EmitDefaultMethod (ec, false);
}
}
-
- public class Operator : MemberCore {
-
+
+ public class Event : FieldBase {
const int AllowedModifiers =
+ Modifiers.NEW |
Modifiers.PUBLIC |
+ Modifiers.PROTECTED |
+ Modifiers.INTERNAL |
+ Modifiers.PRIVATE |
+ Modifiers.STATIC |
+ Modifiers.VIRTUAL |
+ Modifiers.SEALED |
+ Modifiers.OVERRIDE |
Modifiers.UNSAFE |
- Modifiers.EXTERN |
- Modifiers.STATIC;
+ Modifiers.ABSTRACT;
- const int RequiredModifiers =
- Modifiers.PUBLIC |
- Modifiers.STATIC;
+ public readonly AddDelegateMethod Add;
+ public readonly RemoveDelegateMethod Remove;
+ public MyEventBuilder EventBuilder;
- public enum OpType : byte {
+ MethodBuilder AddBuilder, RemoveBuilder;
+
+ public Event (Expression type, string name, Object init, int mod, Attributes attrs, Location loc)
+ : base (type, mod, AllowedModifiers, name, init, attrs, loc)
+ {
+ Add = new AddDelegateMethod (this, loc);
+ Remove = new RemoveDelegateMethod (this, loc);
- // Unary operators
- LogicalNot,
- OnesComplement,
- Increment,
- Decrement,
- True,
- False,
+ Implements = null;
+ }
- // Unary and Binary operators
- Addition,
- Subtraction,
+ public Event (Expression type, string name, Object init, int mod, Attributes attrs, ArrayList impl_what, Location loc)
+ : base (type, mod, AllowedModifiers, name, init, attrs, loc)
+ {
+ Add = new AddDelegateMethod (this, loc);
+ Remove = new RemoveDelegateMethod (this, loc);
- UnaryPlus,
- UnaryNegation,
-
- // Binary operators
- Multiply,
- Division,
- Modulus,
- BitwiseAnd,
- BitwiseOr,
- ExclusiveOr,
- LeftShift,
- RightShift,
- Equality,
- Inequality,
- GreaterThan,
- LessThan,
- GreaterThanOrEqual,
- LessThanOrEqual,
-
- // Implicit and Explicit
- Implicit,
- Explicit
- };
-
- public readonly OpType OperatorType;
- public readonly string ReturnType;
- public readonly string FirstArgType;
- public readonly string FirstArgName;
- public readonly string SecondArgType;
- public readonly string SecondArgName;
- public readonly Block Block;
- public Attributes OptAttributes;
- public MethodBuilder OperatorMethodBuilder;
-
- public string MethodName;
- public Method OperatorMethod;
-
- public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
- string arg2type, string arg2name, Block block, Attributes attrs, Location loc)
- : base ("", loc)
- {
- OperatorType = type;
- ReturnType = ret_type;
- ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
- FirstArgType = arg1type;
- FirstArgName = arg1name;
- SecondArgType = arg2type;
- SecondArgName = arg2name;
- Block = block;
- OptAttributes = attrs;
+ Implements = impl_what;
}
- string Prototype (TypeContainer parent)
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
{
- return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
- SecondArgType + ")";
+ EventBuilder.SetCustomAttribute (cb);
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Event;
+ }
}
public override bool Define (TypeContainer parent)
{
- int length = 1;
- MethodName = "op_" + OperatorType;
-
- if (SecondArgType != null)
- length = 2;
-
- Parameter [] param_list = new Parameter [length];
+ EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
- if ((ModFlags & RequiredModifiers) != RequiredModifiers){
- Report.Error (
- 558, Location,
- "User defined operators `" +
- Prototype (parent) +
- "' must be declared static and public");
+ if (!DoDefine (parent))
+ return false;
+
+ if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
+ Report.Error (31044, Location, "'" + parent.Name + "." + Name +
+ "' : event must be of a delegate type");
return false;
}
- param_list[0] = new Parameter (FirstArgType, FirstArgName,
- Parameter.Modifier.NONE, null);
- if (SecondArgType != null)
- param_list[1] = new Parameter (SecondArgType, SecondArgName,
- Parameter.Modifier.NONE, null);
-
- OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
- new Parameters (param_list, null, Location),
- OptAttributes, Mono.CSharp.Location.Null);
-
- OperatorMethod.Define (parent);
+ Type [] parameter_types = new Type [1];
+ parameter_types [0] = MemberType;
- if (OperatorMethod.MethodBuilder == null)
- return false;
-
- OperatorMethodBuilder = OperatorMethod.MethodBuilder;
+ Parameter [] parms = new Parameter [1];
+ parms [0] = new Parameter (Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
+ /*InternalParameters ip = new InternalParameters (
+ parent, new Parameters (parms, null, Location));
+ */
- Type [] param_types = OperatorMethod.ParameterTypes (parent);
- Type declaring_type = OperatorMethodBuilder.DeclaringType;
- Type return_type = OperatorMethod.GetReturnType (parent);
- Type first_arg_type = param_types [0];
+ if (!CheckBase (parent))
+ return false;
- // Rules for conversion operators
+ AddBuilder = Add.Define (parent);
+ RemoveBuilder = Remove.Define (parent);
- if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
- if (first_arg_type == return_type && first_arg_type == declaring_type){
- Report.Error (
- 555, Location,
- "User-defined conversion cannot take an object of the " +
- "enclosing type and convert to an object of the enclosing" +
- " type");
- return false;
- }
-
- if (first_arg_type != declaring_type && return_type != declaring_type){
- Report.Error (
- 556, Location,
- "User-defined conversion must convert to or from the " +
- "enclosing type");
- return false;
- }
-
- if (first_arg_type == TypeManager.object_type ||
- return_type == TypeManager.object_type){
- Report.Error (
- -8, Location,
- "User-defined conversion cannot convert to or from " +
- "object type");
- return false;
- }
- if (first_arg_type.IsInterface || return_type.IsInterface){
- Report.Error (
- 552, Location,
- "User-defined conversion cannot convert to or from an " +
- "interface type");
- return false;
- }
-
- if (first_arg_type.IsSubclassOf (return_type) ||
- return_type.IsSubclassOf (first_arg_type)){
- Report.Error (
- -10, Location,
- "User-defined conversion cannot convert between types " +
- "that derive from each other");
- return false;
- }
- } else if (SecondArgType == null) {
- // Checks for Unary operators
-
- if (first_arg_type != declaring_type){
- Report.Error (
- 562, Location,
- "The parameter of a unary operator must be the " +
- "containing type");
- return false;
- }
-
- if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
- if (return_type != declaring_type){
- Report.Error (
- 559, Location,
- "The parameter and return type for ++ and -- " +
- "must be the containing type");
- return false;
- }
+ if (!IsExplicitImpl){
+ EventBuilder = new MyEventBuilder (
+ parent.TypeBuilder, Name, e_attr, MemberType);
- }
-
- if (OperatorType == OpType.True || OperatorType == OpType.False) {
- if (return_type != TypeManager.bool_type){
- Report.Error (
- 215, Location,
- "The return type of operator True or False " +
- "must be bool");
- return false;
- }
- }
-
- } else {
- // Checks for Binary operators
-
- if (first_arg_type != declaring_type &&
- param_types [1] != declaring_type){
- Report.Error (
- 563, Location,
- "One of the parameters of a binary operator must " +
- "be the containing type");
+ FieldBuilder = parent.TypeBuilder.DefineField (Name, MemberType,
+ FieldAttributes.FamANDAssem | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
+ TypeManager.RegisterPrivateFieldOfEvent ((EventInfo) EventBuilder, FieldBuilder);
+ TypeManager.RegisterFieldBase (FieldBuilder, this);
+
+ EventBuilder.SetAddOnMethod (AddBuilder);
+ EventBuilder.SetRemoveOnMethod (RemoveBuilder);
+
+ if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
+ Report.Error (111, Location,
+ "Class `" + parent.Name +
+ "' already contains a definition for the event `" +
+ Name + "'");
return false;
}
}
-
+
return true;
}
-
- public void Emit (TypeContainer parent)
- {
- EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
- Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
- //
- // abstract or extern methods have no bodies
- //
- if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
- return;
+ public void EmitDefaultMethod (EmitContext ec, bool is_add)
+ {
+ ILGenerator ig = ec.ig;
+ MethodInfo method = null;
- OperatorMethod.Block = Block;
- OperatorMethod.Emit (parent);
+ if (is_add)
+ method = TypeManager.delegate_combine_delegate_delegate;
+ else
+ method = TypeManager.delegate_remove_delegate_delegate;
+
+ if ((ModFlags & Modifiers.STATIC) != 0) {
+ ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Call, method);
+ ig.Emit (OpCodes.Castclass, MemberType);
+ ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
+ } else {
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
+ ig.Emit (OpCodes.Ldarg_1);
+ ig.Emit (OpCodes.Call, method);
+ ig.Emit (OpCodes.Castclass, MemberType);
+ ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
+ }
+ ig.Emit (OpCodes.Ret);
+ }
+
+ public void Emit (TypeContainer tc)
+ {
+ EmitContext ec;
+
+ ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
+
+ if (OptAttributes != null)
+ OptAttributes.Emit (ec, this);
+
+ Add.Emit (tc);
+ Remove.Emit (tc);
+ }
+
+ public MethodAttributes MethodAttributeFlags {
+ get {
+ return flags;
+ }
}
+
}
- //
- // This is used to compare method signatures
- //
struct MethodSignature {
public string Name;
public Type RetType;
/// </summary>
public static MemberFilter method_signature_filter;
+ /// <summary>
+ /// This delegate is used to extract methods which have the
+ /// same signature as the argument except for the name
+ /// </summary>
+ public static MemberFilter method_signature_noname_filter;
+
/// <summary>
/// This delegate is used to extract inheritable methods which
/// have the same signature as the argument. By inheritable,
/// from the current assembly and class
/// </summary>
public static MemberFilter inheritable_method_signature_filter;
+
+ /// <summary>
+ /// This delegate is used to extract inheritable methods which
+ /// have the same signature as the argument. By inheritable,
+ /// this means that we have permissions to override the method
+ /// from the current assembly and class
+ /// </summary>
+ public static MemberFilter inheritable_property_signature_filter;
static MethodSignature ()
{
method_signature_filter = new MemberFilter (MemberSignatureCompare);
+ method_signature_noname_filter = new MemberFilter (MemberSignatureCompareNoName);
inheritable_method_signature_filter = new MemberFilter (
InheritableMemberSignatureCompare);
+ inheritable_property_signature_filter = new MemberFilter (
+ InheritablePropertySignatureCompare);
}
public MethodSignature (string name, Type ret_type, Type [] parameters)
return true;
}
+ static bool MemberSignatureCompareNoName (MemberInfo m, object filter_criteria)
+ {
+ return MemberSignatureCompare (m, filter_criteria, false);
+ }
+
static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
{
- MethodInfo mi;
+ return MemberSignatureCompare (m, filter_criteria, true);
+ }
+
+ static bool MemberSignatureCompare (MemberInfo m, object filter_criteria, bool use_name)
+ {
+ MethodSignature sig = (MethodSignature) filter_criteria;
- if (! (m is MethodInfo))
+ if (use_name && (m.Name != sig.Name))
return false;
- MethodSignature sig = (MethodSignature) filter_criteria;
+ Type ReturnType;
+ MethodInfo mi = m as MethodInfo;
+ PropertyInfo pi = m as PropertyInfo;
- if (m.Name != sig.Name)
+ if (mi != null)
+ ReturnType = mi.ReturnType;
+ else if (pi != null)
+ ReturnType = pi.PropertyType;
+ else
return false;
-
- mi = (MethodInfo) m;
//
// we use sig.RetType == null to mean `do not check the
// method return value.
//
if (sig.RetType != null)
- if (mi.ReturnType != sig.RetType)
+ if (ReturnType != sig.RetType)
return false;
- Type [] args = TypeManager.GetArgumentTypes (mi);
+ Type [] args;
+ if (mi != null)
+ args = TypeManager.GetArgumentTypes (mi);
+ else
+ args = TypeManager.GetArgumentTypes (pi);
+
Type [] sigp = sig.Parameters;
if (args.Length != sigp.Length)
}
return false;
}
- }
+
+ //
+ // This filter should be used when we are requesting properties that
+ // we want to override.
+ //
+ // This makes a number of assumptions, for example
+ // that the methods being extracted are of a parent
+ // class (this means we know implicitly that we are
+ // being called to find out about members by a derived
+ // class).
+ //
+ static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
+ {
+ if (MemberSignatureCompare (m, filter_criteria)){
+ PropertyInfo pi = (PropertyInfo) m;
+
+ MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
+ MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
+
+ MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
+
+ MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
+
+ // If only accessible to the current class.
+ if (prot == MethodAttributes.Private)
+ return false;
+
+ // If only accessible to the defining assembly or
+ if (prot == MethodAttributes.FamANDAssem ||
+ prot == MethodAttributes.Assembly){
+ if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
+ return true;
+ else
+ return false;
+ }
+
+ // Anything else (FamOrAssembly and Public) is fine
+ return true;
+ }
+ return false;
+ }
+ }
}