2002-09-16 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / ecore.cs
index 1d79636abe026ccf9086b759eb4fcb959880803b..26d88130ad84bd63e665004339c1e700409e43c4 100755 (executable)
@@ -54,7 +54,14 @@ namespace Mono.CSharp {
                // Allows SimpleNames to be returned.
                // This is used by MemberAccess to construct long names that can not be
                // partially resolved (namespace-qualified names for example).
-               SimpleName              = 8
+               SimpleName              = 8,
+
+               // Mask of all the expression class flags.
+               MaskExprClass           = 15,
+
+               // Disable control flow analysis while resolving the expression.
+               // This is used when resolving the instance expression of a field expression.
+               DisableFlowAnalysis     = 16
        }
 
        //
@@ -85,6 +92,42 @@ namespace Mono.CSharp {
                void AddressOf (EmitContext ec, AddressOp mode);
        }
 
+       /// <summary>
+       ///   This interface is implemented by variables
+       /// </summary>
+       public interface IVariable {
+               /// <summary>
+               ///   Checks whether the variable has already been assigned at
+               ///   the current position of the method's control flow and
+               ///   reports an appropriate error message if not.
+               ///
+               ///   If the variable is a struct, then this call checks whether
+               ///   all of its fields (including all private ones) have been
+               ///   assigned.
+               /// </summary>
+               bool IsAssigned (EmitContext ec, Location loc);
+
+               /// <summary>
+               ///   Checks whether field `name' in this struct has been assigned.
+               /// </summary>
+               bool IsFieldAssigned (EmitContext ec, string name, Location loc);
+
+               /// <summary>
+               ///   Tells the flow analysis code that the variable has already
+               ///   been assigned at the current code position.
+               ///
+               ///   If the variable is a struct, this call marks all its fields
+               ///   (including private fields) as being assigned.
+               /// </summary>
+               void SetAssigned (EmitContext ec);
+
+               /// <summary>
+               ///   Tells the flow analysis code that field `name' in this struct
+               ///   has already been assigned atthe current code position.
+               /// </summary>
+               void SetFieldAssigned (EmitContext ec, string name);
+       }
+
        /// <summary>
        ///   This interface denotes an expression which evaluates to a member
        ///   of a struct or a class.
@@ -98,6 +141,13 @@ namespace Mono.CSharp {
                        get;
                }
 
+               /// <summary>
+               ///   Whether this is an instance member.
+               /// </summary>
+               bool IsInstance {
+                       get;
+               }
+
                /// <summary>
                ///   Whether this is a static member.
                /// </summary>
@@ -105,6 +155,13 @@ namespace Mono.CSharp {
                        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.
@@ -114,6 +171,17 @@ namespace Mono.CSharp {
                }
        }
 
+       /// <summary>
+       ///   Expression which resolves to a type.
+       /// </summary>
+       public interface ITypeExpression
+       {
+               /// <summary>
+               ///   Resolve the expression, but only lookup types.
+               /// </summary>
+               Expression DoResolveType (EmitContext ec);
+       }
+
        /// <remarks>
        ///   Base class for expressions
        /// </remarks>
@@ -221,13 +289,28 @@ namespace Mono.CSharp {
                /// </remarks>
                public Expression Resolve (EmitContext ec, ResolveFlags flags)
                {
-                       Expression e;
+                       // Are we doing a types-only search ?
+                       if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type) {
+                               ITypeExpression type_expr = this as ITypeExpression;
+
+                               if (type_expr == null)
+                                       return null;
+
+                               return type_expr.DoResolveType (ec);
+                       }
+
+                       bool old_do_flow_analysis = ec.DoFlowAnalysis;
+                       if ((flags & ResolveFlags.DisableFlowAnalysis) != 0)
+                               ec.DoFlowAnalysis = false;
 
+                       Expression e;
                        if (this is SimpleName)
                                e = ((SimpleName) this).DoResolveAllowStatic (ec);
                        else 
                                e = DoResolve (ec);
 
+                       ec.DoFlowAnalysis = old_do_flow_analysis;
+
                        if (e == null)
                                return null;
 
@@ -235,10 +318,16 @@ namespace Mono.CSharp {
                                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;
                                }
 
@@ -462,7 +551,23 @@ namespace Mono.CSharp {
                public static Expression MemberLookup (EmitContext ec, Type t, string name,
                                                       MemberTypes mt, BindingFlags bf, Location loc)
                {
-                       MemberInfo [] mi = TypeManager.MemberLookup (ec.ContainerType, t, mt, bf, name);
+                       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)
+               {
+                       MemberInfo [] mi = TypeManager.MemberLookup (invocation_type, t, mt, bf, name);
 
                        if (mi == null)
                                return null;
@@ -493,12 +598,14 @@ namespace Mono.CSharp {
 
                public static Expression MemberLookup (EmitContext ec, Type t, string name, Location loc)
                {
-                       return MemberLookup (ec, t, name, AllMemberTypes, AllBindingFlags, loc);
+                       return MemberLookup (ec, ec.ContainerType, t, name,
+                                            AllMemberTypes, AllBindingFlags, loc);
                }
 
                public static Expression MethodLookup (EmitContext ec, Type t, string name, Location loc)
                {
-                       return MemberLookup (ec, t, name, MemberTypes.Method, AllBindingFlags, loc);
+                       return MemberLookup (ec, ec.ContainerType, t, name,
+                                            MemberTypes.Method, AllBindingFlags, loc);
                }
 
                /// <summary>
@@ -520,7 +627,7 @@ namespace Mono.CSharp {
 
                        int errors = Report.Errors;
 
-                       e = MemberLookup (ec, t, name, mt, bf, loc);
+                       e = MemberLookup (ec, ec.ContainerType, t, name, mt, bf, loc);
 
                        if (e != null)
                                return e;
@@ -691,19 +798,8 @@ namespace Mono.CSharp {
                                        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.
@@ -947,7 +1043,7 @@ namespace Mono.CSharp {
 
                        return false;
                }
-               
+
                /// <summary>
                ///  Determines if a standard implicit conversion exists from
                ///  expr_type to target_type
@@ -955,6 +1051,9 @@ namespace Mono.CSharp {
                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;
@@ -1117,6 +1216,7 @@ namespace Mono.CSharp {
                                if (i.Value == 0)
                                        return true;
                        }
+
                        return false;
                }
 
@@ -1196,7 +1296,7 @@ namespace Mono.CSharp {
                ///   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)
                {
@@ -1204,10 +1304,11 @@ namespace Mono.CSharp {
                        
                        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);
@@ -1228,16 +1329,14 @@ namespace Mono.CSharp {
                                        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);
                                }
                        }
@@ -1249,9 +1348,7 @@ namespace Mono.CSharp {
                                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);
                                }
 
@@ -1344,8 +1441,10 @@ namespace Mono.CSharp {
                        //
                        if (apply_explicit_conv_rules)
                                return FindMostEncompassedType (tgt_types_set);
-                       else
+                       else {
+                               Console.WriteLine ("Here with: " + tgt_types_set.Count);
                                return FindMostEncompassingType (tgt_types_set);
+                       }
                }
                
                /// <summary>
@@ -1466,14 +1565,14 @@ namespace Mono.CSharp {
                        }
 #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){
@@ -1690,7 +1789,7 @@ namespace Mono.CSharp {
 
                        //
                        // 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;
@@ -1698,6 +1797,9 @@ namespace Mono.CSharp {
                        if (TypeManager.IsEnumType (real_target_type))
                                real_target_type = TypeManager.EnumToUnderlying (real_target_type);
 
+                       if (StandardConversionExists (expr, real_target_type))
+                               return new EmptyCast (expr, target_type);
+                       
                        if (expr_type == TypeManager.sbyte_type){
                                //
                                // From sbyte to byte, ushort, uint, ulong, char
@@ -3267,7 +3369,7 @@ namespace Mono.CSharp {
        ///   The downside of this is that we might be hitting `LookupType' too many
        ///   times with this scheme.
        /// </remarks>
-       public class SimpleName : Expression {
+       public class SimpleName : Expression, ITypeExpression {
                public readonly string Name;
                
                public SimpleName (string name, Location l)
@@ -3276,35 +3378,33 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public static void Error_ObjectRefRequired (Location l, string name)
+               public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
                {
-                       Report.Error (
-                               120, l,
-                               "An object reference is required " +
-                               "for the non-static field `"+name+"'");
+                       if (ec.IsFieldInitializer)
+                               Report.Error (
+                                       236, l,
+                                       "A field initializer cannot reference the non-static field, " +
+                                       "method or property `"+name+"'");
+                       else
+                               Report.Error (
+                                       120, l,
+                                       "An object reference is required " +
+                                       "for the non-static field `"+name+"'");
                }
                
                //
                // Checks whether we are trying to access an instance
                // property, method or field from a static body.
                //
-               Expression MemberStaticCheck (Expression e)
+               Expression MemberStaticCheck (EmitContext ec, Expression e)
                {
                        if (e is IMemberExpr){
                                IMemberExpr member = (IMemberExpr) e;
                                
                                if (!member.IsStatic){
-                                       Error_ObjectRefRequired (loc, Name);
+                                       Error_ObjectRefRequired (ec, loc, Name);
                                        return null;
                                }
-                       } else if (e is MethodGroupExpr){
-                               MethodGroupExpr mg = (MethodGroupExpr) e;
-
-                               if (!mg.RemoveInstanceMethods ()){
-                                       Error_ObjectRefRequired (loc, mg.Methods [0].Name);
-                                       return null;
-                               }
-                               return e;
                        }
 
                        return e;
@@ -3326,6 +3426,47 @@ namespace Mono.CSharp {
                        return SimpleNameResolve (ec, null, true);
                }
 
+               public Expression DoResolveType (EmitContext ec)
+               {
+                       //
+                       // Stage 3: Lookup symbol in the various namespaces. 
+                       //
+                       DeclSpace ds = ec.DeclSpace;
+                       Type t;
+                       string alias_value;
+
+                       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.
+                       //
+                       // Since we are cheating: we only do the Alias lookup for
+                       // namespaces if the name does not include any dots in it
+                       //
+                               
+                       alias_value = ec.DeclSpace.LookupAlias (Name);
+                               
+                       if (Name.IndexOf ('.') == -1 && alias_value != null) {
+                               if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null)
+                                       return new TypeExpr (t, loc);
+                                       
+                               // we have alias value, but it isn't Type, so try if it's 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;
+               }
+
                /// <remarks>
                ///   7.5.2: Simple Names. 
                ///
@@ -3350,128 +3491,108 @@ namespace Mono.CSharp {
                        //
                        // Stage 1: Performed by the parser (binding to locals or parameters).
                        //
-                       if (!ec.OnlyLookupTypes){
-                               Block current_block = ec.CurrentBlock;
-                               if (current_block != null && current_block.IsVariableDefined (Name)){
-                                       LocalVariableReference var;
+                       Block current_block = ec.CurrentBlock;
+                       if (current_block != null && current_block.IsVariableDefined (Name)){
+                               LocalVariableReference var;
+
+                               var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
+
+                               if (right_side != null)
+                                       return var.ResolveLValue (ec, right_side);
+                               else
+                                       return var.Resolve (ec);
+                       }
+
+                       if (current_block != null){
+                               int idx = -1;
+                               Parameter par = null;
+                               Parameters pars = current_block.Parameters;
+                               if (pars != null)
+                                       par = pars.GetParameterByName (Name, out idx);
+
+                               if (par != null) {
+                                       ParameterReference param;
                                        
-                                       var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
+                                       param = new ParameterReference (pars, idx, Name, loc);
 
                                        if (right_side != null)
-                                               return var.ResolveLValue (ec, right_side);
+                                               return param.ResolveLValue (ec, right_side);
                                        else
-                                               return var.Resolve (ec);
+                                               return param.Resolve (ec);
                                }
+                       }
 
-                               if (current_block != null){
-                                       int idx = -1;
-                                       Parameter par = null;
-                                       Parameters pars = current_block.Parameters;
-                                       if (pars != null)
-                                               par = pars.GetParameterByName (Name, out idx);
+                       //
+                       // Stage 2: Lookup members 
+                       //
 
-                                       if (par != null) {
-                                               ParameterReference param;
-                                       
-                                               param = new ParameterReference (pars, idx, Name, loc);
+                       //
+                       // For enums, the TypeBuilder is not ec.DeclSpace.TypeBuilder
+                       // Hence we have two different cases
+                       //
 
-                                               if (right_side != null)
-                                                       return param.ResolveLValue (ec, right_side);
-                                               else
-                                                       return param.Resolve (ec);
-                                       }
-                               }
+                       DeclSpace lookup_ds = ec.DeclSpace;
+                       do {
+                               if (lookup_ds.TypeBuilder == null)
+                                       break;
 
-                               //
-                               // Stage 2: Lookup members 
-                               //
+                               e = MemberLookup (ec, lookup_ds.TypeBuilder, Name, loc);
+                               if (e != null)
+                                       break;
 
                                //
-                               // For enums, the TypeBuilder is not ec.DeclSpace.TypeBuilder
-                               // Hence we have two different cases
+                               // Classes/structs keep looking, enums break
                                //
+                               if (lookup_ds is TypeContainer)
+                                       lookup_ds = ((TypeContainer) lookup_ds).Parent;
+                               else
+                                       break;
+                       } while (lookup_ds != null);
+                               
+                       if (e == null && ec.ContainerType != null)
+                               e = MemberLookup (ec, ec.ContainerType, Name, loc);
 
-                               DeclSpace lookup_ds = ec.DeclSpace;
-                               do {
-                                       if (lookup_ds.TypeBuilder == null)
-                                               break;
+                       if (e == null)
+                               return DoResolveType (ec);
 
-                                       e = MemberLookup (ec, lookup_ds.TypeBuilder, Name, loc);
-                                       if (e != null)
-                                               break;
+                       if (e is TypeExpr)
+                               return e;
 
-                                       //
-                                       // Classes/structs keep looking, enums break
-                                       //
-                                       if (lookup_ds is TypeContainer)
-                                               lookup_ds = ((TypeContainer) lookup_ds).Parent;
-                                       else
-                                               break;
-                               } while (lookup_ds != null);
-                               
-                               if (e == null && ec.ContainerType != null)
-                                       e = MemberLookup (ec, ec.ContainerType, Name, loc);
-                       }
+                       if (e is IMemberExpr) {
+                               e = MemberAccess.ResolveMemberAccess (ec, e, null, loc, this);
+                               if (e == null)
+                                       return null;
 
-                       // Continuation of stage 2
-                       if (e == null){
-                               //
-                               // Stage 3: Lookup symbol in the various namespaces. 
-                               //
-                               DeclSpace ds = ec.DeclSpace;
-                               Type t;
-                               string alias_value;
+                               IMemberExpr me = e as IMemberExpr;
+                               if (me == null)
+                                       return e;
 
-                               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.
-                               //
-                               // Since we are cheating: we only do the Alias lookup for
-                               // namespaces if the name does not include any dots in it
-                               //
-                               
-                               alias_value = ec.DeclSpace.LookupAlias (Name);
-                               
-                               if (Name.IndexOf ('.') == -1 && alias_value != null) {
-                                       if ((t = RootContext.LookupType (ds, alias_value, true, loc))
-                                           != null)
-                                               return new TypeExpr (t, loc);
-                                       
-                               // we have alias value, but it isn't Type, so try if it's 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;
-                       }
+                               // This fails if ResolveMemberAccess() was unable to decide whether
+                               // it's a field or a type of the same name.
+                               if (!me.IsStatic && (me.InstanceExpression == null))
+                                       return e;
 
-                       //
-                       // Stage 2 continues here. 
-                       // 
-                       if (e is TypeExpr)
-                               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 (ec.OnlyLookupTypes)
-                               return null;
+                               if (right_side != null)
+                                       e = e.DoResolveLValue (ec, right_side);
+                               else
+                                       e = e.DoResolve (ec);
 
-                       if (e is IMemberExpr)
-                               return MemberAccess.ResolveMemberAccess (ec, e, null, loc, this);
+                               return e;                               
+                       }
 
-                       if (ec.IsStatic){
+                       if (ec.IsStatic || ec.IsFieldInitializer){
                                if (allow_static)
                                        return e;
 
-                               return MemberStaticCheck (e);
+                               return MemberStaticCheck (ec, e);
                        } else
                                return e;
                }
@@ -3497,7 +3618,7 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Fully resolved expression that evaluates to a type
        /// </summary>
-       public class TypeExpr : Expression {
+       public class TypeExpr : Expression, ITypeExpression {
                public TypeExpr (Type t, Location l)
                {
                        Type = t;
@@ -3505,6 +3626,11 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               public virtual Expression DoResolveType (EmitContext ec)
+               {
+                       return this;
+               }
+
                override public Expression DoResolve (EmitContext ec)
                {
                        return this;
@@ -3514,31 +3640,41 @@ namespace Mono.CSharp {
                {
                        throw new Exception ("Should never be called");
                }
+
+               public override string ToString ()
+               {
+                       return Type.ToString ();
+               }
        }
 
        /// <summary>
        ///   Used to create types from a fully qualified name.  These are just used
-       ///   by the parser to setup the core types.  A TypeExpression is always
+       ///   by the parser to setup the core types.  A TypeLookupExpression is always
        ///   classified as a type.
        /// </summary>
-       public class TypeExpression : TypeExpr {
+       public class TypeLookupExpression : TypeExpr {
                string name;
                
-               public TypeExpression (string name) : base (null, Location.Null)
+               public TypeLookupExpression (string name) : base (null, Location.Null)
                {
                        this.name = name;
                }
 
-               public override Expression DoResolve (EmitContext ec)
+               public override Expression DoResolveType (EmitContext ec)
                {
                        if (type == null)
                                type = RootContext.LookupType (ec.DeclSpace, name, false, Location.Null);
                        return this;
                }
 
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return DoResolveType (ec);
+               }
+
                public override void Emit (EmitContext ec)
                {
-                       throw new Exception ("Should never be called");                 
+                       throw new Exception ("Should never be called");
                }
 
                public override string ToString ()
@@ -3552,9 +3688,10 @@ namespace Mono.CSharp {
        ///  
        ///   This is a fully resolved expression that evaluates to a type
        /// </summary>
-       public class MethodGroupExpr : Expression {
+       public class MethodGroupExpr : Expression, IMemberExpr {
                public MethodBase [] Methods;
                Expression instance_expression = null;
+               bool is_explicit_impl = false;
                
                public MethodGroupExpr (MemberInfo [] mi, Location l)
                {
@@ -3584,6 +3721,12 @@ namespace Mono.CSharp {
                        eclass = ExprClass.MethodGroup;
                        type = TypeManager.object_type;
                }
+
+               public Type DeclaringType {
+                       get {
+                               return Methods [0].DeclaringType;
+                       }
+               }
                
                //
                // `A method group may have associated an instance expression' 
@@ -3597,9 +3740,51 @@ namespace Mono.CSharp {
                                instance_expression = value;
                        }
                }
+
+               public bool IsExplicitImpl {
+                       get {
+                               return is_explicit_impl;
+                       }
+
+                       set {
+                               is_explicit_impl = value;
+                       }
+               }
+
+               public string Name {
+                       get {
+                               return Methods [0].Name;
+                       }
+               }
+
+               public bool IsInstance {
+                       get {
+                               foreach (MethodBase mb in Methods)
+                                       if (!mb.IsStatic)
+                                               return true;
+
+                               return false;
+                       }
+               }
+
+               public bool IsStatic {
+                       get {
+                               foreach (MethodBase mb in Methods)
+                                       if (mb.IsStatic)
+                                               return true;
+
+                               return false;
+                       }
+               }
                
                override public Expression DoResolve (EmitContext ec)
                {
+                       if (instance_expression != null) {
+                               instance_expression = instance_expression.DoResolve (ec);
+                               if (instance_expression == null)
+                                       return null;
+                       }
+
                        return this;
                }
 
@@ -3672,12 +3857,24 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool IsInstance {
+                       get {
+                               return !FieldInfo.IsStatic;
+                       }
+               }
+
                public bool IsStatic {
                        get {
                                return FieldInfo.IsStatic;
                        }
                }
 
+               public Type DeclaringType {
+                       get {
+                               return FieldInfo.DeclaringType;
+                       }
+               }
+
                public Expression InstanceExpression {
                        get {
                                return instance_expr;
@@ -3697,11 +3894,20 @@ namespace Mono.CSharp {
                                                             "Of the FieldExpr to set this\n");
                                }
 
-                               instance_expr = instance_expr.Resolve (ec);
+                               // Resolve the field's instance expression while flow analysis is turned
+                               // off: when accessing a field "a.b", we must check whether the field
+                               // "a.b" is initialized, not whether the whole struct "a" is initialized.
+                               instance_expr = instance_expr.Resolve (ec, ResolveFlags.VariableOrValue |
+                                                                      ResolveFlags.DisableFlowAnalysis);
                                if (instance_expr == null)
                                        return null;
                        }
 
+                       // If the instance expression is a local variable or parameter.
+                       IVariable var = instance_expr as IVariable;
+                       if ((var != null) && !var.IsFieldAssigned (ec, FieldInfo.Name, loc))
+                               return null;
+
                        return this;
                }
 
@@ -3721,6 +3927,10 @@ namespace Mono.CSharp {
                
                override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
+                       IVariable var = instance_expr as IVariable;
+                       if (var != null)
+                               var.SetFieldAssigned (ec, FieldInfo.Name);
+
                        Expression e = DoResolve (ec);
 
                        if (e == null)
@@ -3745,7 +3955,7 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
                        bool is_volatile = false;
-                               
+
                        if (FieldInfo is FieldBuilder){
                                FieldBase f = TypeManager.GetField (FieldInfo);
 
@@ -3925,12 +4135,24 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool IsInstance {
+                       get {
+                               return !is_static;
+                       }
+               }
+
                public bool IsStatic {
                        get {
                                return is_static;
                        }
                }
                
+               public Type DeclaringType {
+                       get {
+                               return PropertyInfo.DeclaringType;
+                       }
+               }
+
                //
                // The instance expression associated with this expression
                //
@@ -3966,7 +4188,35 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       type = PropertyInfo.PropertyType;
+                       if ((instance_expr == null) && ec.IsStatic && !is_static) {
+                               SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
+                               return null;
+                       }
+
+                       if (instance_expr != null) {
+                               instance_expr = instance_expr.DoResolve (ec);
+                               if (instance_expr == null)
+                                       return null;
+                       }
+
+                       return this;
+               }
+
+               override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       if (!PropertyInfo.CanWrite){
+                               Report.Error (154, loc, 
+                                             "The property `" + PropertyInfo.Name +
+                                             "' can not be used in " +
+                                             "this context because it lacks a set accessor");
+                               return null;
+                       }
+
+                       if (instance_expr != null) {
+                               instance_expr = instance_expr.DoResolve (ec);
+                               if (instance_expr == null)
+                                       return null;
+                       }
 
                        return this;
                }
@@ -3978,7 +4228,8 @@ namespace Mono.CSharp {
                        //
                        // Special case: length of single dimension array is turned into ldlen
                        //
-                       if (method == TypeManager.int_array_get_length){
+                       if ((method == TypeManager.system_int_array_get_length) ||
+                           (method == TypeManager.int_array_get_length)){
                                Type iet = instance_expr.Type;
 
                                //
@@ -4049,12 +4300,24 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool IsInstance {
+                       get {
+                               return !is_static;
+                       }
+               }
+
                public bool IsStatic {
                        get {
                                return is_static;
                        }
                }
 
+               public Type DeclaringType {
+                       get {
+                               return EventInfo.DeclaringType;
+                       }
+               }
+
                public Expression InstanceExpression {
                        get {
                                return instance_expr;
@@ -4067,7 +4330,12 @@ namespace Mono.CSharp {
 
                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;
                }