void AddressOf (EmitContext ec, AddressOp mode);
}
+ /// <summary>
+ /// We are either a namespace or a type.
+ /// If we're a type, `IsType' is true and we may use `Type' to get
+ /// a TypeExpr representing that type.
+ /// </summary>
+ public interface IAlias {
+ bool IsType {
+ get;
+ }
+
+ string Name {
+ get;
+ }
+
+ TypeExpr Type {
+ get;
+ }
+ }
+
/// <summary>
/// This interface is implemented by variables
/// </summary>
// value will be returned if the expression is not a type
// reference
//
- public Expression ResolveAsTypeTerminal (EmitContext ec)
+ public TypeExpr ResolveAsTypeTerminal (EmitContext ec)
{
- Expression e = ResolveAsTypeStep (ec);
-
- if (e == null)
- return null;
- if (e is SimpleName)
- return null;
- return e;
+ return ResolveAsTypeStep (ec) as TypeExpr;
}
/// <summary>
break;
case ExprClass.MethodGroup:
+ if (!RootContext.V2){
if ((flags & ResolveFlags.MethodGroup) == 0) {
((MethodGroupExpr) e).ReportUsageError ();
return null;
}
+ }
break;
case ExprClass.Value:
return null;
}
- if (e.type == null)
+ if ((e.type == null) && !(e is ConstructedType))
throw new Exception ("Expression " + e +
" did not set its type after Resolve");
}
/// </remarks>
public abstract void Emit (EmitContext ec);
+ public virtual void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+ {
+ Emit (ec);
+ ec.ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+ }
+
/// <summary>
/// Protected constructor. Only derivate types should
/// be able to be created
else if (t == TypeManager.bool_type)
return new BoolConstant ((bool) v);
else if (TypeManager.IsEnumType (t)){
- Constant e = Constantify (v, TypeManager.TypeToCoreType (v.GetType ()));
+ Type real_type = TypeManager.TypeToCoreType (v.GetType ());
+ if (real_type == t)
+ real_type = real_type.UnderlyingSystemType;
+
+ Constant e = Constantify (v, real_type);
return new EnumConstant (e, t);
} else
else if (mi is PropertyInfo)
return new PropertyExpr (ec, (PropertyInfo) mi, loc);
else if (mi is Type){
- return new TypeExpr ((System.Type) mi, loc);
+ return new TypeExpression ((System.Type) mi, loc);
}
return null;
string name, MemberTypes mt,
BindingFlags bf, Location loc)
{
- MemberInfo [] mi = TypeManager.MemberLookup (container_type, qualifier_type,
- queried_type, mt, bf, name);
+ MemberInfo [] mi = TypeManager.MemberLookup (
+ container_type, qualifier_type,queried_type, mt, bf, name);
if (mi == null)
return null;
/// find it.
/// </summary>
public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
- Type queried_type, string name, Location loc)
+ Type queried_type, string name,
+ Location loc)
{
return MemberLookupFinal (ec, qualifier_type, queried_type, name,
AllMemberTypes, AllBindingFlags, loc);
if (errors < Report.Errors)
return null;
- MemberLookupFailed (ec, qualifier_type, queried_type, name, null, loc);
+ MemberLookupFailed (ec, qualifier_type, queried_type, name,
+ null, loc);
return null;
}
Type queried_type, string name,
string class_name, Location loc)
{
- object lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
- AllMemberTypes, AllBindingFlags |
- BindingFlags.NonPublic, name);
+ MemberInfo[] mi = TypeManager.MemberLookup (queried_type, null, queried_type,
+ AllMemberTypes, AllBindingFlags |
+ BindingFlags.NonPublic, name);
- if (lookup == null) {
+ if (mi == null) {
if (class_name != null)
Report.Error (103, loc, "The name `" + name + "' could not be " +
"found in `" + class_name + "'");
return;
}
+ if (TypeManager.MemberLookup (queried_type, null, queried_type,
+ AllMemberTypes, AllBindingFlags |
+ BindingFlags.NonPublic, name) == null) {
+ if ((mi.Length == 1) && (mi [0] is Type)) {
+ Type t = (Type) mi [0];
+
+ Report.Error (305, loc,
+ "Using the generic type `{0}' " +
+ "requires {1} type arguments",
+ TypeManager.GetFullName (t),
+ TypeManager.GetNumberOfTypeArguments (t));
+ return;
+ }
+ }
+
if ((qualifier_type != null) && (qualifier_type != ec.ContainerType) &&
ec.ContainerType.IsSubclassOf (qualifier_type)) {
// Although a derived class can access protected members of
// ec.ContainerType and the lookup succeeds with the latter one,
// then we are in this situation.
- lookup = TypeManager.MemberLookup (
+ mi = TypeManager.MemberLookup (
ec.ContainerType, ec.ContainerType, ec.ContainerType,
AllMemberTypes, AllBindingFlags, name);
- if (lookup != null) {
+ if (mi != null) {
Report.Error (
1540, loc, "Cannot access protected member `" +
TypeManager.CSharpName (qualifier_type) + "." +
Report.Error (
122, loc, "`" + TypeManager.CSharpName (qualifier_type) + "." +
name + "' is inaccessible due to its protection level");
- else
+ else if (name == ".ctor") {
+ Report.Error (143, loc, String.Format ("The type {0} has no constructors defined",
+ TypeManager.CSharpName (queried_type)));
+ } else {
Report.Error (
122, loc, "`" + name + "' is inaccessible due to its " +
"protection level");
}
+ }
static public MemberInfo GetFieldFromEvent (EventExpr event_expr)
{
ArrayList arguments = new ArrayList ();
arguments.Add (new Argument (e, Argument.AType.Expression));
- method = Invocation.OverloadResolve (ec, (MethodGroupExpr) operator_group, arguments, loc);
+ method = Invocation.OverloadResolve (
+ ec, (MethodGroupExpr) operator_group, arguments, false, loc);
if (method == null)
return null;
"a `" + sb.ToString () + "' was expected");
}
- static void Error_ConstantValueCannotBeConverted (Location l, string val, Type t)
+ static public void Error_ConstantValueCannotBeConverted (Location l, string val, Type t)
{
Report.Error (31, l, "Constant value `" + val + "' cannot be converted to " +
TypeManager.CSharpName (t));
public class EmptyCast : Expression {
protected Expression child;
+ public Expression Child {
+ get {
+ return child;
+ }
+ }
+
public EmptyCast (Expression child, Type return_type)
{
eclass = child.eclass;
{
return Child.ConvertToInt ();
}
+
+ public override bool IsZeroInteger {
+ get { return Child.IsZeroInteger; }
+ }
}
/// <summary>
public BoxedCast (Expression expr)
: base (expr, TypeManager.object_type)
{
+ eclass = ExprClass.Value;
}
public BoxedCast (Expression expr, Type target_type)
: base (expr, target_type)
{
+ eclass = ExprClass.Value;
}
public override Expression DoResolve (EmitContext ec)
ILGenerator ig = ec.ig;
base.Emit (ec);
- ig.Emit (OpCodes.Unbox, t);
+ if (t.IsGenericParameter)
+ ig.Emit (OpCodes.Unbox_Any, t);
+ else {
+ ig.Emit (OpCodes.Unbox, t);
- LoadFromPtr (ig, t);
+ LoadFromPtr (ig, t);
+ }
}
}
{
base.Emit (ec);
- ec.ig.Emit (OpCodes.Castclass, type);
- }
-
+ if (child.Type.IsGenericParameter)
+ ec.ig.Emit (OpCodes.Box, child.Type);
+
+ if (type.IsGenericParameter)
+ ec.ig.Emit (OpCodes.Unbox_Any, type);
+ else
+ ec.ig.Emit (OpCodes.Castclass, type);
+ }
}
/// <summary>
public override Expression ResolveAsTypeStep (EmitContext ec)
{
DeclSpace ds = ec.DeclSpace;
- NamespaceEntry ns = ds.Namespace;
- Type t;
- string alias_value;
+ NamespaceEntry ns = ds.NamespaceEntry;
+ TypeExpr t;
+ IAlias alias_value;
//
// Since we are cheating: we only do the Alias lookup for
else
alias_value = null;
- if (ec.ResolvingTypeTree){
- if (alias_value != null){
- if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null)
- return new TypeExpr (t, loc);
- }
+ TypeParameterExpr generic_type = ds.LookupGeneric (Name, loc);
+ if (generic_type != null)
+ return generic_type.ResolveAsTypeTerminal (ec);
+ if (ec.ResolvingTypeTree){
int errors = Report.Errors;
- Type dt = ec.DeclSpace.FindType (loc, Name);
+ Type dt = ds.FindType (loc, Name);
if (Report.Errors != errors)
return null;
if (dt != null)
- return new TypeExpr (dt, loc);
+ return new TypeExpression (dt, loc);
+
+ if (alias_value != null){
+ if (alias_value.IsType)
+ return alias_value.Type;
+ if ((t = RootContext.LookupType (ds, alias_value.Name, true, loc)) != null)
+ return t;
+ }
}
//
// First, the using aliases
//
if (alias_value != null){
- if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null)
- return new TypeExpr (t, loc);
+ if (alias_value.IsType)
+ return alias_value.Type;
+ if ((t = RootContext.LookupType (ds, alias_value.Name, true, loc)) != null)
+ return t;
// we have alias value, but it isn't Type, so try if it's namespace
- return new SimpleName (alias_value, loc);
+ return new SimpleName (alias_value.Name, loc);
}
- if (ec.IsGeneric){
- TypeParameterExpr generic_type = ds.LookupGeneric (Name, loc);
-
- if (generic_type != null)
- return generic_type;
- }
-
//
// Stage 2: Lookup up if we are an alias to a type
// or a namespace.
//
if ((t = RootContext.LookupType (ds, Name, true, loc)) != null)
- return new TypeExpr (t, loc);
+ return t;
// No match, maybe our parent can compose us
// into something meaningful.
{
Expression e = null;
- //
- // Since we are cheating (is_base is our hint
- // that we are the beginning of the name): we
- // only do the Alias lookup for namespaces if
- // the name does not include any dots in it
- //
- NamespaceEntry ns = ec.DeclSpace.Namespace;
- if (is_base && ns != null){
- string alias_value = ns.LookupAlias (Name);
- if (alias_value != null){
- Name = alias_value;
- Type t;
-
- if ((t = TypeManager.LookupType (Name)) != null)
- return new TypeExpr (t, loc);
-
- // No match, maybe our parent can compose us
- // into something meaningful.
- return this;
- }
- }
-
-
//
// Stage 1: Performed by the parser (binding to locals or parameters).
//
Block current_block = ec.CurrentBlock;
if (current_block != null){
+ if (is_base && current_block.IsVariableNameUsedInChildBlock(Name)) {
+ Report.Error (135, Location, "'" + Name + "' has a different meaning in a child block");
+ return null;
+ }
+
LocalInfo vi = current_block.GetLocalInfo (Name);
if (vi != null){
Expression var;
if (e == null && ec.ContainerType != null)
e = MemberLookup (ec, ec.ContainerType, Name, loc);
- if (e == null)
+ if (e == null) {
+ //
+ // Since we are cheating (is_base is our hint
+ // that we are the beginning of the name): we
+ // only do the Alias lookup for namespaces if
+ // the name does not include any dots in it
+ //
+ NamespaceEntry ns = ec.DeclSpace.NamespaceEntry;
+ if (is_base && ns != null){
+ IAlias alias_value = ns.LookupAlias (Name);
+ if (alias_value != null){
+ if (alias_value.IsType)
+ return alias_value.Type;
+
+ Name = alias_value.Name;
+ Type t;
+
+ if ((t = TypeManager.LookupType (Name)) != null)
+ return new TypeExpression (t, loc);
+
+ // No match, maybe our parent can compose us
+ // into something meaningful.
+ return this;
+ }
+ }
+
return ResolveAsTypeStep (ec);
+ }
if (e is TypeExpr)
return e;
/// <summary>
/// Fully resolved expression that evaluates to a type
/// </summary>
- public class TypeExpr : Expression {
- public TypeExpr (Type t, Location l)
+ public abstract class TypeExpr : Expression, IAlias {
+ override public Expression ResolveAsTypeStep (EmitContext ec)
{
- Type = t;
- eclass = ExprClass.Type;
- loc = l;
- }
+ TypeExpr t = DoResolveAsTypeStep (ec);
+ if (t == null)
+ return null;
- public override Expression ResolveAsTypeStep (EmitContext ec)
- {
- return this;
+ eclass = ExprClass.Type;
+ return t;
}
override public Expression DoResolve (EmitContext ec)
{
- return this;
+ return ResolveAsTypeTerminal (ec);
}
override public void Emit (EmitContext ec)
throw new Exception ("Should never be called");
}
+ public virtual bool CheckAccessLevel (DeclSpace ds)
+ {
+ return ds.CheckAccessLevel (Type);
+ }
+
+ public virtual bool AsAccessible (DeclSpace ds, int flags)
+ {
+ return ds.AsAccessible (Type, flags);
+ }
+
+ public virtual bool IsClass {
+ get { return Type.IsClass; }
+ }
+
+ public virtual bool IsValueType {
+ get { return Type.IsValueType; }
+ }
+
+ public virtual bool IsInterface {
+ get { return Type.IsInterface; }
+ }
+
+ public virtual bool IsSealed {
+ get { return Type.IsSealed; }
+ }
+
+ public virtual bool CanInheritFrom ()
+ {
+ if (Type == TypeManager.enum_type ||
+ (Type == TypeManager.value_type && RootContext.StdLib) ||
+ Type == TypeManager.multicast_delegate_type ||
+ Type == TypeManager.delegate_type ||
+ Type == TypeManager.array_type)
+ return false;
+
+ return true;
+ }
+
+ public virtual bool IsAttribute {
+ get {
+ return Type == TypeManager.attribute_type ||
+ Type.IsSubclassOf (TypeManager.attribute_type);
+ }
+ }
+
+ public virtual TypeExpr[] GetInterfaces ()
+ {
+ return TypeManager.GetInterfaces (Type);
+ }
+
+ public abstract TypeExpr DoResolveAsTypeStep (EmitContext ec);
+
+ public virtual Type ResolveType (EmitContext ec)
+ {
+ TypeExpr t = ResolveAsTypeTerminal (ec);
+ if (t == null)
+ return null;
+
+ return t.Type;
+ }
+
+ public abstract string Name {
+ get;
+ }
+
+ public override bool Equals (object obj)
+ {
+ TypeExpr tobj = obj as TypeExpr;
+ if (tobj == null)
+ return false;
+
+ return Type == tobj.Type;
+ }
+
+ public override int GetHashCode ()
+ {
+ return Type.GetHashCode ();
+ }
+
public override string ToString ()
{
- return Type.ToString ();
+ return Name;
+ }
+
+ bool IAlias.IsType {
+ get { return true; }
+ }
+
+ TypeExpr IAlias.Type {
+ get {
+ return this;
+ }
+ }
+ }
+
+ public class TypeExpression : TypeExpr, IAlias {
+ public TypeExpression (Type t, Location l)
+ {
+ Type = t;
+ eclass = ExprClass.Type;
+ loc = l;
+ }
+
+ public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
+ {
+ return this;
+ }
+
+ public override string Name {
+ get {
+ return Type.ToString ();
+ }
+ }
+
+ string IAlias.Name {
+ get {
+ return Type.FullName != null ? Type.FullName : Type.Name;
+ }
}
}
public class TypeLookupExpression : TypeExpr {
string name;
- public TypeLookupExpression (string name) : base (null, Location.Null)
+ public TypeLookupExpression (string name)
{
this.name = name;
}
- public override Expression ResolveAsTypeStep (EmitContext ec)
+ public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
{
- if (type == null)
- type = RootContext.LookupType (ec.DeclSpace, name, false, Location.Null);
+ if (type == null) {
+ TypeExpr texpr = RootContext.LookupType (
+ ec.DeclSpace, name, false, Location.Null);
+ if (texpr == null)
+ return null;
+
+ type = texpr.ResolveType (ec);
+ if (type == null)
+ return null;
+ }
+
return this;
}
- public override Expression DoResolve (EmitContext ec)
+ public override string Name {
+ get {
+ return name;
+ }
+ }
+ }
+
+ public class TypeAliasExpression : TypeExpr, IAlias {
+ TypeExpr texpr;
+ TypeArguments args;
+ string name;
+
+ public TypeAliasExpression (TypeExpr texpr, TypeArguments args, Location l)
{
- return ResolveAsTypeStep (ec);
+ this.texpr = texpr;
+ this.args = args;
+ loc = texpr.Location;
+
+ eclass = ExprClass.Type;
+ if (args != null)
+ name = texpr.Name + "<" + args.ToString () + ">";
+ else
+ name = texpr.Name;
}
- public override void Emit (EmitContext ec)
+ public override string Name {
+ get { return name; }
+ }
+
+ public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
{
- throw new Exception ("Should never be called");
+ Type type = texpr.ResolveType (ec);
+ if (type == null)
+ return null;
+
+ int num_args = TypeManager.GetNumberOfTypeArguments (type);
+
+ if (args != null) {
+ if (num_args == 0) {
+ Report.Error (308, loc,
+ "The non-generic type `{0}' cannot " +
+ "be used with type arguments.",
+ TypeManager.CSharpName (type));
+ return null;
+ }
+
+ ConstructedType ctype = new ConstructedType (type, args, loc);
+ return ctype.ResolveAsTypeTerminal (ec);
+ } else if (num_args > 0) {
+ Report.Error (305, loc,
+ "Using the generic type `{0}' " +
+ "requires {1} type arguments",
+ TypeManager.GetFullName (type), num_args);
+ return null;
+ }
+
+ return new TypeExpression (type, loc);
}
- public override string ToString ()
+ public override Type ResolveType (EmitContext ec)
+ {
+ TypeExpr t = ResolveAsTypeTerminal (ec);
+ if (t == null)
+ return null;
+
+ type = t.ResolveType (ec);
+ return type;
+ }
+
+ public override bool CheckAccessLevel (DeclSpace ds)
+ {
+ return texpr.CheckAccessLevel (ds);
+ }
+
+ public override bool AsAccessible (DeclSpace ds, int flags)
{
- return name;
+ return texpr.AsAccessible (ds, flags);
+ }
+
+ public override bool IsClass {
+ get { return texpr.IsClass; }
+ }
+
+ public override bool IsValueType {
+ get { return texpr.IsValueType; }
+ }
+
+ public override bool IsInterface {
+ get { return texpr.IsInterface; }
+ }
+
+ public override bool IsSealed {
+ get { return texpr.IsSealed; }
+ }
+
+ public override bool IsAttribute {
+ get { return texpr.IsAttribute; }
}
}
public MethodBase [] Methods;
Expression instance_expression = null;
bool is_explicit_impl = false;
+ bool has_type_arguments = false;
public MethodGroupExpr (MemberInfo [] mi, Location l)
{
}
}
+ public bool HasTypeArguments {
+ get {
+ return has_type_arguments;
+ }
+
+ set {
+ has_type_arguments = value;
+ }
+ }
+
public string Name {
get {
- //return Methods [0].Name;
- return Methods [Methods.Length - 1].Name;
+ return TypeManager.CSharpSignature (
+ Methods [Methods.Length - 1]);
}
}
{
FieldInfo = fi;
eclass = ExprClass.Variable;
- type = fi.FieldType;
+ type = TypeManager.TypeToCoreType (fi.FieldType);
loc = l;
}
FieldBase fb = TypeManager.GetField (FieldInfo);
if (fb != null)
- fb.IsAssigned = true;
+ fb.SetAssigned ();
//
// InitOnly fields can only be assigned in constructors
//
if (ec.IsConstructor){
- if (ec.ContainerType == FieldInfo.DeclaringType)
+ if (IsStatic && !ec.IsStatic)
+ Report_AssignToReadonly (false);
+
+ Type ctype;
+ if (ec.TypeContainer.CurrentType != null)
+ ctype = ec.TypeContainer.CurrentType.ResolveType (ec);
+ else
+ ctype = ec.ContainerType;
+
+ if (TypeManager.IsEqual (ctype, FieldInfo.DeclaringType))
return this;
}
if (FieldInfo is FieldBuilder){
FieldBase f = TypeManager.GetField (FieldInfo);
-
- if ((f.ModFlags & Modifiers.VOLATILE) != 0)
- is_volatile = true;
-
- f.status |= Field.Status.USED;
+ if (f != null){
+ if ((f.ModFlags & Modifiers.VOLATILE) != 0)
+ is_volatile = true;
+
+ f.status |= Field.Status.USED;
+ }
}
if (FieldInfo.IsStatic){
if (!(instance_expr is IMemoryLocation)){
tempo = new LocalTemporary (ec, instance_expr.Type);
- if (ec.RemapToProxy)
- ec.EmitThis ();
-
InstanceExpression.Emit (ec);
tempo.Store (ec);
ml = tempo;
ml.AddressOf (ec, AddressOp.Load);
} else {
- if (ec.RemapToProxy)
- ec.EmitThis ();
- else
- instance_expr.Emit (ec);
+ instance_expr.Emit (ec);
}
if (is_volatile)
ig.Emit (OpCodes.Volatile);
Report_AssignToReadonly (!is_static);
return;
}
-
+
if (!is_static){
Expression instance = instance_expr;
ml.AddressOf (ec, AddressOp.Store);
} else {
- if (ec.RemapToProxy)
- ec.EmitThis ();
- else
- instance.Emit (ec);
+ instance.Emit (ec);
}
}
if (FieldInfo is FieldBuilder){
FieldBase f = TypeManager.GetField (FieldInfo);
-
- if ((f.ModFlags & Modifiers.VOLATILE) != 0)
- ig.Emit (OpCodes.Volatile);
-
- f.status |= Field.Status.ASSIGNED;
+ if (f != null){
+ if ((f.ModFlags & Modifiers.VOLATILE) != 0)
+ ig.Emit (OpCodes.Volatile);
+
+ f.status |= Field.Status.ASSIGNED;
+ }
}
if (is_static)
if (FieldInfo is FieldBuilder){
FieldBase f = TypeManager.GetField (FieldInfo);
- if ((f.ModFlags & Modifiers.VOLATILE) != 0){
- Error (676, "volatile variable: can not take its address, or pass as ref/out parameter");
- return;
+ if (f != null){
+ if ((f.ModFlags & Modifiers.VOLATILE) != 0){
+ Error (676, "volatile variable: can not take its address, or pass as ref/out parameter");
+ return;
+ }
+
+ if ((mode & AddressOp.Store) != 0)
+ f.status |= Field.Status.ASSIGNED;
+ if ((mode & AddressOp.Load) != 0)
+ f.status |= Field.Status.USED;
}
-
- if ((mode & AddressOp.Store) != 0)
- f.status |= Field.Status.ASSIGNED;
- if ((mode & AddressOp.Load) != 0)
- f.status |= Field.Status.USED;
}
//
// Handle initonly fields specially: make a copy and then
// get the address of the copy.
//
- if (FieldInfo.IsInitOnly && !ec.IsConstructor){
+ bool need_copy;
+ if (FieldInfo.IsInitOnly){
+ need_copy = true;
+ if (ec.IsConstructor){
+ if (FieldInfo.IsStatic){
+ if (ec.IsStatic)
+ need_copy = false;
+ } else
+ need_copy = false;
+ }
+ } else
+ need_copy = false;
+
+ if (need_copy){
LocalBuilder local;
-
Emit (ec);
local = ig.DeclareLocal (type);
ig.Emit (OpCodes.Stloc, local);
return;
}
- if (FieldInfo.IsStatic)
+
+ if (FieldInfo.IsStatic){
ig.Emit (OpCodes.Ldsflda, FieldInfo);
- else {
+ } else {
//
// In the case of `This', we call the AddressOf method, which will
// only load the pointer, and not perform an Ldobj immediately after
IMemoryLocation ml = (IMemoryLocation) instance_expr;
ml.AddressOf (ec, AddressOp.LoadStore);
- } else
+ } else {
instance_expr.Emit (ec);
+
+ if (instance_expr.Type.IsValueType) {
+ LocalBuilder local = ig.DeclareLocal (instance_expr.Type);
+ ig.Emit(OpCodes.Stloc, local);
+ ig.Emit(OpCodes.Ldloca, local);
+ ig.Emit(OpCodes.Ldfld, FieldInfo);
+ LocalBuilder local2 = ig.DeclareLocal(type);
+ ig.Emit(OpCodes.Stloc, local2);
+ ig.Emit(OpCodes.Ldloca, local2);
+ return;
+ }
+ }
ig.Emit (OpCodes.Ldflda, FieldInfo);
}
}
}
+ //
+ // A FieldExpr whose address can not be taken
+ //
+ public class FieldExprNoAddress : FieldExpr, IMemoryLocation {
+ public FieldExprNoAddress (FieldInfo fi, Location loc) : base (fi, loc)
+ {
+ }
+
+ public new void AddressOf (EmitContext ec, AddressOp mode)
+ {
+ Report.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
+ }
+ }
+
/// <summary>
/// Expression that evaluates to a Property. The Assign class
/// might set the `Value' expression if we are in an assignment.
return true;
}
- MethodInfo GetAccessor (Type invocation_type, string accessor_name)
+ MethodInfo FindAccessor (Type invocation_type, bool is_set)
{
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
- BindingFlags.Static | BindingFlags.Instance;
- MemberInfo[] group;
+ BindingFlags.Static | BindingFlags.Instance |
+ BindingFlags.DeclaredOnly;
- group = TypeManager.MemberLookup (
- invocation_type, invocation_type, PropertyInfo.DeclaringType,
- MemberTypes.Method, flags, accessor_name + "_" + PropertyInfo.Name);
+ Type current = PropertyInfo.DeclaringType;
+ for (; current != null; current = current.BaseType) {
+ MemberInfo[] group = TypeManager.MemberLookup (
+ invocation_type, invocation_type, current,
+ MemberTypes.Property, flags, PropertyInfo.Name);
- //
- // The first method is the closest to us
- //
- if (group == null)
+ if (group == null)
+ continue;
+
+ if (group.Length != 1)
+ // Oooops, can this ever happen ?
+ return null;
+
+ PropertyInfo pi = (PropertyInfo) group [0];
+
+ MethodInfo get = pi.GetGetMethod (true);
+ MethodInfo set = pi.GetSetMethod (true);
+
+ if (is_set) {
+ if (set != null)
+ return set;
+ } else {
+ if (get != null)
+ return get;
+ }
+
+ MethodInfo accessor = get != null ? get : set;
+ if (accessor == null)
+ continue;
+ if ((accessor.Attributes & MethodAttributes.NewSlot) != 0)
+ break;
+ }
+
+ return null;
+ }
+
+ MethodInfo GetAccessor (Type invocation_type, bool is_set)
+ {
+ MethodInfo mi = FindAccessor (invocation_type, is_set);
+ if (mi == null)
return null;
- foreach (MethodInfo mi in group) {
- MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;
+ MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;
- //
- // If only accessible to the current class or children
- //
- if (ma == MethodAttributes.Private) {
- Type declaring_type = mi.DeclaringType;
+ //
+ // If only accessible to the current class or children
+ //
+ if (ma == MethodAttributes.Private) {
+ Type declaring_type = mi.DeclaringType;
- if (invocation_type != declaring_type){
- if (TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType))
- return mi;
- else
- continue;
- } else
+ if (invocation_type != declaring_type){
+ if (TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType))
return mi;
- }
- //
- // FamAndAssem requires that we not only derivate, but we are on the
- // same assembly.
- //
- if (ma == MethodAttributes.FamANDAssem){
- if (mi.DeclaringType.Assembly != invocation_type.Assembly)
- continue;
else
- return mi;
- }
+ return null;
+ } else
+ return mi;
+ }
+ //
+ // FamAndAssem requires that we not only derivate, but we are on the
+ // same assembly.
+ //
+ if (ma == MethodAttributes.FamANDAssem){
+ if (mi.DeclaringType.Assembly != invocation_type.Assembly)
+ return null;
+ else
+ return mi;
+ }
- // Assembly and FamORAssem succeed if we're in the same assembly.
- if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
- if (mi.DeclaringType.Assembly != invocation_type.Assembly)
- continue;
- else
- return mi;
- }
+ // Assembly and FamORAssem succeed if we're in the same assembly.
+ if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
+ if (mi.DeclaringType.Assembly == invocation_type.Assembly)
+ return mi;
+ }
- // We already know that we aren't in the same assembly.
- if (ma == MethodAttributes.Assembly)
- continue;
+ // We already know that we aren't in the same assembly.
+ if (ma == MethodAttributes.Assembly)
+ return null;
- // Family and FamANDAssem require that we derive.
- if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
- if (!TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType))
- continue;
- else {
+ // Family and FamANDAssem require that we derive.
+ if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem) || (ma == MethodAttributes.FamORAssem)){
+ if (!TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType))
+ return null;
+ else {
+ if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType))
must_do_cs1540_check = true;
- return mi;
- }
+ return mi;
}
-
- return mi;
}
- return null;
+ return mi;
}
//
//
void ResolveAccessors (EmitContext ec)
{
- getter = GetAccessor (ec.ContainerType, "get");
+ getter = GetAccessor (ec.ContainerType, false);
if ((getter != null) && getter.IsStatic)
is_static = true;
- setter = GetAccessor (ec.ContainerType, "set");
+ setter = GetAccessor (ec.ContainerType, true);
if ((setter != null) && setter.IsStatic)
is_static = true;
override public Expression DoResolve (EmitContext ec)
{
+ if (getter != null){
+ if (TypeManager.GetArgumentTypes (getter).Length != 0){
+ Report.Error (
+ 117, loc, "`{0}' does not contain a " +
+ "definition for `{1}'.", getter.DeclaringType,
+ Name);
+ return null;
+ }
+ }
+
if (getter == null){
//
// The following condition happens if the PropertyExpr was
return null;
}
+ if (TypeManager.GetArgumentTypes (setter).Length != 1){
+ Report.Error (
+ 117, loc, "`{0}' does not contain a " +
+ "definition for `{1}'.", getter.DeclaringType,
+ Name);
+ return null;
+ }
+
if (!InstanceResolve (ec))
return null;
if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)){
instance_expr.Emit (ec);
ec.ig.Emit (OpCodes.Ldlen);
+ ec.ig.Emit (OpCodes.Conv_I4);
return;
}
}
public void EmitAddOrRemove (EmitContext ec, Expression source)
{
- Expression handler = ((Binary) source).Right;
+ BinaryDelegate source_del = (BinaryDelegate) source;
+ Expression handler = source_del.Right;
Argument arg = new Argument (handler, Argument.AType.Expression);
ArrayList args = new ArrayList ();
args.Add (arg);
- if (((Binary) source).Oper == Binary.Operator.Addition)
+ if (source_del.IsAddition)
Invocation.EmitCall (
ec, false, IsStatic, instance_expr, add_accessor, args, loc);
else