get;
}
+ /// <summary>
+ /// The type which declares this member.
+ /// </summary>
+ Type DeclaringType {
+ get;
+ }
+
/// <summary>
/// The instance expression associated with this member, if it's a
/// non-static member.
SimpleName s = (SimpleName) e;
if ((flags & ResolveFlags.SimpleName) == 0) {
- Report.Error (
- 103, loc,
- "The name `" + s.Name + "' could not be found in `" +
- ec.DeclSpace.Name + "'");
+
+ object lookup = TypeManager.MemberLookup (
+ ec.ContainerType, ec.ContainerType, AllMemberTypes,
+ AllBindingFlags | BindingFlags.NonPublic, s.Name);
+ if (lookup != null)
+ Error (122, "`" + s.Name + "' " +
+ "is inaccessible because of its protection level");
+ else
+ Error (103, "The name `" + s.Name + "' could not be " +
+ "found in `" + ec.DeclSpace.Name + "'");
return null;
}
else if (mi is FieldInfo)
return new FieldExpr ((FieldInfo) mi, loc);
else if (mi is PropertyInfo)
- return new PropertyExpr ((PropertyInfo) mi, loc);
+ return new PropertyExpr (ec, (PropertyInfo) mi, loc);
else if (mi is Type){
return new TypeExpr ((System.Type) mi, loc);
}
return MemberLookup (ec, ec.ContainerType, t, name, mt, bf, loc);
}
+ //
+ // Lookup type `t' for code in class `invocation_type'. Note that it's important
+ // to set `invocation_type' correctly since this method also checks whether the
+ // invoking class is allowed to access the member in class `t'. When you want to
+ // explicitly do a lookup in the base class, you must set both `t' and `invocation_type'
+ // to the base class (although a derived class can access protected members of its base
+ // class it cannot do so through an instance of the base class (error CS1540)).
+ //
+
public static Expression MemberLookup (EmitContext ec, Type invocation_type, Type t,
string name, MemberTypes mt, BindingFlags bf,
Location loc)
expr.Emit (null);
}
-
- if (target_type == TypeManager.object_type) {
+
+ //
+ // notice that it is possible to write "ValueType v = 1", the ValueType here
+ // is an abstract class, and not really a value type, so we apply the same rules.
+ //
+ if (target_type == TypeManager.object_type || target_type == TypeManager.value_type) {
//
// A pointer type cannot be converted to object
//
if (expr_type.IsClass || expr_type.IsInterface)
return new EmptyCast (expr, target_type);
} else if (expr_type.IsSubclassOf (target_type)) {
+ //
+ // Special case: enumeration to System.Enum.
+ // System.Enum is not a value type, it is a class, so we need
+ // a boxing conversion
+ //
+ if (expr_type.IsEnum)
+ return new BoxedCast (expr);
+
return new EmptyCast (expr, target_type);
} else {
return new EmptyCast (expr, target_type);
// from any class-type S to any interface-type T.
- if (expr_type.IsClass && target_type.IsInterface) {
- if (TypeManager.ImplementsInterface (expr_type, target_type))
- return new EmptyCast (expr, target_type);
- else
- return null;
+ if (target_type.IsInterface) {
+ if (TypeManager.ImplementsInterface (expr_type, target_type)){
+ if (expr_type.IsClass)
+ return new EmptyCast (expr, target_type);
+ else if (expr_type.IsValueType)
+ return new BoxedCast (expr);
+ }
}
// from any interface type S to interface-type T.
if (expr_type.IsInterface && target_type.IsInterface) {
-
if (TypeManager.ImplementsInterface (expr_type, target_type))
return new EmptyCast (expr, target_type);
else
return null;
}
- /// <summary>
- /// Handles expressions like this: decimal d; d = 1;
- /// and changes them into: decimal d; d = new System.Decimal (1);
- /// </summary>
- static Expression InternalTypeConstructor (EmitContext ec, Expression expr, Type target)
- {
- ArrayList args = new ArrayList ();
-
- args.Add (new Argument (expr, Argument.AType.Expression));
-
- Expression ne = new New (new TypeExpr (target, Location.Null), args, Location.Null);
-
- return ne.Resolve (ec);
- }
-
/// <summary>
/// Implicit Numeric Conversions.
///
return new ULongConstant ((ulong) v);
}
- //
- // If we have an enumeration, extract the underlying type,
- // use this during the comparission, but wrap around the original
- // target_type
- //
- Type real_target_type = target_type;
-
- if (TypeManager.IsEnumType (real_target_type))
- real_target_type = TypeManager.EnumToUnderlying (real_target_type);
+ Type real_target_type = target_type;
- if (expr_type == real_target_type)
- return new EmptyCast (expr, target_type);
-
if (expr_type == TypeManager.sbyte_type){
//
// From sbyte to short, int, long, float, double.
return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
if (real_target_type == TypeManager.short_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
- if (real_target_type == TypeManager.decimal_type)
- return InternalTypeConstructor (ec, expr, target_type);
} else if (expr_type == TypeManager.byte_type){
//
// From byte to short, ushort, int, uint, long, ulong, float, double
return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
if (real_target_type == TypeManager.double_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
- if (real_target_type == TypeManager.decimal_type)
- return InternalTypeConstructor (ec, expr, target_type);
} else if (expr_type == TypeManager.short_type){
//
// From short to int, long, float, double
return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
if (real_target_type == TypeManager.float_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
- if (real_target_type == TypeManager.decimal_type)
- return InternalTypeConstructor (ec, expr, target_type);
} else if (expr_type == TypeManager.ushort_type){
//
// From ushort to int, uint, long, ulong, float, double
return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
if (real_target_type == TypeManager.float_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
- if (real_target_type == TypeManager.decimal_type)
- return InternalTypeConstructor (ec, expr, target_type);
} else if (expr_type == TypeManager.int32_type){
//
// From int to long, float, double
return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
if (real_target_type == TypeManager.float_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
- if (real_target_type == TypeManager.decimal_type)
- return InternalTypeConstructor (ec, expr, target_type);
} else if (expr_type == TypeManager.uint32_type){
//
// From uint to long, ulong, float, double
if (real_target_type == TypeManager.float_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
OpCodes.Conv_R4);
- if (real_target_type == TypeManager.decimal_type)
- return InternalTypeConstructor (ec, expr, target_type);
} else if (expr_type == TypeManager.int64_type){
//
// From long/ulong to float, double
return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
if (real_target_type == TypeManager.float_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
- if (real_target_type == TypeManager.decimal_type)
- return InternalTypeConstructor (ec, expr, target_type);
} else if (expr_type == TypeManager.uint64_type){
//
// From ulong to float, double
if (real_target_type == TypeManager.float_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
OpCodes.Conv_R4);
- if (real_target_type == TypeManager.decimal_type)
- return InternalTypeConstructor (ec, expr, target_type);
} else if (expr_type == TypeManager.char_type){
//
// From char to ushort, int, uint, long, ulong, float, double
return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
if (real_target_type == TypeManager.double_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
- if (real_target_type == TypeManager.decimal_type)
- return InternalTypeConstructor (ec, expr, target_type);
} else if (expr_type == TypeManager.float_type){
//
// float to double
} else if (expr_type.IsSubclassOf (target_type)) {
return true;
-
} else {
// Please remember that all code below actually comes
// from ImplicitReferenceConversion so make sure code remains in sync
// from any class-type S to any interface-type T.
- if (expr_type.IsClass && target_type.IsInterface) {
+ if (target_type.IsInterface) {
if (TypeManager.ImplementsInterface (expr_type, target_type))
return true;
}
return false;
}
-
+
/// <summary>
/// Determines if a standard implicit conversion exists from
/// expr_type to target_type
public static bool StandardConversionExists (Expression expr, Type target_type)
{
Type expr_type = expr.Type;
+
+ if (expr_type == TypeManager.void_type)
+ return false;
if (expr_type == target_type)
return true;
if (i.Value == 0)
return true;
}
+
+ if (target_type == TypeManager.void_ptr_type && expr_type.IsPointer)
+ return true;
+
return false;
}
/// by making use of FindMostEncomp* methods. Applies the correct rules separately
/// for explicit and implicit conversion operators.
/// </summary>
- static public Type FindMostSpecificSource (MethodGroupExpr me, Type source_type,
+ static public Type FindMostSpecificSource (MethodGroupExpr me, Expression source,
bool apply_explicit_conv_rules,
Location loc)
{
if (priv_fms_expr == null)
priv_fms_expr = new EmptyExpression ();
-
+
//
// If any operator converts from S then Sx = S
//
+ Type source_type = source.Type;
foreach (MethodBase mb in me.Methods){
ParameterData pd = Invocation.GetParameterData (mb);
Type param_type = pd.ParameterType (0);
if (StandardConversionExists (priv_fms_expr, source_type))
src_types_set.Add (param_type);
else {
- priv_fms_expr.SetType (source_type);
- if (StandardConversionExists (priv_fms_expr, param_type))
+ if (StandardConversionExists (source, param_type))
src_types_set.Add (param_type);
}
} else {
//
// Only if S is encompassed by param_type
//
- priv_fms_expr.SetType (source_type);
- if (StandardConversionExists (priv_fms_expr, param_type))
+ if (StandardConversionExists (source, param_type))
src_types_set.Add (param_type);
}
}
ArrayList candidate_set = new ArrayList ();
foreach (Type param_type in src_types_set){
- priv_fms_expr.SetType (source_type);
-
- if (StandardConversionExists (priv_fms_expr, param_type))
+ if (StandardConversionExists (source, param_type))
candidate_set.Add (param_type);
}
//
if (apply_explicit_conv_rules)
return FindMostEncompassedType (tgt_types_set);
- else
+ else
return FindMostEncompassingType (tgt_types_set);
}
}
#endif
- most_specific_source = FindMostSpecificSource (union, source_type, look_for_explicit, loc);
+ most_specific_source = FindMostSpecificSource (union, source, look_for_explicit, loc);
if (most_specific_source == null)
return null;
most_specific_target = FindMostSpecificTarget (union, target, look_for_explicit, loc);
if (most_specific_target == null)
return null;
-
+
int count = 0;
foreach (MethodBase mb in union.Methods){
}
}
- if (method == null || count > 1) {
- Report.Error (-11, loc, "Ambiguous user defined conversion");
+ if (method == null || count > 1)
return null;
- }
+
//
// This will do the conversion to the best match that we
//
if (value >= 0)
return new ULongConstant ((ulong) value);
- }
+ } else if (target_type == TypeManager.double_type)
+ return new DoubleConstant ((double) value);
+ else if (target_type == TypeManager.float_type)
+ return new FloatConstant ((float) value);
- if (value == 0 && ic is IntLiteral && TypeManager.IsEnumType (target_type))
- return new EnumConstant (ic, target_type);
-
+ if (value == 0 && ic is IntLiteral && TypeManager.IsEnumType (target_type)){
+ Type underlying = TypeManager.EnumToUnderlying (target_type);
+ Constant e = (Constant) ic;
+
+ //
+ // Possibly, we need to create a different 0 literal before passing
+ // to EnumConstant
+ //n
+ if (underlying == TypeManager.int64_type)
+ e = new LongLiteral (0);
+ else if (underlying == TypeManager.uint64_type)
+ e = new ULongLiteral (0);
+
+ return new EnumConstant (e, target_type);
+ }
return null;
}
"Double literal cannot be implicitly converted to " +
"float type, use F suffix to create a float literal");
}
-
+
Error_CannotConvertImplicit (loc, source.Type, target_type);
return null;
/// <summary>
/// Performs the explicit numeric conversions
/// </summary>
- static Expression ConvertNumericExplicit (EmitContext ec, Expression expr, Type target_type)
+ static Expression ConvertNumericExplicit (EmitContext ec, Expression expr, Type target_type, Location loc)
{
Type expr_type = expr.Type;
//
// If we have an enumeration, extract the underlying type,
- // use this during the comparission, but wrap around the original
+ // use this during the comparison, but wrap around the original
// target_type
//
Type real_target_type = target_type;
if (TypeManager.IsEnumType (real_target_type))
real_target_type = TypeManager.EnumToUnderlying (real_target_type);
+ if (StandardConversionExists (expr, real_target_type)){
+ Expression ce = ConvertImplicitStandard (ec, expr, real_target_type, loc);
+
+ if (real_target_type != target_type)
+ return new EmptyCast (ce, target_type);
+ return ce;
+ }
+
if (expr_type == TypeManager.sbyte_type){
//
// From sbyte to byte, ushort, uint, ulong, char
return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U8);
if (real_target_type == TypeManager.char_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_CH);
- if (real_target_type == TypeManager.decimal_type)
- return InternalTypeConstructor (ec, expr, target_type);
} else if (expr_type == TypeManager.double_type){
//
// From double to byte, byte, short,
return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_CH);
if (real_target_type == TypeManager.float_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_R4);
- if (real_target_type == TypeManager.decimal_type)
- return InternalTypeConstructor (ec, expr, target_type);
}
// decimal is taken care of by the op_Explicit methods.
if (ne != null)
return ne;
- ne = ConvertNumericExplicit (ec, expr, target_type);
+ ne = ConvertNumericExplicit (ec, expr, target_type, loc);
if (ne != null)
return ne;
//
// Unboxing conversion.
//
- if (expr_type == TypeManager.object_type && target_type.IsValueType)
+ if (expr_type == TypeManager.object_type && target_type.IsValueType){
+ if (expr is NullLiteral){
+ Report.Error (37, "Cannot convert null to value type `" + TypeManager.CSharpName (expr_type) + "'");
+ return null;
+ }
return new UnboxCast (expr, target_type);
+ }
//
// Enum types
if (t != null)
return t;
- return ConvertNumericExplicit (ec, e, target_type);
+ t = ConvertNumericExplicit (ec, e, target_type, loc);
+ if (t != null)
+ return t;
+
+ Error_CannotConvertType (loc, expr_type, target_type);
+ return null;
}
ne = ConvertReferenceExplicit (expr, target_type);
if (ci != null)
return ci;
- ce = ConvertNumericExplicit (ec, e, target_type);
+ ce = ConvertNumericExplicit (ec, e, target_type, loc);
if (ce != null)
return ce;
//
if (ne != null)
return ne;
- ne = ConvertNumericExplicit (ec, expr, target_type);
+ ne = ConvertNumericExplicit (ec, expr, target_type, l);
if (ne != null)
return ne;
//
public static void StoreFromPtr (ILGenerator ig, Type type)
{
- if (type.IsEnum)
+ if (TypeManager.IsEnumType (type))
type = TypeManager.EnumToUnderlying (type);
if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
ig.Emit (OpCodes.Stind_I4);
t == TypeManager.char_type ||
t == TypeManager.ushort_type)
return 2;
+ else if (t == TypeManager.decimal_type)
+ return 16;
else
return 0;
}
Type t;
string alias_value;
+ if (ec.ResolvingTypeTree){
+ int errors = Report.Errors;
+ Type dt = ec.DeclSpace.FindType (loc, Name);
+ if (Report.Errors != errors)
+ return null;
+
+ if (dt != null)
+ return new TypeExpr (dt, loc);
+ }
+
if ((t = RootContext.LookupType (ds, Name, true, loc)) != null)
return new TypeExpr (t, loc);
+
//
// Stage 2 part b: Lookup up if we are an alias to a type
// or a namespace.
return new SimpleName (alias_value, loc);
}
- if (ec.ResolvingTypeTree){
- Type dt = ec.DeclSpace.FindType (Name);
- if (dt != null)
- return new TypeExpr (dt, 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 && current_block.IsVariableDefined (Name)){
+ if (current_block != null && current_block.GetVariableInfo (Name) != null){
LocalVariableReference var;
var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
if (!me.IsStatic && (me.InstanceExpression == null))
return e;
+ if (!me.IsStatic &&
+ TypeManager.IsNestedChildOf (me.InstanceExpression.Type, me.DeclaringType)) {
+ Error (38, "Cannot access nonstatic member `" + me.Name + "' of " +
+ "outer type `" + me.DeclaringType + "' via nested type `" +
+ me.InstanceExpression.Type + "'");
+ return null;
+ }
+
if (right_side != null)
e = e.DoResolveLValue (ec, right_side);
else
loc = l;
}
- public Expression DoResolveType (EmitContext ec)
+ public virtual Expression DoResolveType (EmitContext ec)
{
return this;
}
{
throw new Exception ("Should never be called");
}
+
+ public override string ToString ()
+ {
+ return Type.ToString ();
+ }
}
/// <summary>
public class MethodGroupExpr : Expression, IMemberExpr {
public MethodBase [] Methods;
Expression instance_expression = null;
+ bool is_explicit_impl = false;
public MethodGroupExpr (MemberInfo [] mi, Location l)
{
eclass = ExprClass.MethodGroup;
type = TypeManager.object_type;
}
+
+ public Type DeclaringType {
+ get {
+ return Methods [0].DeclaringType;
+ }
+ }
//
// `A method group may have associated an instance expression'
}
}
+ public bool IsExplicitImpl {
+ get {
+ return is_explicit_impl;
+ }
+
+ set {
+ is_explicit_impl = value;
+ }
+ }
+
public string Name {
get {
return Methods [0].Name;
override public Expression DoResolve (EmitContext ec)
{
+ if (instance_expression != null) {
+ instance_expression = instance_expression.DoResolve (ec);
+ if (instance_expression == null)
+ return null;
+ }
+
return this;
}
}
}
+ public Type DeclaringType {
+ get {
+ return FieldInfo.DeclaringType;
+ }
+ }
+
public Expression InstanceExpression {
get {
return instance_expr;
// Handle initonly fields specially: make a copy and then
// get the address of the copy.
//
- if (FieldInfo.IsInitOnly){
- if (ec.IsConstructor) {
- ig.Emit (OpCodes.Ldsflda, FieldInfo);
- } else {
- LocalBuilder local;
+ if (FieldInfo.IsInitOnly && !ec.IsConstructor){
+ LocalBuilder local;
- Emit (ec);
- local = ig.DeclareLocal (type);
- ig.Emit (OpCodes.Stloc, local);
- ig.Emit (OpCodes.Ldloca, local);
- }
+ Emit (ec);
+ local = ig.DeclareLocal (type);
+ ig.Emit (OpCodes.Stloc, local);
+ ig.Emit (OpCodes.Ldloca, local);
return;
}
/// </summary>
public class PropertyExpr : ExpressionStatement, IAssignMethod, IMemberExpr {
public readonly PropertyInfo PropertyInfo;
+
+ //
+ // This is set externally by the `BaseAccess' class
+ //
public bool IsBase;
- MethodInfo [] Accessors;
+ MethodInfo getter, setter;
bool is_static;
Expression instance_expr;
- public PropertyExpr (PropertyInfo pi, Location l)
+ public PropertyExpr (EmitContext ec, PropertyInfo pi, Location l)
{
PropertyInfo = pi;
eclass = ExprClass.PropertyAccess;
is_static = false;
loc = l;
- Accessors = TypeManager.GetAccessors (pi);
- if (Accessors != null)
- foreach (MethodInfo mi in Accessors){
- if (mi != null)
- if (mi.IsStatic)
- is_static = true;
- }
- else
- Accessors = new MethodInfo [2];
-
type = TypeManager.TypeToCoreType (pi.PropertyType);
+
+ ResolveAccessors (ec);
}
public string Name {
}
}
+ public Type DeclaringType {
+ get {
+ return PropertyInfo.DeclaringType;
+ }
+ }
+
//
// The instance expression associated with this expression
//
public bool VerifyAssignable ()
{
- if (!PropertyInfo.CanWrite){
+ if (setter == null) {
Report.Error (200, loc,
"The property `" + PropertyInfo.Name +
"' can not be assigned to, as it has not set accessor");
return true;
}
+ //
+ // We also perform the permission checking here, as the PropertyInfo does not
+ // hold the information for the accessibility of its setter/getter
+ //
+ void ResolveAccessors (EmitContext ec)
+ {
+ BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
+ MemberInfo [] group;
+
+ group = TypeManager.MemberLookup (ec.ContainerType, PropertyInfo.DeclaringType,
+ MemberTypes.Method, flags, "get_" + PropertyInfo.Name);
+
+ //
+ // The first method is the closest to us
+ //
+ if (group != null && group.Length > 0){
+ getter = (MethodInfo) group [0];
+
+ if (getter.IsStatic)
+ is_static = true;
+ }
+
+ //
+ // The first method is the closest to us
+ //
+ group = TypeManager.MemberLookup (ec.ContainerType, PropertyInfo.DeclaringType,
+ MemberTypes.Method, flags, "set_" + PropertyInfo.Name);
+ if (group != null && group.Length > 0){
+ setter = (MethodInfo) group [0];
+ if (setter.IsStatic)
+ is_static = true;
+ }
+
+ if (setter == null && getter == null){
+ Error (122, "`" + PropertyInfo.Name + "' " +
+ "is inaccessible because of its protection level");
+
+ }
+ }
+
+ bool InstanceResolve (EmitContext ec)
+ {
+ if ((instance_expr == null) && ec.IsStatic && !is_static) {
+ SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
+ return false;
+ }
+
+ if (instance_expr != null) {
+ instance_expr = instance_expr.DoResolve (ec);
+ if (instance_expr == null)
+ return false;
+ }
+
+ return true;
+ }
+
override public Expression DoResolve (EmitContext ec)
{
- if (!PropertyInfo.CanRead){
+ if (getter == null){
+ //
+ // The following condition happens if the PropertyExpr was
+ // created, but is invalid (ie, the property is inaccessible),
+ // and we did not want to embed the knowledge about this in
+ // the caller routine. This only avoids double error reporting.
+ //
+ if (setter == null)
+ return null;
+
Report.Error (154, loc,
"The property `" + PropertyInfo.Name +
"' can not be used in " +
"this context because it lacks a get accessor");
return null;
+ }
+
+ if (!InstanceResolve (ec))
+ return null;
+
+ //
+ // Only base will allow this invocation to happen.
+ //
+ if (IsBase && getter.IsAbstract){
+ Report.Error (205, loc, "Cannot call an abstract base property: " +
+ PropertyInfo.DeclaringType + "." +PropertyInfo.Name);
+ return null;
}
return this;
override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
{
- if (!PropertyInfo.CanWrite){
+ if (setter == null){
+ //
+ // The following condition happens if the PropertyExpr was
+ // created, but is invalid (ie, the property is inaccessible),
+ // and we did not want to embed the knowledge about this in
+ // the caller routine. This only avoids double error reporting.
+ //
+ if (getter == null)
+ return null;
+
Report.Error (154, loc,
"The property `" + PropertyInfo.Name +
"' can not be used in " +
return null;
}
+ if (!InstanceResolve (ec))
+ return null;
+
+ //
+ // Only base will allow this invocation to happen.
+ //
+ if (IsBase && setter.IsAbstract){
+ Report.Error (205, loc, "Cannot call an abstract base property: " +
+ PropertyInfo.DeclaringType + "." +PropertyInfo.Name);
+ return null;
+ }
return this;
}
override public void Emit (EmitContext ec)
{
- MethodInfo method = Accessors [0];
-
//
- // Special case: length of single dimension array is turned into ldlen
+ // Special case: length of single dimension array property is turned into ldlen
//
- if (method == TypeManager.int_array_get_length){
+ if ((getter == TypeManager.system_int_array_get_length) ||
+ (getter == TypeManager.int_array_get_length)){
Type iet = instance_expr.Type;
//
}
}
- Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, method, null, loc);
+ Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, getter, null, loc);
}
ArrayList args = new ArrayList ();
args.Add (arg);
- Invocation.EmitCall (ec, false, IsStatic, instance_expr, Accessors [1], args, loc);
+ Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, setter, args, loc);
}
override public void EmitStatement (EmitContext ec)
if (add_accessor.IsStatic || remove_accessor.IsStatic)
is_static = true;
- if (EventInfo is MyEventBuilder)
- type = ((MyEventBuilder) EventInfo).EventType;
- else
+ if (EventInfo is MyEventBuilder){
+ MyEventBuilder eb = (MyEventBuilder) EventInfo;
+ type = eb.EventType;
+ eb.SetUsed ();
+ } else
type = EventInfo.EventHandlerType;
}
}
}
+ public Type DeclaringType {
+ get {
+ return EventInfo.DeclaringType;
+ }
+ }
+
public Expression InstanceExpression {
get {
return instance_expr;
public override Expression DoResolve (EmitContext ec)
{
- // We are born fully resolved
+ if (instance_expr != null) {
+ instance_expr = instance_expr.DoResolve (ec);
+ if (instance_expr == null)
+ return null;
+ }
+
+
return this;
}
public override void Emit (EmitContext ec)
{
- throw new Exception ("Should not happen I think");
+ Report.Error (70, loc, "The event `" + Name + "' can only appear on the left hand side of += or -= (except on the defining type)");
}
public void EmitAddOrRemove (EmitContext ec, Expression source)