**** Merged r40732-r40872 from MCS ****
[mono.git] / mcs / gmcs / ecore.cs
old mode 100755 (executable)
new mode 100644 (file)
index 8635971..baf528b
@@ -51,20 +51,15 @@ namespace Mono.CSharp {
                // Returns a method group.
                MethodGroup             = 4,
 
-               // 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,
-
                // Mask of all the expression class flags.
-               MaskExprClass           = 15,
+               MaskExprClass           = 7,
 
                // Disable control flow analysis while resolving the expression.
                // This is used when resolving the instance expression of a field expression.
-               DisableFlowAnalysis     = 16,
+               DisableFlowAnalysis     = 8,
 
                // Set if this is resolving the first part of a MemberAccess.
-               Intermediate            = 32
+               Intermediate            = 16
        }
 
        //
@@ -109,9 +104,7 @@ namespace Mono.CSharp {
                        get;
                }
 
-               TypeExpr Type {
-                       get;
-               }
+               TypeExpr ResolveAsType (EmitContext ec);
        }
 
        /// <summary>
@@ -206,23 +199,13 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Utility wrapper routine for Warning, just to beautify the code
                /// </summary>
-               public void Warning (int warning, string s)
+               public void Warning (int code, string format, params object[] args)
                {
-                       if (!Location.IsNull (loc))
-                               Report.Warning (warning, loc, s);
-                       else
-                               Report.Warning (warning, s);
+                       Report.Warning (code, loc, format, args);
                }
 
-               /// <summary>
-               ///   Utility wrapper routine for Warning, only prints the warning if
-               ///   warnings of level `level' are enabled.
-               /// </summary>
-               public void Warning (int warning, int level, string s)
-               {
-                       if (level <= RootContext.WarningLevel)
-                               Warning (warning, s);
-               }
+               // Not nice but we have broken hierarchy
+               public virtual void CheckMarshallByRefAccess (Type container) {}
 
                /// <summary>
                /// Tests presence of ObsoleteAttribute and report proper error
@@ -236,6 +219,55 @@ namespace Mono.CSharp {
                        AttributeTester.Report_ObsoleteMessage (obsolete_attr, type.FullName, loc);
                }
 
+               public static bool IsAccessorAccessible (Type invocation_type, MethodInfo mi, out bool must_do_cs1540_check)
+               {
+                       MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;
+
+                       must_do_cs1540_check = false; // by default we do not check for this
+
+                       //
+                       // If only accessible to the current class or children
+                       //
+                       if (ma == MethodAttributes.Private) {
+                               Type declaring_type = mi.DeclaringType;
+
+                               if (invocation_type != declaring_type)
+                                       return TypeManager.IsNestedChildOf (invocation_type, declaring_type);
+
+                               return true;
+                       }
+                       //
+                       // FamAndAssem requires that we not only derivate, but we are on the
+                       // same assembly.  
+                       //
+                       if (ma == MethodAttributes.FamANDAssem){
+                               return (mi.DeclaringType.Assembly != invocation_type.Assembly);
+                       }
+
+                       // 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 true;
+                       }
+
+                       // We already know that we aren't in the same assembly.
+                       if (ma == MethodAttributes.Assembly)
+                               return false;
+
+                       // Family and FamANDAssem require that we derive.
+                       if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem) || (ma == MethodAttributes.FamORAssem)){
+                               if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType))
+                                       return false;
+
+                               if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType))
+                                       must_do_cs1540_check = true;
+
+                               return true;
+                       }
+
+                       return true;
+               }
+
                /// <summary>
                ///   Performs semantic analysis on the Expression
                /// </summary>
@@ -267,15 +299,14 @@ namespace Mono.CSharp {
 
                public virtual Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
-                       return DoResolve (ec);
+                       return null;
                }
 
                //
-               // This is used if the expression should be resolved as a type.
-               // the default implementation fails.   Use this method in
-               // those participants in the SimpleName chain system.
+               // This is used if the expression should be resolved as a type or namespace name.
+               // the default implementation fails.   
                //
-               public virtual Expression ResolveAsTypeStep (EmitContext ec)
+               public virtual FullNamedExpression ResolveAsTypeStep (EmitContext ec)
                {
                        return null;
                }
@@ -285,9 +316,33 @@ namespace Mono.CSharp {
                // value will be returned if the expression is not a type
                // reference
                //
-               public TypeExpr ResolveAsTypeTerminal (EmitContext ec)
+               public virtual TypeExpr ResolveAsTypeTerminal (EmitContext ec)
                {
-                       return ResolveAsTypeStep (ec) as TypeExpr;
+                       int errors = Report.Errors;
+
+                       FullNamedExpression fne = ResolveAsTypeStep (ec);
+
+                       if (fne == null) {
+                               if (errors == Report.Errors)
+                                       Report.Error (246, Location, "Cannot find type '{0}'", ToString ());
+                               return null;
+                       }
+
+                       if (fne.eclass != ExprClass.Type) {
+                               if (errors == Report.Errors)
+                                       Report.Error (118, Location, "'{0}' denotes a '{1}', where a type was expected",
+                                                     fne.FullName, fne.ExprClassName ());
+                               return null;
+                       }
+
+                       TypeExpr te = fne as TypeExpr;
+
+                       if (!te.CheckAccessLevel (ec.DeclSpace)) {
+                               Report.Error (122, Location, "'{0}' is inaccessible due to its protection level", te.Name);
+                               return null;
+                       }
+
+                       return te;
                }
               
                /// <summary>
@@ -320,21 +375,9 @@ namespace Mono.CSharp {
                        if (e == null)
                                return null;
 
-                       if (e is SimpleName){
-                               SimpleName s = (SimpleName) e;
-
-                               if ((flags & ResolveFlags.SimpleName) == 0) {
-                                       MemberLookupFailed (ec, null, ec.ContainerType, s.Name,
-                                                           ec.DeclSpace.Name, loc);
-                                       return null;
-                               }
-
-                               return s;
-                       }
-
-                       if ((e is TypeExpr) || (e is ComposedCast)) {
+                       if ((e is TypeExpr) || (e is ComposedCast) || (e is Namespace)) {
                                if ((flags & ResolveFlags.Type) == 0) {
-                                       e.Error_UnexpectedKind (flags);
+                                       e.Error_UnexpectedKind (flags, loc);
                                        return null;
                                }
 
@@ -343,18 +386,19 @@ namespace Mono.CSharp {
 
                        switch (e.eclass) {
                        case ExprClass.Type:
+                       case ExprClass.Namespace:
                                if ((flags & ResolveFlags.VariableOrValue) == 0) {
-                                       e.Error_UnexpectedKind (flags);
+                                       e.Error_UnexpectedKind (flags, loc);
                                        return null;
                                }
                                break;
 
                        case ExprClass.MethodGroup:
-                               if (!RootContext.V2){
-                               if ((flags & ResolveFlags.MethodGroup) == 0) {
-                                       ((MethodGroupExpr) e).ReportUsageError ();
-                                       return null;
-                               }
+                               if (RootContext.Version == LanguageVersion.ISO_1){
+                                       if ((flags & ResolveFlags.MethodGroup) == 0) {
+                                               ((MethodGroupExpr) e).ReportUsageError ();
+                                               return null;
+                                       }
                                }
                                break;
 
@@ -369,7 +413,7 @@ namespace Mono.CSharp {
                                        FieldInfo fi = ((FieldExpr) e).FieldInfo;
                                        
                                        Console.WriteLine ("{0} and {1}", fi.DeclaringType, fi.Name);
-                                       e.Error_UnexpectedKind (flags);
+                                       e.Error_UnexpectedKind (flags, loc);
                                        return null;
                                }
                                break;
@@ -379,11 +423,12 @@ namespace Mono.CSharp {
                                                     " ExprClass is Invalid after resolve");
                        }
 
-                       if (e.type == null)
+                       if (e.type == null && !(e is Namespace)) {
                                throw new Exception (
                                        "Expression " + e.GetType () +
                                        " did not set its type after Resolve\n" +
                                        "called from: " + this.GetType ());
+                       }
 
                        return e;
                }
@@ -406,16 +451,16 @@ namespace Mono.CSharp {
                /// </remarks>
                public Expression ResolveLValue (EmitContext ec, Expression right_side)
                {
+                       int errors = Report.Errors;
                        Expression e = DoResolveLValue (ec, right_side);
 
-                       if (e != null){
-                               if (e is SimpleName){
-                                       SimpleName s = (SimpleName) e;
-                                       MemberLookupFailed (ec, null, ec.ContainerType, s.Name,
-                                                           ec.DeclSpace.Name, loc);
-                                       return null;
-                               }
+                       if (e == null) {
+                               if (errors == Report.Errors)
+                                       Report.Error (131, Location, "The left-hand side of an assignment or mutating operation must be a variable, property or indexer");
+                               return null;
+                       }
 
+                       if (e != null){
                                if (e.eclass == ExprClass.Invalid)
                                        throw new Exception ("Expression " + e +
                                                             " ExprClass is Invalid after resolve");
@@ -501,15 +546,19 @@ namespace Mono.CSharp {
                                return new CharConstant ((char)v);
                        else if (t == TypeManager.bool_type)
                                return new BoolConstant ((bool) v);
+                       else if (t == TypeManager.decimal_type)
+                               return new DecimalConstant ((decimal) v);
                        else if (TypeManager.IsEnumType (t)){
                                Type real_type = TypeManager.TypeToCoreType (v.GetType ());
                                if (real_type == t)
-                                       real_type = real_type.UnderlyingSystemType;
+                                       real_type = System.Enum.GetUnderlyingType (real_type);
 
                                Constant e = Constantify (v, real_type);
 
                                return new EnumConstant (e, t);
-                       } else
+                       } else if (v == null && !TypeManager.IsValueType (t))
+                               return NullLiteral.Null;
+                       else
                                throw new Exception ("Unknown type for constant (" + t +
                                                     "), details: " + v);
                }
@@ -532,8 +581,7 @@ namespace Mono.CSharp {
                        return null;
                }
 
-
-               private static ArrayList almostMatchedMembers = new ArrayList (4);
+               protected static ArrayList almostMatchedMembers = new ArrayList (4);
 
                //
                // FIXME: Probably implement a cache for (t,name,current_access_set)?
@@ -685,16 +733,28 @@ namespace Mono.CSharp {
                                if (qualifier_type != ec.ContainerType) {
                                        // Although a derived class can access protected members of
                                        // its base class it cannot do so through an instance of the
-                                       // base class (CS1540).  If the qualifier_type is a parent of the
+                                       // base class (CS1540).  If the qualifier_type is a base of the
                                        // ec.ContainerType and the lookup succeeds with the latter one,
                                        // then we are in this situation.
-                                       foreach (MemberInfo m in almostMatchedMembers)
+                                       for (int i = 0; i < almostMatchedMembers.Count; ++i) {
+                                               MemberInfo m = (MemberInfo) almostMatchedMembers [i];
+                                               for (int j = 0; j < i; ++j) {
+                                                       if (m == almostMatchedMembers [j]) {
+                                                               m = null;
+                                                               break;
+                                                       }
+                                               }
+                                               if (m == null)
+                                                       continue;
+
+                                               Report.SymbolRelatedToPreviousError (m);
                                                Report.Error (1540, loc, 
                                                              "Cannot access protected member `{0}' via a qualifier of type `{1}';"
                                                              + " the qualifier must be of type `{2}' (or derived from it)", 
                                                              TypeManager.GetFullNameSignature (m),
                                                              TypeManager.CSharpName (qualifier_type),
                                                              TypeManager.CSharpName (ec.ContainerType));
+                                       }
                                        return;
                                }
                                almostMatchedMembers.Clear ();
@@ -730,15 +790,17 @@ namespace Mono.CSharp {
                                }
                        }
 
+                       if (name == ".ctor" && TypeManager.FindMembers (qualifier_type, MemberTypes.Constructor,
+                               BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly, null, null).Count == 0)
+                       {
+                               Report.Error (143, loc, String.Format ("The type '{0}' has no constructors defined", TypeManager.CSharpName (queried_type)));
+                               return;
+                       }
 
-
-                       if (qualifier_type != null)
-                               Report.Error_T (122, loc, TypeManager.CSharpName (qualifier_type) + "." + name);
-                       else if (name == ".ctor") {
-                               Report.Error (143, loc, String.Format ("The type {0} has no constructors defined",
-                                                                      TypeManager.CSharpName (queried_type)));
+                       if (qualifier_type != null) {
+                               Report.Error (122, loc, "'{0}' is inaccessible due to its protection level", TypeManager.CSharpName (qualifier_type) + "." + name);
                        } else {
-                               Report.Error_T (122, loc, name);
+                               Report.Error (122, loc, "'{0}' is inaccessible due to its protection level", name);
                }
                }
 
@@ -753,7 +815,7 @@ namespace Mono.CSharp {
                ///   Returns an expression that can be used to invoke operator true
                ///   on the expression if it exists.
                /// </summary>
-               static public StaticCallExpr GetOperatorTrue (EmitContext ec, Expression e, Location loc)
+               static public Expression GetOperatorTrue (EmitContext ec, Expression e, Location loc)
                {
                        return GetOperatorTrueOrFalse (ec, e, true, loc);
                }
@@ -762,16 +824,19 @@ namespace Mono.CSharp {
                ///   Returns an expression that can be used to invoke operator false
                ///   on the expression if it exists.
                /// </summary>
-               static public StaticCallExpr GetOperatorFalse (EmitContext ec, Expression e, Location loc)
+               static public Expression GetOperatorFalse (EmitContext ec, Expression e, Location loc)
                {
                        return GetOperatorTrueOrFalse (ec, e, false, loc);
                }
 
-               static StaticCallExpr GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
+               static Expression GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
                {
                        MethodBase method;
                        Expression operator_group;
 
+                       if (TypeManager.IsNullableType (e.Type))
+                               return new Nullable.OperatorTrueOrFalse (e, is_true, loc).Resolve (ec);
+
                        operator_group = MethodLookup (ec, e.Type, is_true ? "op_True" : "op_False", loc);
                        if (operator_group == null)
                                return null;
@@ -797,30 +862,28 @@ namespace Mono.CSharp {
                        if (e == null)
                                return null;
 
-                       Expression converted = e;
-                       if (e.Type != TypeManager.bool_type)
-                               converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, new Location (-1));
+                       if (e.Type == TypeManager.bool_type)
+                               return e;
+
+                       Expression converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, new Location (-1));
+
+                       if (converted != null)
+                               return converted;
 
                        //
                        // If no implicit conversion to bool exists, try using `operator true'
                        //
-                       if (converted == null){
-                               Expression operator_true = Expression.GetOperatorTrue (ec, e, loc);
-                               if (operator_true == null){
-                                       Report.Error (
-                                               31, loc, "Can not convert the expression to a boolean");
-                                       return null;
-                               }
-                               e = operator_true;
-                       } else
-                               e = converted;
-
-                       return e;
+                       Expression operator_true = Expression.GetOperatorTrue (ec, e, loc);
+                       if (operator_true == null){
+                               Report.Error (31, loc, "Can not convert the expression to a boolean");
+                               return null;
+                       }
+                       return operator_true;
                }
                
-               static string ExprClassName (ExprClass c)
+               public string ExprClassName ()
                {
-                       switch (c){
+                       switch (eclass){
                        case ExprClass.Invalid:
                                return "Invalid";
                        case ExprClass.Value:
@@ -848,17 +911,13 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Reports that we were expecting `expr' to be of class `expected'
                /// </summary>
-               public void Error_UnexpectedKind (string expected)
+               public void Error_UnexpectedKind (string expected, Location loc)
                {
-                       string kind = "Unknown";
-                       
-                       kind = ExprClassName (eclass);
-
-                       Error (118, "Expression denotes a `" + kind +
+                       Report.Error (118, loc, "Expression denotes a `" + ExprClassName () +
                               "' where a `" + expected + "' was expected");
                }
 
-               public void Error_UnexpectedKind (ResolveFlags flags)
+               public void Error_UnexpectedKind (ResolveFlags flags, Location loc)
                {
                        ArrayList valid = new ArrayList (10);
 
@@ -873,9 +932,6 @@ namespace Mono.CSharp {
                        if ((flags & ResolveFlags.MethodGroup) != 0)
                                valid.Add ("method group");
 
-                       if ((flags & ResolveFlags.SimpleName) != 0)
-                               valid.Add ("simple name");
-
                        if (valid.Count == 0)
                                valid.Add ("unknown");
 
@@ -888,9 +944,7 @@ namespace Mono.CSharp {
                                sb.Append (valid [i]);
                        }
 
-                       string kind = ExprClassName (eclass);
-
-                       Error (119, "Expression denotes a `" + kind + "' where " +
+                       Report.Error (119, loc, "Expression denotes a `" + ExprClassName () + "' where " +
                               "a `" + sb.ToString () + "' was expected");
                }
                
@@ -922,7 +976,7 @@ namespace Mono.CSharp {
                /// </summary>
                public static object ConvertIntLiteral (Constant c, Type target_type, Location loc)
                {
-                       if (!Convert.ImplicitStandardConversionExists (c, target_type)){
+                       if (!Convert.ImplicitStandardConversionExists (Convert.ConstantEC, c, target_type)){
                                Convert.Error_CannotImplicitConversion (loc, c.Type, target_type);
                                return null;
                        }
@@ -968,7 +1022,7 @@ namespace Mono.CSharp {
                                }
 
                                s = v.ToString ();
-                       } else if (c is UIntConstant){
+                       } else if (c is UIntConstant){
                                uint v = ((UIntConstant) c).Value;
 
                                if (target_type == TypeManager.int32_type){
@@ -994,7 +1048,7 @@ namespace Mono.CSharp {
                                else if (target_type == TypeManager.uint64_type)
                                        return (ulong) v;
                                s = v.ToString ();
-                       } else if (c is LongConstant){ 
+                       } else if (c is LongConstant){ 
                                long v = ((LongConstant) c).Value;
 
                                if (target_type == TypeManager.int32_type){
@@ -1023,7 +1077,7 @@ namespace Mono.CSharp {
                                                return (ulong) v;
                                }
                                s = v.ToString ();
-                       } else if (c is ULongConstant){
+                       } else if (c is ULongConstant){
                                ulong v = ((ULongConstant) c).Value;
 
                                if (target_type == TypeManager.int32_type){
@@ -1215,11 +1269,11 @@ namespace Mono.CSharp {
                                        ig.Emit (OpCodes.Ldind_Ref);
                                else
                                        LoadFromPtr (ig, TypeManager.EnumToUnderlying (t));
-                       } else if (t.IsValueType)
+                       } else if (t.IsValueType || t.IsGenericParameter)
                                ig.Emit (OpCodes.Ldobj, t);
                        else if (t.IsPointer)
                                ig.Emit (OpCodes.Ldind_I);
-                       else 
+                       else
                                ig.Emit (OpCodes.Ldind_Ref);
                }
 
@@ -1246,7 +1300,7 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Stind_I1);
                        else if (type == TypeManager.intptr_type)
                                ig.Emit (OpCodes.Stind_I);
-                       else if (type.IsValueType)
+                       else if (type.IsValueType || type.IsGenericParameter)
                                ig.Emit (OpCodes.Stobj, type);
                        else
                                ig.Emit (OpCodes.Stind_Ref);
@@ -1280,16 +1334,9 @@ namespace Mono.CSharp {
                                return 0;
                }
 
-               //
-               // Default implementation of IAssignMethod.CacheTemporaries
-               //
-               public virtual void CacheTemporaries (EmitContext ec)
+               public static void Error_NegativeArrayIndex (Location loc)
                {
-               }
-
-               static void Error_NegativeArrayIndex (Location loc)
-               {
-                       Report.Error (284, loc, "Can not create array with a negative size");
+                       Report.Error (248, loc, "Cannot create an array with a negative size");
                }
                
                //
@@ -1397,6 +1444,7 @@ namespace Mono.CSharp {
                public EmptyCast (Expression child, Type return_type)
                {
                        eclass = child.eclass;
+                       loc = child.Location;
                        type = return_type;
                        this.child = child;
                }
@@ -1451,6 +1499,18 @@ namespace Mono.CSharp {
                {
                        child.Emit (ec);
                }
+
+               public override bool IsDefaultValue {
+                       get {
+                               throw new NotImplementedException ();
+                       }
+               }
+
+               public override bool IsNegative {
+                       get {
+                               return false;
+                       }
+               }
        }
 
 
@@ -1485,6 +1545,11 @@ namespace Mono.CSharp {
                        return Child.GetValue ();
                }
 
+               public object GetValueAsEnumType ()
+               {
+                       return System.Enum.ToObject (type, Child.GetValue ());
+               }
+
                //
                // Converts from one of the valid underlying types for an enumeration
                // (int32, uint32, int64, uint64, short, ushort, byte, sbyte) to
@@ -1577,10 +1642,22 @@ namespace Mono.CSharp {
                {
                        return Child.ConvertToInt ();
                }
-               
+
+               public override bool IsDefaultValue {
+                       get {
+                               return Child.IsDefaultValue;
+                       }
+               }
+
                public override bool IsZeroInteger {
                        get { return Child.IsZeroInteger; }
                }
+
+               public override bool IsNegative {
+                       get {
+                               return Child.IsNegative;
+                       }
+               }
        }
 
        /// <summary>
@@ -1939,54 +2016,17 @@ namespace Mono.CSharp {
        }
        
        /// <summary>
-       ///   SimpleName expressions are initially formed of a single
-       ///   word and it only happens at the beginning of the expression.
+       ///   SimpleName expressions are formed of a single word and only happen at the beginning 
+       ///   of a dotted-name.
        /// </summary>
-       ///
-       /// <remarks>
-       ///   The expression will try to be bound to a Field, a Method
-       ///   group or a Property.  If those fail we pass the name to our
-       ///   caller and the SimpleName is compounded to perform a type
-       ///   lookup.  The idea behind this process is that we want to avoid
-       ///   creating a namespace map from the assemblies, as that requires
-       ///   the GetExportedTypes function to be called and a hashtable to
-       ///   be constructed which reduces startup time.  If later we find
-       ///   that this is slower, we should create a `NamespaceExpr' expression
-       ///   that fully participates in the resolution process. 
-       ///   
-       ///   For example `System.Console.WriteLine' is decomposed into
-       ///   MemberAccess (MemberAccess (SimpleName ("System"), "Console"), "WriteLine")
-       ///   
-       ///   The first SimpleName wont produce a match on its own, so it will
-       ///   be turned into:
-       ///   MemberAccess (SimpleName ("System.Console"), "WriteLine").
-       ///   
-       ///   System.Console will produce a TypeExpr match.
-       ///   
-       ///   The downside of this is that we might be hitting `LookupType' too many
-       ///   times with this scheme.
-       /// </remarks>
        public class SimpleName : Expression {
                public string Name;
                public readonly TypeArguments Arguments;
 
-               //
-               // If true, then we are a simple name, not composed with a ".
-               //
-               bool is_base;
-
-               public SimpleName (string a, string b, Location l)
-               {
-                       Name = String.Concat (a, ".", b);
-                       loc = l;
-                       is_base = false;
-               }
-               
                public SimpleName (string name, Location l)
                {
                        Name = name;
                        loc = l;
-                       is_base = true;
                }
 
                public SimpleName (string name, TypeArguments args, Location l)
@@ -1994,7 +2034,6 @@ namespace Mono.CSharp {
                        Name = name;
                        Arguments = args;
                        loc = l;
-                       is_base = true;
                }
 
                public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
@@ -2045,68 +2084,23 @@ namespace Mono.CSharp {
                        return SimpleNameResolve (ec, null, true, intermediate);
                }
 
-               public override Expression ResolveAsTypeStep (EmitContext ec)
+               public override FullNamedExpression ResolveAsTypeStep (EmitContext ec)
                {
                        DeclSpace ds = ec.DeclSpace;
-                       NamespaceEntry ns = ds.NamespaceEntry;
-                       TypeExpr t;
-                       IAlias alias_value;
-
-                       //
-                       // Since we are cheating: we only do the Alias lookup for
-                       // namespaces if the name does not include any dots in it
-                       //
-                       if (ns != null && is_base)
-                               alias_value = ns.LookupAlias (Name);
-                       else
-                               alias_value = null;
-
-                       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 = ds.FindType (loc, Name);
-                               
-                               if (Report.Errors != errors)
-                                       return null;
-                               
-                               if (dt != null)
-                                       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;
-                               }
-                       }
+                       FullNamedExpression dt;
 
-                       //
-                       // First, the using aliases
-                       //
-                       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;
-                               
-                               // we have alias value, but it isn't Type, so try if it's namespace
-                               return new SimpleName (alias_value.Name, loc);
-                       }
+                       dt = ds.LookupGeneric (Name, loc);
+                       if (dt != null)
+                               return dt.ResolveAsTypeStep (ec);
 
-                       //
-                       // Stage 2: Lookup up if we are an alias to a type
-                       // or a namespace.
-                       //
+                       int errors = Report.Errors;
+                       dt = ec.ResolvingTypeTree 
+                               ? ds.FindType (loc, Name)
+                               : ds.LookupType (Name, loc, /*silent=*/ true, /*ignore_cs0104=*/ false);
+                       if (Report.Errors != errors)
+                               return null;
 
-                       if ((t = RootContext.LookupType (ds, Name, true, loc)) != null)
-                               return t;
-                               
-                       // No match, maybe our parent can compose us
-                       // into something meaningful.
-                       return this;
+                       return dt;
                }
 
                Expression SimpleNameResolve (EmitContext ec, Expression right_side,
@@ -2118,12 +2112,9 @@ namespace Mono.CSharp {
 
                        Block current_block = ec.CurrentBlock;
                        if (current_block != null){
-                               LocalInfo vi = current_block.GetLocalInfo (Name);
-                               if (is_base &&
-                                   current_block.IsVariableNameUsedInChildBlock(Name)) {
+                               if (current_block.IsVariableNameUsedInChildBlock (Name)) {
                                        Report.Error (135, Location,
-                                                     "'{0}' has a different meaning in a " +
-                                                     "child block", Name);
+                                                     "'{0}' has a different meaning in a child block", Name);
                                        return null;
                                }
                        }
@@ -2174,21 +2165,12 @@ namespace Mono.CSharp {
                                                return var.Resolve (ec);
                                }
 
-                               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;
-                                       
-                                       param = new ParameterReference (pars, current_block, idx, Name, loc);
-
+                               ParameterReference pref = current_block.GetParameterReference (Name, loc);
+                               if (pref != null) {
                                        if (right_side != null)
-                                               return param.ResolveLValue (ec, right_side);
+                                               return pref.ResolveLValue (ec, right_side);
                                        else
-                                               return param.Resolve (ec);
+                                               return pref.Resolve (ec);
                                }
                        }
                        
@@ -2197,6 +2179,8 @@ namespace Mono.CSharp {
                        //
 
                        DeclSpace lookup_ds = ec.DeclSpace;
+                       Type almost_matched_type = null;
+                       ArrayList almost_matched = null;
                        do {
                                if (lookup_ds.TypeBuilder == null)
                                        break;
@@ -2205,6 +2189,11 @@ namespace Mono.CSharp {
                                if (e != null)
                                        break;
 
+                               if (almost_matched == null && almostMatchedMembers.Count > 0) {
+                                       almost_matched_type = lookup_ds.TypeBuilder;
+                                       almost_matched = (ArrayList) almostMatchedMembers.Clone ();
+                               }
+
                                lookup_ds =lookup_ds.Parent;
                        } while (lookup_ds != null);
 
@@ -2212,32 +2201,20 @@ namespace Mono.CSharp {
                                e = MemberLookup (ec, ec.ContainerType, Name, loc);
 
                        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;
-                                       }
+                               if (almost_matched == null && almostMatchedMembers.Count > 0) {
+                                       almost_matched_type = ec.ContainerType;
+                                       almost_matched = (ArrayList) almostMatchedMembers.Clone ();
                                }
+                               e = ResolveAsTypeStep (ec);
+                       }
 
-                               return ResolveAsTypeStep (ec);
+                       if (e == null) {
+                               if (almost_matched != null)
+                                       almostMatchedMembers = almost_matched;
+                               if (almost_matched_type == null)
+                                       almost_matched_type = ec.ContainerType;
+                               MemberLookupFailed (ec, null, almost_matched_type, ((SimpleName) this).Name, ec.DeclSpace.Name, loc);
+                               return null;
                        }
 
                        if (e is TypeExpr)
@@ -2267,8 +2244,9 @@ namespace Mono.CSharp {
                                        return e;
 
                                if (!me.IsStatic &&
-                                   TypeManager.IsNestedChildOf (me.InstanceExpression.Type, me.DeclaringType) &&
-                                   !me.InstanceExpression.Type.IsSubclassOf (me.DeclaringType) &&
+                                   TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
+                                   me.InstanceExpression.Type != me.DeclaringType &&
+                                   !TypeManager.IsFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
                                    (!intermediate || !MemberAccess.IdenticalNameAndTypeName (ec, this, e, loc))) {
                                        Error (38, "Cannot access nonstatic member `" + me.Name + "' of " +
                                               "outer type `" + me.DeclaringType + "' via nested type `" +
@@ -2307,12 +2285,27 @@ namespace Mono.CSharp {
                        return Name;
                }
        }
+
+       /// <summary>
+       ///   Represents a namespace or a type.  The name of the class was inspired by
+       ///   section 10.8.1 (Fully Qualified Names).
+       /// </summary>
+       public abstract class FullNamedExpression : Expression {
+               public override FullNamedExpression ResolveAsTypeStep (EmitContext ec)
+               {
+                       return this;
+               }
+
+               public abstract string FullName {
+                       get;
+               }
+       }
        
        /// <summary>
        ///   Fully resolved expression that evaluates to a type
        /// </summary>
-       public abstract class TypeExpr : Expression, IAlias {
-               override public Expression ResolveAsTypeStep (EmitContext ec)
+       public abstract class TypeExpr : FullNamedExpression {
+               override public FullNamedExpression ResolveAsTypeStep (EmitContext ec)
                {
                        TypeExpr t = DoResolveAsTypeStep (ec);
                        if (t == null)
@@ -2377,12 +2370,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public virtual TypeExpr[] GetInterfaces ()
-               {
-                       return TypeManager.GetInterfaces (Type);
-               }
-
-               public abstract TypeExpr DoResolveAsTypeStep (EmitContext ec);
+               protected abstract TypeExpr DoResolveAsTypeStep (EmitContext ec);
 
                public virtual Type ResolveType (EmitContext ec)
                {
@@ -2415,19 +2403,9 @@ namespace Mono.CSharp {
                {
                        return Name;
                }
-
-               bool IAlias.IsType {
-                       get { return true; }
-               }
-
-               TypeExpr IAlias.Type {
-                       get {
-                               return this;
-                       }
-               }
        }
 
-       public class TypeExpression : TypeExpr, IAlias {
+       public class TypeExpression : TypeExpr {
                public TypeExpression (Type t, Location l)
                {
                        Type = t;
@@ -2435,7 +2413,7 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
+               protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
                {
                        return this;
                }
@@ -2446,7 +2424,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               string IAlias.Name {
+               public override string FullName {
                        get {
                                return Type.FullName != null ? Type.FullName : Type.Name;
                        }
@@ -2466,17 +2444,16 @@ namespace Mono.CSharp {
                        this.name = name;
                }
 
-               public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
+               protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
                {
                        if (type == null) {
-                               TypeExpr texpr = RootContext.LookupType (
-                                       ec.DeclSpace, name, false, Location.Null);
-                               if (texpr == null)
+                               FullNamedExpression t = ec.DeclSpace.LookupType (
+                                       name, Location.Null, /*silent=*/ false, /*ignore_cs0104=*/ false);
+                               if (t == null)
                                        return null;
-
-                               type = texpr.ResolveType (ec);
-                               if (type == null)
+                               if (!(t is TypeExpr))
                                        return null;
+                               type = ((TypeExpr) t).ResolveType (ec);
                        }
 
                        return this;
@@ -2487,36 +2464,58 @@ namespace Mono.CSharp {
                                return name;
                        }
                }
+
+               public override string FullName {
+                       get {
+                               return name;
+                       }
+               }
        }
 
-       public class TypeAliasExpression : TypeExpr, IAlias {
+       /// <summary>
+       ///   Represents an "unbound generic type", ie. typeof (Foo<>).
+       ///   See 14.5.11.
+       /// </summary>
+       public class UnboundTypeExpression : TypeLookupExpression {
+               public UnboundTypeExpression (string name)
+                       : base (name)
+               { }
+       }
+
+       public class TypeAliasExpression : TypeExpr {
+               FullNamedExpression alias;
                TypeExpr texpr;
                TypeArguments args;
                string name;
 
-               public TypeAliasExpression (TypeExpr texpr, TypeArguments args, Location l)
+               public TypeAliasExpression (FullNamedExpression alias, TypeArguments args, Location l)
                {
-                       this.texpr = texpr;
+                       this.alias = alias;
                        this.args = args;
-                       loc = texpr.Location;
+                       loc = l;
 
                        eclass = ExprClass.Type;
                        if (args != null)
-                               name = texpr.Name + "<" + args.ToString () + ">";
+                               name = alias.FullName + "<" + args.ToString () + ">";
                        else
-                               name = texpr.Name;
+                               name = alias.FullName;
                }
 
                public override string Name {
+                       get { return alias.FullName; }
+               }
+
+               public override string FullName {
                        get { return name; }
                }
 
-               public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
+               protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
                {
-                       Type type = texpr.ResolveType (ec);
-                       if (type == null)
+                       texpr = alias.ResolveAsTypeTerminal (ec);
+                       if (texpr == null)
                                return null;
 
+                       Type type = texpr.Type;
                        int num_args = TypeManager.GetNumberOfTypeArguments (type);
 
                        if (args != null) {
@@ -2541,16 +2540,6 @@ namespace Mono.CSharp {
                        return new TypeExpression (type, loc);
                }
 
-               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);
@@ -2593,6 +2582,7 @@ namespace Mono.CSharp {
                bool is_explicit_impl = false;
                bool has_type_arguments = false;
                bool identical_type_name = false;
+               bool is_base;
                
                public MethodGroupExpr (MemberInfo [] mi, Location l)
                {
@@ -2677,6 +2667,15 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool IsBase {
+                       get {
+                               return is_base;
+                       }
+                       set {
+                               is_base = value;
+                       }
+               }
+
                public string Name {
                        get {
                                //return Methods [0].Name;
@@ -2823,9 +2822,9 @@ namespace Mono.CSharp {
                Expression instance_expr;
                VariableInfo variable_info;
                
-               LocalTemporary temporary;
-               IMemoryLocation instance_ml;
-               bool have_temporary;
+               LocalTemporary temp;
+               bool prepared;
+               bool is_field_initializer;
                
                public FieldExpr (FieldInfo fi, Location l)
                {
@@ -2869,6 +2868,16 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool IsFieldInitializer {
+                       get {
+                               return is_field_initializer;
+                       }
+
+                       set {
+                               is_field_initializer = value;
+                       }
+               }
+
                public VariableInfo VariableInfo {
                        get {
                                return variable_info;
@@ -2899,7 +2908,7 @@ namespace Mono.CSharp {
                        ObsoleteAttribute oa;
                        FieldBase f = TypeManager.GetField (FieldInfo);
                        if (f != null) {
-                               oa = f.GetObsoleteAttribute (ec.DeclSpace);
+                               oa = f.GetObsoleteAttribute (f.Parent);
                                if (oa != null)
                                        AttributeTester.Report_ObsoleteMessage (oa, f.GetSignatureForError (), loc);
                                // To be sure that type is external because we do not register generated fields
@@ -2909,6 +2918,16 @@ namespace Mono.CSharp {
                                        AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc);
                        }
 
+                       if (ec.CurrentAnonymousMethod != null){
+                               if (!FieldInfo.IsStatic){
+                                       if (ec.TypeContainer is Struct){
+                                               Report.Error (1673, loc, "Can not reference instance variables in anonymous methods hosted in structs");
+                                               return null;
+                                       }
+                                       ec.CaptureField (this);
+                               } 
+                       }
+                       
                        // If the instance expression is a local variable or parameter.
                        IVariable var = instance_expr as IVariable;
                        if ((var == null) || (var.VariableInfo == null))
@@ -2969,8 +2988,9 @@ namespace Mono.CSharp {
                                        Report_AssignToReadonly (false);
 
                                Type ctype;
-                               if (ec.TypeContainer.CurrentType != null)
-                                       ctype = ec.TypeContainer.CurrentType.ResolveType (ec);
+                               if (!is_field_initializer &&
+                                   (ec.TypeContainer.CurrentType != null))
+                                       ctype = ec.TypeContainer.CurrentType;
                                else
                                        ctype = ec.ContainerType;
 
@@ -2978,11 +2998,19 @@ namespace Mono.CSharp {
                                        return this;
                        }
 
-                       Report_AssignToReadonly (true);
+                       Report_AssignToReadonly (!IsStatic);
                        
                        return null;
                }
 
+               public override void CheckMarshallByRefAccess (Type container)
+               {
+                       if (!IsStatic && Type.IsValueType && !container.IsSubclassOf (TypeManager.mbr_type) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
+                               Report.SymbolRelatedToPreviousError (DeclaringType);
+                               Report.Error (1690, loc, "Cannot call '{0}' method, property, or indexer because it is a value type member of a marshal-by-reference class", Name);
+                       }
+               }
+
                public bool VerifyFixed (bool is_expression)
                {
                        IVariable variable = instance_expr as IVariable;
@@ -2991,37 +3019,8 @@ namespace Mono.CSharp {
 
                        return true;
                }
-
-               public override void CacheTemporaries (EmitContext ec)
-               {
-                       if (!FieldInfo.IsStatic && (temporary == null))
-                               temporary = new LocalTemporary (ec, instance_expr.Type);
-               }
-
-               void EmitInstance (EmitContext ec)
-               {
-                       if (instance_expr.Type.IsValueType)
-                               CacheTemporaries (ec);
-
-                       if ((temporary == null) || have_temporary)
-                               return;
-
-                       if (instance_expr.Type.IsValueType) {
-                               instance_ml = instance_expr as IMemoryLocation;
-                               if (instance_ml == null) {
-                                       instance_expr.Emit (ec);
-                                       temporary.Store (ec);
-                                       instance_ml = temporary;
-                               }
-                       } else {
-                               instance_expr.Emit (ec);
-                               temporary.Store (ec);
-                       }
-
-                       have_temporary = true;
-               }
-
-               override public void Emit (EmitContext ec)
+               
+               public void Emit (EmitContext ec, bool leave_copy)
                {
                        ILGenerator ig = ec.ig;
                        bool is_volatile = false;
@@ -3041,46 +3040,60 @@ namespace Mono.CSharp {
                                        ig.Emit (OpCodes.Volatile);
                                
                                ig.Emit (OpCodes.Ldsfld, FieldInfo);
-                               return;
+                       } else {
+                               if (!prepared)
+                                       EmitInstance (ec);
+
+                               if (is_volatile)
+                                       ig.Emit (OpCodes.Volatile);
+
+                               IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
+                               if (ff != null)
+                               {
+                                       ig.Emit (OpCodes.Ldflda, FieldInfo);
+                                       ig.Emit (OpCodes.Ldflda, ff.Element);
+                               }
+                               else {
+                                       ig.Emit (OpCodes.Ldfld, FieldInfo);
+                               }
                        }
-                       
-                       EmitInstance (ec);
-                       if (instance_ml != null)
-                               instance_ml.AddressOf (ec, AddressOp.Load);
-                       else if (temporary != null)
-                               temporary.Emit (ec);
-                       else
-                               instance_expr.Emit (ec);
 
-                       if (is_volatile)
-                               ig.Emit (OpCodes.Volatile);
-                       
-                       ig.Emit (OpCodes.Ldfld, FieldInfo);
+                       if (leave_copy) {
+                               ec.ig.Emit (OpCodes.Dup);
+                               if (!FieldInfo.IsStatic) {
+                                       temp = new LocalTemporary (ec, this.Type);
+                                       temp.Store (ec);
+                               }
+                       }
                }
 
-               public void EmitAssign (EmitContext ec, Expression source)
+               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
                {
                        FieldAttributes fa = FieldInfo.Attributes;
                        bool is_static = (fa & FieldAttributes.Static) != 0;
                        bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
                        ILGenerator ig = ec.ig;
+                       prepared = prepare_for_load;
 
                        if (is_readonly && !ec.IsConstructor){
                                Report_AssignToReadonly (!is_static);
                                return;
                        }
 
-                       if (!is_static){
+                       if (!is_static) {
                                EmitInstance (ec);
-                               if (instance_ml != null)
-                                       instance_ml.AddressOf (ec, AddressOp.Store);
-                               else if (temporary != null)
-                                       temporary.Emit (ec);
-                               else
-                                       instance_expr.Emit (ec);
+                               if (prepare_for_load)
+                                       ig.Emit (OpCodes.Dup);
                        }
 
                        source.Emit (ec);
+                       if (leave_copy) {
+                               ec.ig.Emit (OpCodes.Dup);
+                               if (!FieldInfo.IsStatic) {
+                                       temp = new LocalTemporary (ec, this.Type);
+                                       temp.Store (ec);
+                               }
+                       }
 
                        if (FieldInfo is FieldBuilder){
                                FieldBase f = TypeManager.GetField (FieldInfo);
@@ -3096,8 +3109,31 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Stsfld, FieldInfo);
                        else 
                                ig.Emit (OpCodes.Stfld, FieldInfo);
+                       
+                       if (temp != null)
+                               temp.Emit (ec);
                }
-               
+
+               void EmitInstance (EmitContext ec)
+               {
+                       if (instance_expr.Type.IsValueType) {
+                               if (instance_expr is IMemoryLocation) {
+                                       ((IMemoryLocation) instance_expr).AddressOf (ec, AddressOp.LoadStore);
+                               } else {
+                                       LocalTemporary t = new LocalTemporary (ec, instance_expr.Type);
+                                       instance_expr.Emit (ec);
+                                       t.Store (ec);
+                                       t.AddressOf (ec, AddressOp.Store);
+                               }
+                       } else
+                               instance_expr.Emit (ec);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       Emit (ec, false);
+               }
+
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        ILGenerator ig = ec.ig;
@@ -3147,20 +3183,7 @@ namespace Mono.CSharp {
                        if (FieldInfo.IsStatic){
                                ig.Emit (OpCodes.Ldsflda, FieldInfo);
                        } else {
-                               //
-                               // In the case of `This', we call the AddressOf method, which will
-                               // only load the pointer, and not perform an Ldobj immediately after
-                               // the value has been loaded into the stack.
-                               //
                                EmitInstance (ec);
-                               if (instance_ml != null)
-                                       instance_ml.AddressOf (ec, AddressOp.LoadStore);
-                               else if (temporary != null)
-                                       temporary.Emit (ec);
-                               else if (instance_expr is This)
-                                       ((This)instance_expr).AddressOf (ec, AddressOp.LoadStore);
-                               else
-                                       instance_expr.Emit (ec);
                                ig.Emit (OpCodes.Ldflda, FieldInfo);
                        }
                }
@@ -3196,11 +3219,12 @@ namespace Mono.CSharp {
                public bool IsBase;
                MethodInfo getter, setter;
                bool is_static;
-               bool must_do_cs1540_check;
                
                Expression instance_expr;
-               LocalTemporary temporary;
-               bool have_temporary;
+               LocalTemporary temp;
+               bool prepared;
+
+               internal static PtrHashtable AccessorTable = new PtrHashtable (); 
 
                public PropertyExpr (EmitContext ec, PropertyInfo pi, Location l)
                {
@@ -3263,7 +3287,7 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               MethodInfo FindAccessor (Type invocation_type, bool is_set)
+               void FindAccessors (Type invocation_type)
                {
                        BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
                                BindingFlags.Static | BindingFlags.Instance |
@@ -3280,87 +3304,21 @@ namespace Mono.CSharp {
 
                                if (group.Length != 1)
                                        // Oooops, can this ever happen ?
-                                       return null;
+                                       return;
 
                                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;
-
-                       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 (invocation_type != declaring_type){
-                                       if (TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType))
-                                               return mi;
-                                       else
-                                               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)
-                                       return mi;
-                       }
+                               if (getter == null)
+                                       getter = pi.GetGetMethod (true);
 
-                       // We already know that we aren't in the same assembly.
-                       if (ma == MethodAttributes.Assembly)
-                               return null;
+                               if (setter == null)
+                                       setter = pi.GetSetMethod (true);
 
-                       // 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;
+                               MethodInfo accessor = getter != null ? getter : setter;
 
-                                       return mi;
-                               }
+                               if (!accessor.IsVirtual)
+                                       return;
                        }
-
-                       return mi;
                }
 
                //
@@ -3369,20 +3327,20 @@ namespace Mono.CSharp {
                //
                void ResolveAccessors (EmitContext ec)
                {
-                       getter = GetAccessor (ec.ContainerType, false);
-                       if ((getter != null) && getter.IsStatic)
-                               is_static = true;
+                       FindAccessors (ec.ContainerType);
 
-                       setter = GetAccessor (ec.ContainerType, true);
-                       if ((setter != null) && setter.IsStatic)
-                               is_static = true;
+                       if (getter != null) {
+                               AccessorTable [getter] = PropertyInfo;
+                               is_static = getter.IsStatic;
+                       }
 
-                       if (setter == null && getter == null){
-                               Report.Error_T (122, loc, PropertyInfo.Name);
+                       if (setter != null) {
+                               AccessorTable [setter] = PropertyInfo;
+                               is_static = setter.IsStatic;
                        }
                }
 
-               bool InstanceResolve (EmitContext ec)
+               bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
                {
                        if ((instance_expr == null) && ec.IsStatic && !is_static) {
                                SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
@@ -3393,6 +3351,8 @@ namespace Mono.CSharp {
                                instance_expr = instance_expr.DoResolve (ec);
                                if (instance_expr == null)
                                        return false;
+
+                               instance_expr.CheckMarshallByRefAccess (ec.ContainerType);
                        }
 
                        if (must_do_cs1540_check && (instance_expr != null)) {
@@ -3441,7 +3401,13 @@ namespace Mono.CSharp {
                                return null;
                        } 
 
-                       if (!InstanceResolve (ec))
+                       bool must_do_cs1540_check;
+                       if (!IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) {
+                               Report.Error (122, loc, "'{0}.get' is inaccessible due to its protection level", PropertyInfo.Name);
+                               return null;
+                       }
+
+                       if (!InstanceResolve (ec, must_do_cs1540_check))
                                return null;
 
                        //
@@ -3483,7 +3449,13 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       if (!InstanceResolve (ec))
+                       bool must_do_cs1540_check;
+                       if (!IsAccessorAccessible (ec.ContainerType, setter, out must_do_cs1540_check)) {
+                               Report.Error (122, loc, "'{0}.set' is inaccessible due to its protection level", PropertyInfo.Name);
+                               return null;
+                       }
+
+                       if (!InstanceResolve (ec, must_do_cs1540_check))
                                return null;
                        
                        //
@@ -3494,32 +3466,53 @@ namespace Mono.CSharp {
                                              PropertyInfo.DeclaringType + "." +PropertyInfo.Name);
                                return null;
                        }
+
+                       //
+                       // Check that we are not making changes to a temporary memory location
+                       //
+                       if (instance_expr != null && instance_expr.Type.IsValueType && !(instance_expr is IMemoryLocation)) {
+                               // FIXME: Provide better error reporting.
+                               Error (1612, "Cannot modify expression because it is not a variable.");
+                               return null;
+                       }
+
                        return this;
                }
 
-               public override void CacheTemporaries (EmitContext ec)
+
+               
+               public override void Emit (EmitContext ec)
                {
-                       if (!is_static)
-                               temporary = new LocalTemporary (ec, instance_expr.Type);
+                       Emit (ec, false);
                }
-
-               Expression EmitInstance (EmitContext ec)
+               
+               void EmitInstance (EmitContext ec)
                {
-                       if (temporary != null){
-                               if (!have_temporary){
+                       if (is_static)
+                               return;
+
+                       if (instance_expr.Type.IsValueType) {
+                               if (instance_expr is IMemoryLocation) {
+                                       ((IMemoryLocation) instance_expr).AddressOf (ec, AddressOp.LoadStore);
+                               } else {
+                                       LocalTemporary t = new LocalTemporary (ec, instance_expr.Type);
                                        instance_expr.Emit (ec);
-                                       temporary.Store (ec);
-                                       have_temporary = true;
+                                       t.Store (ec);
+                                       t.AddressOf (ec, AddressOp.Store);
                                }
-                               return temporary;
                        } else
-                               return instance_expr;
+                               instance_expr.Emit (ec);
+                       
+                       if (prepared)
+                               ec.ig.Emit (OpCodes.Dup);
                }
 
-               override public void Emit (EmitContext ec)
+               
+               public void Emit (EmitContext ec, bool leave_copy)
                {
-                       Expression expr = EmitInstance (ec);
-
+                       if (!prepared)
+                               EmitInstance (ec);
+                       
                        //
                        // Special case: length of single dimension array property is turned into ldlen
                        //
@@ -3531,30 +3524,50 @@ namespace Mono.CSharp {
                                // System.Array.Length can be called, but the Type does not
                                // support invoking GetArrayRank, so test for that case first
                                //
-                               if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)){
-                                       expr.Emit (ec);
+                               if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)) {
                                        ec.ig.Emit (OpCodes.Ldlen);
                                        ec.ig.Emit (OpCodes.Conv_I4);
                                        return;
                                }
                        }
 
-                       Invocation.EmitCall (ec, IsBase, IsStatic, expr, getter, null, loc);
+                       Invocation.EmitCall (ec, IsBase, IsStatic, new EmptyAddressOf (), getter, null, loc);
+                       
+                       if (!leave_copy)
+                               return;
                        
+                       ec.ig.Emit (OpCodes.Dup);
+                       if (!is_static) {
+                               temp = new LocalTemporary (ec, this.Type);
+                               temp.Store (ec);
+                       }
                }
 
                //
                // Implements the IAssignMethod interface for assignments
                //
-               public void EmitAssign (EmitContext ec, Expression source)
+               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
                {
-                       Expression expr = EmitInstance (ec);
-
-                       Argument arg = new Argument (source, Argument.AType.Expression);
-                       ArrayList args = new ArrayList ();
+                       prepared = prepare_for_load;
+                       
+                       EmitInstance (ec);
 
-                       args.Add (arg);
-                       Invocation.EmitCall (ec, IsBase, IsStatic, expr, setter, args, loc);
+                       source.Emit (ec);
+                       if (leave_copy) {
+                               ec.ig.Emit (OpCodes.Dup);
+                               if (!is_static) {
+                                       temp = new LocalTemporary (ec, this.Type);
+                                       temp.Store (ec);
+                               }
+                       }
+                       
+                       ArrayList args = new ArrayList (1);
+                       args.Add (new Argument (new EmptyAddressOf (), Argument.AType.Expression));
+                       
+                       Invocation.EmitCall (ec, IsBase, IsStatic, new EmptyAddressOf (), setter, args, loc);
+                       
+                       if (temp != null)
+                               temp.Emit (ec);
                }
 
                override public void EmitStatement (EmitContext ec)
@@ -3628,6 +3641,41 @@ namespace Mono.CSharp {
                        }
                }
 
+               bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
+               {
+                       if ((instance_expr == null) && ec.IsStatic && !is_static) {
+                               SimpleName.Error_ObjectRefRequired (ec, loc, EventInfo.Name);
+                               return false;
+                       }
+
+                       if (instance_expr != null) {
+                               instance_expr = instance_expr.DoResolve (ec);
+                               if (instance_expr == null)
+                                       return false;
+                       }
+
+                       //
+                       // This is using the same mechanism as the CS1540 check in PropertyExpr.
+                       // However, in the Event case, we reported a CS0122 instead.
+                       //
+                       if (must_do_cs1540_check && (instance_expr != null)) {
+                               if ((instance_expr.Type != ec.ContainerType) &&
+                                       ec.ContainerType.IsSubclassOf (instance_expr.Type)) {
+                                       Report.Error (122, loc, "'{0}' is inaccessible due to its protection level",
+                                               DeclaringType.Name + "." + EventInfo.Name);
+
+                                       return false;
+                               }
+                       }
+
+                       return true;
+               }
+
+               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       return DoResolve (ec);
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        if (instance_expr != null) {
@@ -3636,13 +3684,28 @@ namespace Mono.CSharp {
                                        return null;
                        }
 
+                       bool must_do_cs1540_check;
+                       if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check)
+                                   && IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
+                               
+                               Report.Error (122, loc, "'{0}' is inaccessible due to its protection level",
+                                               DeclaringType.Name + "." + EventInfo.Name);
+                               return null;
+                       }
+
+                       if (!InstanceResolve (ec, must_do_cs1540_check))
+                               return null;
                        
                        return this;
-               }
+               }               
 
                public override void Emit (EmitContext ec)
                {
-                       Report.Error (70, loc, "The event `" + Name + "' can only appear on the left hand side of += or -= (except on the defining type)");
+                       if (instance_expr is This)
+                               Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=, try calling the actual delegate", Name);
+                       else
+                               Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
+                                             "(except on the defining type)", Name);
                }
 
                public void EmitAddOrRemove (EmitContext ec, Expression source)