Rework gc descriptor to include size information in more cases.
[mono.git] / mcs / mcs / ecore.cs
index cb7a01e3515498146dad84f8010058b3b5241f53..6263adab8b99b96e64fe7e943f8ea1baf4447c5c 100644 (file)
@@ -7,6 +7,7 @@
 //
 // Copyright 2001, 2002, 2003 Ximian, Inc.
 // Copyright 2003-2008 Novell, Inc.
+// Copyright 2011 Xamarin Inc.
 //
 //
 
@@ -130,13 +131,14 @@ namespace Mono.CSharp {
                        set { type = value; }
                }
 
-               public Location Location {
-                       get { return loc; }
+               public virtual bool IsSideEffectFree {
+                       get {
+                               return false;
+                       }
                }
 
-               public virtual string GetSignatureForError ()
-               {
-                       return type.GetDefinition ().GetSignatureForError ();
+               public Location Location {
+                       get { return loc; }
                }
 
                public virtual bool IsNull {
@@ -145,6 +147,15 @@ namespace Mono.CSharp {
                        }
                }
 
+               //
+               // Returns true when the expression during Emit phase breaks stack
+               // by using await expression
+               //
+               public virtual bool ContainsEmitWithAwait ()
+               {
+                       return false;
+               }
+
                /// <summary>
                ///   Performs semantic analysis on the Expression
                /// </summary>
@@ -183,66 +194,16 @@ namespace Mono.CSharp {
                // This is used if the expression should be resolved as a type or namespace name.
                // the default implementation fails.   
                //
-               public virtual FullNamedExpression ResolveAsTypeStep (IMemberContext rc,  bool silent)
+               public virtual TypeSpec ResolveAsType (IMemberContext mc)
                {
-                       if (!silent) {
-                               ResolveContext ec = new ResolveContext (rc);
-                               Expression e = Resolve (ec);
-                               if (e != null)
-                                       e.Error_UnexpectedKind (ec, ResolveFlags.Type, loc);
-                       }
+                       ResolveContext ec = new ResolveContext (mc);
+                       Expression e = Resolve (ec);
+                       if (e != null)
+                               e.Error_UnexpectedKind (ec, ResolveFlags.Type, loc);
 
                        return null;
                }
 
-               //
-               // This is used to resolve the expression as a type, a null
-               // value will be returned if the expression is not a type
-               // reference
-               //
-               public virtual TypeExpr ResolveAsTypeTerminal (IMemberContext ec , bool silent)
-               {
-                       // FIXME: THIS IS TOO SLOW and it should not be needed either
-                       int errors = ec.Module.Compiler.Report.Errors;
-
-                       FullNamedExpression fne = ResolveAsTypeStep (ec, silent);
-
-                       if (fne == null)
-                               return null;
-                               
-                       TypeExpr te = fne as TypeExpr;                          
-                       if (te == null) {
-                               if (!silent && errors == ec.Module.Compiler.Report.Errors)
-                                       fne.Error_UnexpectedKind (ec.Module.Compiler.Report, null, "type", loc);
-                               return null;
-                       }
-
-                       if (!te.type.IsAccessible (ec)) {
-                               ec.Module.Compiler.Report.SymbolRelatedToPreviousError (te.Type);
-                               ErrorIsInaccesible (ec, te.Type.GetSignatureForError (), loc);
-                       }
-
-                       te.loc = loc;
-
-                       var dep = te.type.GetMissingDependencies ();
-                       if (dep != null) {
-                               ImportedTypeDefinition.Error_MissingDependency (ec, dep, loc);
-                       }
-
-                       //
-                       // Obsolete checks cannot be done when resolving base context as they
-                       // require type dependecies to be set but we are just resolving them
-                       //
-                       if (!silent && !(ec is TypeContainer.BaseContext)) {
-                               ObsoleteAttribute obsolete_attr = te.Type.GetAttributeObsolete ();
-                               if (obsolete_attr != null && !ec.IsObsolete) {
-                                       AttributeTester.Report_ObsoleteMessage (obsolete_attr, te.GetSignatureForError (), Location, ec.Module.Compiler.Report);
-                               }
-                       }
-
-                       return te;
-               }
-       
                public static void ErrorIsInaccesible (IMemberContext rc, string member, Location loc)
                {
                        rc.Module.Compiler.Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", member);
@@ -289,8 +250,8 @@ namespace Mono.CSharp {
                        string from_type = type.GetSignatureForError ();
                        string to_type = target.GetSignatureForError ();
                        if (from_type == to_type) {
-                               from_type = string.Format ("{0} [{1}]", from_type, type.MemberDefinition.DeclaringAssembly.FullName);
-                               to_type = string.Format ("{0} [{1}]", to_type, target.MemberDefinition.DeclaringAssembly.FullName);
+                               from_type = type.GetSignatureForErrorIncludingAssemblyName ();
+                               to_type = target.GetSignatureForErrorIncludingAssemblyName ();
                        }
 
                        if (expl) {
@@ -313,10 +274,11 @@ namespace Mono.CSharp {
                        }
                }
 
-               public void Error_TypeArgumentsCannotBeUsed (Report report, Location loc, MemberSpec member, int arity)
+               public void Error_TypeArgumentsCannotBeUsed (IMemberContext context, MemberSpec member, int arity, Location loc)
                {
                        // Better message for possible generic expressions
                        if (member != null && (member.Kind & MemberKind.GenericMask) != 0) {
+                               var report = context.Module.Compiler.Report;
                                report.SymbolRelatedToPreviousError (member);
                                if (member is TypeSpec)
                                        member = ((TypeSpec) member).GetDefinition ();
@@ -332,13 +294,13 @@ namespace Mono.CSharp {
                                                name, member.GetSignatureForError ());
                                }
                        } else {
-                               Error_TypeArgumentsCannotBeUsed (report, ExprClassName, GetSignatureForError (), loc);
+                               Error_TypeArgumentsCannotBeUsed (context, ExprClassName, GetSignatureForError (), loc);
                        }
                }
 
-               public void Error_TypeArgumentsCannotBeUsed (Report report, string exprType, string name, Location loc)
+               public void Error_TypeArgumentsCannotBeUsed (IMemberContext context, string exprType, string name, Location loc)
                {
-                       report.Error (307, loc, "The {0} `{1}' cannot be used with type arguments",
+                       context.Module.Compiler.Report.Error (307, loc, "The {0} `{1}' cannot be used with type arguments",
                                exprType, name);
                }
 
@@ -354,9 +316,20 @@ namespace Mono.CSharp {
                                TypeManager.CSharpName (type), name);
                }
 
-               protected static void Error_ValueAssignment (ResolveContext ec, Location loc)
+               public void Error_ValueAssignment (ResolveContext rc, Expression rhs)
                {
-                       ec.Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer");
+                       if (rhs == EmptyExpression.LValueMemberAccess || rhs == EmptyExpression.LValueMemberOutAccess) {
+                               rc.Report.SymbolRelatedToPreviousError (type);
+                               if (rc.CurrentInitializerVariable != null) {
+                                       rc.Report.Error (1918, loc, "Members of value type `{0}' cannot be assigned using a property `{1}' object initializer",
+                                               type.GetSignatureForError (), GetSignatureForError ());
+                               } else {
+                                       rc.Report.Error (1612, loc, "Cannot modify a value type return value of `{0}'. Consider storing the value in a temporary variable",
+                                               GetSignatureForError ());
+                               }
+                       } else {
+                               rc.Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer");
+                       }
                }
 
                protected void Error_VoidPointerOperation (ResolveContext rc)
@@ -389,6 +362,11 @@ namespace Mono.CSharp {
                                }
                        }
                }
+
+               public virtual string GetSignatureForError ()
+               {
+                       return type.GetDefinition ().GetSignatureForError ();
+               }
               
                /// <summary>
                ///   Resolves an expression and performs semantic analysis on it.
@@ -424,7 +402,7 @@ namespace Mono.CSharp {
                                        throw;
 
                                ec.Report.Error (584, loc, "Internal compiler error: {0}", ex.Message);
-                               return EmptyExpression.Null;    // TODO: Add location
+                               return ErrorExpression.Instance;        // TODO: Add location
                        }
                }
 
@@ -465,7 +443,7 @@ namespace Mono.CSharp {
                                        if (out_access)
                                                ec.Report.Error (1510, loc, "A ref or out argument must be an assignable variable");
                                        else
-                                               Error_ValueAssignment (ec, loc);
+                                               Error_ValueAssignment (ec, right_side);
                                }
                                return null;
                        }
@@ -515,6 +493,107 @@ namespace Mono.CSharp {
                        ec.Emit (OpCodes.Pop);
                }
 
+               //
+               // Emits the expression into temporary field variable. The method
+               // should be used for await expressions only
+               //
+               public virtual Expression EmitToField (EmitContext ec)
+               {
+                       //
+                       // This is the await prepare Emit method. When emitting code like
+                       // a + b we emit code like
+                       //
+                       // a.Emit ()
+                       // b.Emit ()
+                       // Opcodes.Add
+                       //
+                       // For await a + await b we have to interfere the flow to keep the
+                       // stack clean because await yields from the expression. The emit
+                       // then changes to
+                       //
+                       // a = a.EmitToField () // a is changed to temporary field access
+                       // b = b.EmitToField ()
+                       // a.Emit ()
+                       // b.Emit ()
+                       // Opcodes.Add
+                       //
+                       //
+                       // The idea is to emit expression and leave the stack empty with
+                       // result value still available.
+                       //
+                       // Expressions should override this default implementation when
+                       // optimized version can be provided (e.g. FieldExpr)
+                       //
+                       //
+                       // We can optimize for side-effect free expressions, they can be
+                       // emitted out of order
+                       //
+                       if (IsSideEffectFree)
+                               return this;
+
+                       bool needs_temporary = ContainsEmitWithAwait ();
+                       if (!needs_temporary)
+                               ec.EmitThis ();
+
+                       // Emit original code
+                       EmitToFieldSource (ec);
+
+                       //
+                       // Store the result to temporary field when we
+                       // cannot load `this' directly
+                       //
+                       var field = ec.GetTemporaryField (type);
+                       if (needs_temporary) {
+                               //
+                               // Create temporary local (we cannot load `this' before Emit)
+                               //
+                               var temp = ec.GetTemporaryLocal (type);
+                               ec.Emit (OpCodes.Stloc, temp);
+
+                               ec.EmitThis ();
+                               ec.Emit (OpCodes.Ldloc, temp);
+                               field.EmitAssignFromStack (ec);
+
+                               ec.FreeTemporaryLocal (temp, type);
+                       } else {
+                               field.EmitAssignFromStack (ec);
+                       }
+
+                       return field;
+               }
+
+               protected virtual void EmitToFieldSource (EmitContext ec)
+               {
+                       //
+                       // Default implementation calls Emit method
+                       //
+                       Emit (ec);
+               }
+
+               protected static void EmitExpressionsList (EmitContext ec, List<Expression> expressions)
+               {
+                       if (ec.HasSet (BuilderContext.Options.AsyncBody)) {
+                               bool contains_await = false;
+
+                               for (int i = 1; i < expressions.Count; ++i) {
+                                       if (expressions[i].ContainsEmitWithAwait ()) {
+                                               contains_await = true;
+                                               break;
+                                       }
+                               }
+
+                               if (contains_await) {
+                                       for (int i = 0; i < expressions.Count; ++i) {
+                                               expressions[i] = expressions[i].EmitToField (ec);
+                                       }
+                               }
+                       }
+
+                       for (int i = 0; i < expressions.Count; ++i) {
+                               expressions[i].Emit (ec);
+                       }
+               }
+
                /// <summary>
                ///   Protected constructor.  Only derivate types should
                ///   be able to be created
@@ -544,7 +623,7 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               protected static MethodSpec ConstructorLookup (ResolveContext rc, TypeSpec type, ref Arguments args, Location loc)
+               public static MethodSpec ConstructorLookup (ResolveContext rc, TypeSpec type, ref Arguments args, Location loc)
                {
                        var ctors = MemberCache.FindMembers (type, Constructor.ConstructorName, true);
                        if (ctors == null) {
@@ -561,6 +640,10 @@ namespace Mono.CSharp {
                        }
 
                        var r = new OverloadResolver (ctors, OverloadResolver.Restrictions.NoBaseMembers, loc);
+                       if (!rc.HasSet (ResolveContext.Options.BaseInitializer)) {
+                               r.InstanceQualifier = new ConstructorInstanceQualifier (type);
+                       }
+
                        return r.ResolveMember<MethodSpec> (rc, ref args);
                }
 
@@ -593,6 +676,9 @@ namespace Mono.CSharp {
                                        if ((member.Modifiers & Modifiers.OVERRIDE) != 0 && member.Kind != MemberKind.Event)
                                                continue;
 
+                                       if ((member.Modifiers & Modifiers.BACKING_FIELD) != 0)
+                                               continue;
+
                                        if ((arity > 0 || (restrictions & MemberLookupRestrictions.ExactArity) != 0) && member.Arity != arity)
                                                continue;
 
@@ -626,9 +712,9 @@ namespace Mono.CSharp {
                                                        continue;
                                        }
 
-                                       if (non_method == null || member is MethodSpec) {
+                                       if (non_method == null || member is MethodSpec || non_method.IsNotCSharpCompatible) {
                                                non_method = member;
-                                       } else if (!errorMode) {
+                                       } else if (!errorMode && !member.IsNotCSharpCompatible) {
                                                ambig_non_method = member;
                                        }
                                }
@@ -663,6 +749,12 @@ namespace Mono.CSharp {
                        throw new NotImplementedException ();
                }
 
+               public virtual void Error_OperatorCannotBeApplied (ResolveContext rc, Location loc, string oper, TypeSpec t)
+               {
+                       rc.Report.Error (23, loc, "The `{0}' operator cannot be applied to operand of type `{1}'",
+                               oper, t.GetSignatureForError ());
+               }
+
                protected void Error_PointerInsideExpressionTree (ResolveContext ec)
                {
                        ec.Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation");
@@ -756,7 +848,7 @@ namespace Mono.CSharp {
                              name, was, expected);
                }
 
-               public void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc)
+               public virtual void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc)
                {
                        string [] valid = new string [4];
                        int count = 0;
@@ -799,18 +891,6 @@ namespace Mono.CSharp {
                        Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context");
                }
 
-               protected void Error_CannotModifyIntermediateExpressionValue (ResolveContext ec)
-               {
-                       ec.Report.SymbolRelatedToPreviousError (type);
-                       if (ec.CurrentInitializerVariable != null) {
-                               ec.Report.Error (1918, loc, "Members of value type `{0}' cannot be assigned using a property `{1}' object initializer",
-                                       TypeManager.CSharpName (type), GetSignatureForError ());
-                       } else {
-                               ec.Report.Error (1612, loc, "Cannot modify a value type return value of `{0}'. Consider storing the value in a temporary variable",
-                                       GetSignatureForError ());
-                       }
-               }
-
                //
                // Converts `source' to an int, uint, long or ulong.
                //
@@ -910,7 +990,7 @@ namespace Mono.CSharp {
 
                protected static TypeExpr CreateExpressionTypeExpression (ResolveContext ec, Location loc)
                {
-                       var t = ec.Module.PredefinedTypes.Expression.Resolve (loc);
+                       var t = ec.Module.PredefinedTypes.Expression.Resolve ();
                        if (t == null)
                                return null;
 
@@ -926,6 +1006,11 @@ namespace Mono.CSharp {
                {
                        throw new NotImplementedException ("MakeExpression for " + GetType ());
                }
+                       
+               public virtual object Accept (StructuralVisitor visitor)
+               {
+                       return visitor.Visit (this);
+               }
        }
 
        /// <summary>
@@ -994,11 +1079,16 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override bool ContainsEmitWithAwait ()
+               {
+                       return child.ContainsEmitWithAwait ();
+               }
+
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
                        Arguments args = new Arguments (2);
                        args.Add (new Argument (child.CreateExpressionTree (ec)));
-                       args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
+                       args.Add (new Argument (new TypeOf (type, loc)));
 
                        if (type.IsPointer || child.Type.IsPointer)
                                Error_PointerInsideExpressionTree (ec);
@@ -1149,7 +1239,7 @@ namespace Mono.CSharp {
                {
                        Arguments args = Arguments.CreateForExpressionTree (ec, null,
                                child.CreateExpressionTree (ec),
-                               new TypeOf (new TypeExpression (type, loc), loc));
+                               new TypeOf (type, loc));
 
                        if (type.IsPointer)
                                Error_PointerInsideExpressionTree (ec);
@@ -1173,6 +1263,12 @@ namespace Mono.CSharp {
                        get { return child.IsOneInteger; }
                }
 
+               public override bool IsSideEffectFree {
+                       get {
+                               return child.IsSideEffectFree;
+                       }
+               }
+
                public override bool IsZeroInteger {
                        get { return child.IsZeroInteger; }
                }
@@ -1310,6 +1406,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override bool IsSideEffectFree {
+                       get {
+                               return Child.IsSideEffectFree;
+                       }
+               }
+
                public override bool IsZeroInteger {
                        get { return Child.IsZeroInteger; }
                }
@@ -1764,6 +1866,17 @@ namespace Mono.CSharp {
                                        c = new ReducedConstantExpression (c, orig_expr);
                                return c;
                        }
+
+                       public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
+                       {
+                               //
+                               // LAMESPEC: Reduced conditional expression is allowed as an attribute argument
+                               //
+                               if (orig_expr is Conditional)
+                                       child.EncodeAttributeValue (rc, enc, targetType);
+                               else
+                                       base.EncodeAttributeValue (rc, enc, targetType);
+                       }
                }
 
                sealed class ReducedExpressionStatement : ExpressionStatement
@@ -1781,6 +1894,11 @@ namespace Mono.CSharp {
                                this.loc = orig.Location;
                        }
 
+                       public override bool ContainsEmitWithAwait ()
+                       {
+                               return stm.ContainsEmitWithAwait ();
+                       }
+
                        public override Expression CreateExpressionTree (ResolveContext ec)
                        {
                                return orig_expr.CreateExpressionTree (ec);
@@ -1823,6 +1941,11 @@ namespace Mono.CSharp {
 
                #endregion
 
+               public override bool ContainsEmitWithAwait ()
+               {
+                       return expr.ContainsEmitWithAwait ();
+               }
+
                //
                // Creates fully resolved expression switcher
                //
@@ -1906,18 +2029,23 @@ namespace Mono.CSharp {
                        this.loc = expr.Location;
                }
 
-               public override Expression CreateExpressionTree (ResolveContext ec)
+               public override bool ContainsEmitWithAwait ()
                {
-                       return expr.CreateExpressionTree (ec);
+                       return expr.ContainsEmitWithAwait ();
+               }
+
+               public override Expression CreateExpressionTree (ResolveContext rc)
+               {
+                       return expr.CreateExpressionTree (rc);
                }
 
                public Expression Child {
                        get { return expr; }
                }
 
-               protected override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext rc)
                {
-                       expr = expr.Resolve (ec);
+                       expr = expr.Resolve (rc);
                        if (expr != null) {
                                type = expr.Type;
                                eclass = expr.eclass;
@@ -1948,6 +2076,12 @@ namespace Mono.CSharp {
                        this.expr = expr;
                }
 
+               public Expression Expr {
+                       get {
+                               return expr;
+                       }
+               }
+
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        if (expr == null)
@@ -1957,6 +2091,11 @@ namespace Mono.CSharp {
                        target.expr = expr.Clone (clonectx);
                }
 
+               public override bool ContainsEmitWithAwait ()
+               {
+                       return expr.ContainsEmitWithAwait ();
+               }
+
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
                        throw new NotSupportedException ("ET");
@@ -1967,9 +2106,6 @@ namespace Mono.CSharp {
                        throw new InternalErrorException ("Missing Resolve call");
                }
 
-               public Expression Expr {
-                       get { return expr; }
-               }
        }
 
        //
@@ -2098,77 +2234,63 @@ namespace Mono.CSharp {
                        return new SimpleName (Name, targs, loc);
                }
 
-               protected virtual void Error_TypeOrNamespaceNotFound (IMemberContext ec)
+               protected override Expression DoResolve (ResolveContext rc)
+               {
+                       var e = SimpleNameResolve (rc, null, false);
+
+                       var fe = e as FieldExpr;
+                       if (fe != null) {
+                               fe.VerifyAssignedStructField (rc, null);
+                       }
+
+                       return e;
+               }
+
+               public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
+               {
+                       return SimpleNameResolve (ec, right_side, false);
+               }
+
+               protected virtual void Error_TypeOrNamespaceNotFound (IMemberContext ctx)
                {
-                       if (ec.CurrentType != null) {
-                               if (ec.CurrentMemberDefinition != null) {
-                                       MemberCore mc = ec.CurrentMemberDefinition.Parent.GetDefinition (Name);
+                       if (ctx.CurrentType != null) {
+                               if (ctx.CurrentMemberDefinition != null) {
+                                       MemberCore mc = ctx.CurrentMemberDefinition.Parent.GetDefinition (Name);
                                        if (mc != null) {
-                                               Error_UnexpectedKind (ec.Module.Compiler.Report, mc, "type", GetMemberType (mc), loc);
+                                               Error_UnexpectedKind (ctx.Module.Compiler.Report, mc, "type", GetMemberType (mc), loc);
                                                return;
                                        }
                                }
-
-                               /*
-                                                               // TODO MemberCache: Implement
-                                                               string ns = ec.CurrentType.Namespace;
-                                                               string fullname = (ns.Length > 0) ? ns + "." + Name : Name;
-                                                               foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) {
-                                                                       var type = a.GetType (fullname);
-                                                                       if (type != null) {
-                                                                               ec.Compiler.Report.SymbolRelatedToPreviousError (type);
-                                                                               Expression.ErrorIsInaccesible (loc, TypeManager.CSharpName (type), ec.Compiler.Report);
-                                                                               return;
-                                                                       }
-                                                               }
-
-                                                               if (ec.CurrentTypeDefinition != null) {
-                                                                       TypeSpec t = ec.CurrentTypeDefinition.LookupAnyGeneric (Name);
-                                                                       if (t != null) {
-                                                                               Namespace.Error_InvalidNumberOfTypeArguments (ec.Compiler.Report, t, loc);
-                                                                               return;
-                                                                       }
-                                                               }
-                               */
                        }
 
-                       FullNamedExpression retval = ec.LookupNamespaceOrType (Name, -System.Math.Max (1, Arity), loc, true);
+                       var retval = ctx.LookupNamespaceOrType (Name, Arity, LookupMode.IgnoreAccessibility, loc);
                        if (retval != null) {
-                               Error_TypeArgumentsCannotBeUsed (ec.Module.Compiler.Report, loc, retval.Type, Arity);
-/*
-                               var te = retval as TypeExpr;
-                               if (HasTypeArguments && te != null && !te.Type.IsGeneric)
-                                       retval.Error_TypeArgumentsCannotBeUsed (ec.Compiler.Report, loc);
-                               else
-                                       Namespace.Error_InvalidNumberOfTypeArguments (ec.Compiler.Report, retval.Type, loc);
-*/
+                               ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (retval.Type);
+                               ErrorIsInaccesible (ctx, retval.GetSignatureForError (), loc);
                                return;
                        }
 
-                       NamespaceEntry.Error_NamespaceNotFound (loc, Name, ec.Module.Compiler.Report);
-               }
-
-               protected override Expression DoResolve (ResolveContext ec)
-               {
-                       return SimpleNameResolve (ec, null, false);
-               }
+                       retval = ctx.LookupNamespaceOrType (Name, -System.Math.Max (1, Arity), LookupMode.Probing, loc);
+                       if (retval != null) {
+                               Error_TypeArgumentsCannotBeUsed (ctx, retval.Type, Arity, loc);
+                               return;
+                       }
 
-               public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
-               {
-                       return SimpleNameResolve (ec, right_side, false);
+                       NamespaceContainer.Error_NamespaceNotFound (loc, Name, ctx.Module.Compiler.Report);
                }
 
-               public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent)
+               public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext ec)
                {
-                       int errors = ec.Module.Compiler.Report.Errors;
-                       FullNamedExpression fne = ec.LookupNamespaceOrType (Name, Arity, loc, /*ignore_cs0104=*/ false);
+                       FullNamedExpression fne = ec.LookupNamespaceOrType (Name, Arity, LookupMode.Normal, loc);
 
                        if (fne != null) {
                                if (fne.Type != null && Arity > 0) {
                                        if (HasTypeArguments) {
                                                GenericTypeExpr ct = new GenericTypeExpr (fne.Type, targs, loc);
-                                               return ct.ResolveAsTypeStep (ec, false);
+                                               if (ct.ResolveAsType (ec) == null)
+                                                       return null;
+
+                                               return ct;
                                        }
 
                                        return new GenericOpenTypeExpr (fne.Type, loc);
@@ -2188,19 +2310,22 @@ namespace Mono.CSharp {
                                                ec.Module.PredefinedAttributes.Dynamic.GetSignatureForError ());
                                }
 
-                               return new DynamicTypeExpr (loc).ResolveAsTypeStep (ec, silent);
+                               fne = new DynamicTypeExpr (loc);
+                               fne.ResolveAsType (ec);
                        }
 
                        if (fne != null)
                                return fne;
 
-                       if (silent || errors != ec.Module.Compiler.Report.Errors)
-                               return null;
-
                        Error_TypeOrNamespaceNotFound (ec);
                        return null;
                }
 
+               public bool IsPossibleTypeOrNamespace (IMemberContext mc)
+               {
+                       return mc.LookupNamespaceOrType (Name, Arity, LookupMode.Probing, loc) != null;
+               }
+
                public override Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restrictions)
                {
                        int lookup_arity = Arity;
@@ -2227,7 +2352,7 @@ namespace Mono.CSharp {
                                                        e = variable.CreateReferenceExpression (rc, loc);
                                                        if (e != null) {
                                                                if (Arity > 0)
-                                                                       Error_TypeArgumentsCannotBeUsed (rc.Report, "variable", Name, loc);
+                                                                       Error_TypeArgumentsCannotBeUsed (rc, "variable", Name, loc);
 
                                                                return e;
                                                        }
@@ -2312,14 +2437,13 @@ namespace Mono.CSharp {
                                // Stage 3: Lookup nested types, namespaces and type parameters in the context
                                //
                                if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0 && !variable_found) {
-                                       e = ResolveAsTypeStep (rc, lookup_arity == 0 || !errorMode);
-                                       if (e != null) {
+                                       if (IsPossibleTypeOrNamespace (rc)) {
                                                if (variable != null) {
                                                        rc.Report.SymbolRelatedToPreviousError (variable.Location, Name);
                                                        rc.Report.Error (135, loc, "`{0}' conflicts with a declaration in a child block", Name);
                                                }
 
-                                               return e;
+                                               return ResolveAsTypeOrNamespace (rc);
                                        }
                                }
 
@@ -2327,10 +2451,53 @@ namespace Mono.CSharp {
                                        if (variable_found) {
                                                rc.Report.Error (841, loc, "A local variable `{0}' cannot be used before it is declared", Name);
                                        } else {
+                                               if (Arity > 0) {
+                                                       TypeParameter[] tparams = rc.CurrentTypeParameters;
+                                                       if (tparams != null) {
+                                                               foreach (var ctp in tparams) {
+                                                                       if (ctp.Name == Name) {
+                                                                               Error_TypeArgumentsCannotBeUsed (rc, "type parameter", Name, loc);
+                                                                               return null;
+                                                                       }
+                                                               }
+                                                       }
+
+                                                       var ct = rc.CurrentType;
+                                                       do {
+                                                               if (ct.MemberDefinition.TypeParametersCount > 0) {
+                                                                       foreach (var ctp in ct.MemberDefinition.TypeParameters) {
+                                                                               if (ctp.Name == Name) {
+                                                                                       Error_TypeArgumentsCannotBeUsed (rc, "type parameter", Name, loc);
+                                                                                       return null;
+                                                                               }
+                                                                       }
+                                                               }
+
+                                                               ct = ct.DeclaringType;
+                                                       } while (ct != null);
+                                               }
+
+                                               if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0) {
+                                                       e = rc.LookupNamespaceOrType (Name, Arity, LookupMode.IgnoreAccessibility, loc);
+                                                       if (e != null) {
+                                                               rc.Report.SymbolRelatedToPreviousError (e.Type);
+                                                               ErrorIsInaccesible (rc, e.GetSignatureForError (), loc);
+                                                               return e;
+                                                       }
+                                               }
+
+                                               e = rc.LookupNamespaceOrType (Name, -System.Math.Max (1, Arity), LookupMode.Probing, loc);
+                                               if (e != null) {
+                                                       if (!(e is TypeExpr) || (restrictions & MemberLookupRestrictions.InvocableOnly) == 0 || !e.Type.IsDelegate) {
+                                                               Error_TypeArgumentsCannotBeUsed (rc, e.Type, Arity, loc);
+                                                               return e;
+                                                       }
+                                               }
+
                                                rc.Report.Error (103, loc, "The name `{0}' does not exist in the current context", Name);
                                        }
 
-                                       return null;
+                                       return ErrorExpression.Instance;
                                }
 
                                if (rc.Module.Evaluator != null) {
@@ -2340,7 +2507,6 @@ namespace Mono.CSharp {
                                }
 
                                lookup_arity = 0;
-                               restrictions &= ~MemberLookupRestrictions.InvocableOnly;
                                errorMode = true;
                        }
                }
@@ -2366,6 +2532,11 @@ namespace Mono.CSharp {
                        //if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
                        return e;
                }
+               
+               public override object Accept (StructuralVisitor visitor)
+               {
+                       return visitor.Visit (this);
+               }
        }
 
        /// <summary>
@@ -2380,16 +2551,60 @@ namespace Mono.CSharp {
                        // resolved to different type
                }
 
+               public override bool ContainsEmitWithAwait ()
+               {
+                       return false;
+               }
+
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
                        throw new NotSupportedException ("ET");
                }
 
-               public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent)
+               public abstract FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc);
+
+               //
+               // This is used to resolve the expression as a type, a null
+               // value will be returned if the expression is not a type
+               // reference
+               //
+               public override TypeSpec ResolveAsType (IMemberContext mc)
                {
-                       return this;
+                       FullNamedExpression fne = ResolveAsTypeOrNamespace (mc);
+
+                       if (fne == null)
+                               return null;
+
+                       TypeExpr te = fne as TypeExpr;
+                       if (te == null) {
+                               fne.Error_UnexpectedKind (mc.Module.Compiler.Report, null, "type", loc);
+                               return null;
+                       }
+
+                       te.loc = loc;
+
+                       type = te.Type;
+
+                       var dep = type.GetMissingDependencies ();
+                       if (dep != null) {
+                               ImportedTypeDefinition.Error_MissingDependency (mc, dep, loc);
+                       }
+
+                       //
+                       // Obsolete checks cannot be done when resolving base context as they
+                       // require type dependencies to be set but we are in process of resolving them
+                       //
+                       if (!(mc is TypeContainer.BaseContext)) {
+                               ObsoleteAttribute obsolete_attr = type.GetAttributeObsolete ();
+                               if (obsolete_attr != null && !mc.IsObsolete) {
+                                       AttributeTester.Report_ObsoleteMessage (obsolete_attr, te.GetSignatureForError (), Location, mc.Module.Compiler.Report);
+                               }
+                       }
+
+                       return type;
                }
 
+
                public override void Emit (EmitContext ec)
                {
                        throw new InternalErrorException ("FullNamedExpression `{0}' found in resolved tree",
@@ -2400,24 +2615,20 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Expression that evaluates to a type
        /// </summary>
-       public abstract class TypeExpr : FullNamedExpression {
-               public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent)
+       public abstract class TypeExpr : FullNamedExpression
+       {
+               public sealed override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc)
                {
-                       TypeExpr t = DoResolveAsTypeStep (ec);
-                       if (t == null)
-                               return null;
-
-                       eclass = ExprClass.Type;
-                       return t;
+                       ResolveAsType (mc);
+                       return this;
                }
 
-               protected override Expression DoResolve (ResolveContext ec)
+               protected sealed override Expression DoResolve (ResolveContext ec)
                {
-                       return ResolveAsTypeTerminal (ec, false);
+                       ResolveAsType (ec);
+                       return this;
                }
 
-               protected abstract TypeExpr DoResolveAsTypeStep (IMemberContext ec);
-
                public override bool Equals (object obj)
                {
                        TypeExpr tobj = obj as TypeExpr;
@@ -2436,7 +2647,8 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Fully resolved Expression that already evaluated to a type
        /// </summary>
-       public class TypeExpression : TypeExpr {
+       public class TypeExpression : TypeExpr
+       {
                public TypeExpression (TypeSpec t, Location l)
                {
                        Type = t;
@@ -2444,14 +2656,9 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               protected override TypeExpr DoResolveAsTypeStep (IMemberContext ec)
-               {
-                       return this;
-               }
-
-               public override TypeExpr ResolveAsTypeTerminal (IMemberContext ec, bool silent)
+               public sealed override TypeSpec ResolveAsType (IMemberContext ec)
                {
-                       return this;
+                       return type;
                }
        }
 
@@ -2459,7 +2666,7 @@ namespace Mono.CSharp {
        ///   This class denotes an expression which evaluates to a member
        ///   of a struct or a class.
        /// </summary>
-       public abstract class MemberExpr : Expression
+       public abstract class MemberExpr : Expression, OverloadResolver.IInstanceQualifier
        {
                //
                // An instance expression associated with this member, if it's a
@@ -2495,11 +2702,16 @@ namespace Mono.CSharp {
                        get;
                }
 
-               // TODO: Not needed
                protected abstract TypeSpec DeclaringType {
                        get;
                }
 
+               TypeSpec OverloadResolver.IInstanceQualifier.InstanceType {
+                       get {
+                               return InstanceExpression.Type;
+                       }
+               }
+
                //
                // Converts best base candidate for virtual method starting from QueriedBaseType
                //
@@ -2515,7 +2727,7 @@ namespace Mono.CSharp {
                        // Overload resulution works on virtual or non-virtual members only (no overrides). That
                        // means for base.member access we have to find the closest match after we found best candidate
                        //
-                       if ((method.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.STATIC)) != Modifiers.STATIC) {
+                       if ((method.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
                                //
                                // The method could already be what we are looking for
                                //
@@ -2564,28 +2776,46 @@ namespace Mono.CSharp {
                        return method;
                }
 
-               protected void CheckProtectedMemberAccess<T> (ResolveContext rc, T member) where T : MemberSpec
+               protected void CheckProtectedMemberAccess (ResolveContext rc, MemberSpec member)
                {
                        if (InstanceExpression == null)
                                return;
 
                        if ((member.Modifiers & Modifiers.PROTECTED) != 0 && !(InstanceExpression is This)) {
-                               var ct = rc.CurrentType;
-                               var expr_type = InstanceExpression.Type;
-                               if (ct == expr_type)
-                                       return;
+                               if (!CheckProtectedMemberAccess (rc, member, InstanceExpression.Type)) {
+                                       Error_ProtectedMemberAccess (rc, member, InstanceExpression.Type, loc);
+                               }
+                       }
+               }
 
-                               if ((member.Modifiers & Modifiers.INTERNAL) != 0 && member.DeclaringType.MemberDefinition.IsInternalAsPublic (ct.MemberDefinition.DeclaringAssembly))
-                                       return;
+               bool OverloadResolver.IInstanceQualifier.CheckProtectedMemberAccess (ResolveContext rc, MemberSpec member)
+               {
+                       if (InstanceExpression == null)
+                               return true;
 
-                               expr_type = expr_type.GetDefinition ();
-                               if (ct != expr_type && !IsSameOrBaseQualifier (ct, expr_type)) {
-                                       rc.Report.SymbolRelatedToPreviousError (member);
-                                       rc.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",
-                                               member.GetSignatureForError (), expr_type.GetSignatureForError (), ct.GetSignatureForError ());
-                               }
+                       return InstanceExpression is This || CheckProtectedMemberAccess (rc, member, InstanceExpression.Type);
+               }
+
+               public static bool CheckProtectedMemberAccess<T> (ResolveContext rc, T member, TypeSpec qualifier) where T : MemberSpec
+               {
+                       var ct = rc.CurrentType;
+                       if (ct == qualifier)
+                               return true;
+
+                       if ((member.Modifiers & Modifiers.INTERNAL) != 0 && member.DeclaringType.MemberDefinition.IsInternalAsPublic (ct.MemberDefinition.DeclaringAssembly))
+                               return true;
+
+                       qualifier = qualifier.GetDefinition ();
+                       if (ct != qualifier && !IsSameOrBaseQualifier (ct, qualifier)) {
+                               return false;
                        }
+
+                       return true;
+               }
+
+               public override bool ContainsEmitWithAwait ()
+               {
+                       return InstanceExpression != null && InstanceExpression.ContainsEmitWithAwait ();
                }
 
                static bool IsSameOrBaseQualifier (TypeSpec type, TypeSpec qtype)
@@ -2633,6 +2863,14 @@ namespace Mono.CSharp {
                        rc.Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
                }
 
+               public static void Error_ProtectedMemberAccess (ResolveContext rc, MemberSpec member, TypeSpec qualifier, Location loc)
+               {
+                       rc.Report.SymbolRelatedToPreviousError (member);
+                       rc.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",
+                               member.GetSignatureForError (), qualifier.GetSignatureForError (), rc.CurrentType.GetSignatureForError ());
+               }
+
                //
                // Implements identicial simple name and type-name
                //
@@ -2646,9 +2884,7 @@ namespace Mono.CSharp {
                        // a constant, field, property, local variable, or parameter with the same type as the meaning of E as a type-name
 
                        if (left is MemberExpr || left is VariableReference) {
-                               rc.Report.DisableReporting ();
-                               Expression identical_type = rc.LookupNamespaceOrType (name.Name, 0, loc, true) as TypeExpr;
-                               rc.Report.EnableReporting ();
+                               var identical_type = rc.LookupNamespaceOrType (name.Name, 0, LookupMode.Probing, loc) as TypeExpr;
                                if (identical_type != null && identical_type.Type == left.Type)
                                        return identical_type;
                        }
@@ -2696,6 +2932,7 @@ namespace Mono.CSharp {
                                                        "An object reference is required to access non-static member `{0}'",
                                                        GetSignatureForError ());
 
+                                       InstanceExpression = new CompilerGeneratedThis (type, loc).Resolve (rc);
                                        return false;
                                }
 
@@ -2706,7 +2943,7 @@ namespace Mono.CSharp {
                                }
 
                                InstanceExpression = new This (loc);
-                               if (this is FieldExpr && rc.CurrentType.IsStruct) {
+                               if (this is FieldExpr && rc.CurrentBlock.ParametersBlock.TopBlock.ThisVariable != null) {
                                        using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) {
                                                InstanceExpression = InstanceExpression.Resolve (rc);
                                        }
@@ -2737,7 +2974,7 @@ namespace Mono.CSharp {
                        // the expression is not field expression which is the only
                        // expression which can use uninitialized this
                        //
-                       if (InstanceExpression is This && !(this is FieldExpr) && rc.CurrentType.IsStruct) {
+                       if (InstanceExpression is This && !(this is FieldExpr) && rc.CurrentBlock.ParametersBlock.TopBlock.ThisVariable != null) {
                                ((This)InstanceExpression).CheckStructThisDefiniteAssignment (rc);
                        }
 
@@ -2745,9 +2982,6 @@ namespace Mono.CSharp {
                        // Additional checks for l-value member access
                        //
                        if (rhs != null) {
-                               //
-                               // TODO: It should be recursive but that would break csc compatibility
-                               //
                                if (InstanceExpression is UnboxCast) {
                                        rc.Report.Error (445, InstanceExpression.Location, "Cannot modify the result of an unboxing conversion");
                                }
@@ -2758,7 +2992,7 @@ namespace Mono.CSharp {
 
                public virtual MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original)
                {
-                       if (left != null && left.IsNull && TypeManager.IsReferenceType (left.Type)) {
+                       if (left != null && left.IsNull && TypeSpec.IsReferenceType (left.Type)) {
                                ec.Report.Warning (1720, 1, left.Location,
                                        "Expression will always cause a `{0}'", "System.NullReferenceException");
                        }
@@ -2770,10 +3004,12 @@ namespace Mono.CSharp {
                protected void EmitInstance (EmitContext ec, bool prepare_for_load)
                {
                        TypeSpec instance_type = InstanceExpression.Type;
-                       if (TypeManager.IsValueType (instance_type)) {
+                       if (TypeSpec.IsValueType (instance_type)) {
                                if (InstanceExpression is IMemoryLocation) {
-                                       ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
+                                       ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.Load);
                                } else {
+                                       // Cannot release the temporary variable when its address
+                                       // is required to be on stack for any parent
                                        LocalTemporary t = new LocalTemporary (instance_type);
                                        InstanceExpression.Emit (ec);
                                        t.Store (ec);
@@ -2783,7 +3019,7 @@ namespace Mono.CSharp {
                                InstanceExpression.Emit (ec);
 
                                // Only to make verifier happy
-                               if (instance_type.IsGenericParameter && !(InstanceExpression is This) && TypeManager.IsReferenceType (instance_type))
+                               if (instance_type.IsGenericParameter && !(InstanceExpression is This) && TypeSpec.IsReferenceType (instance_type))
                                        ec.Emit (OpCodes.Box, instance_type);
                        }
 
@@ -2794,18 +3030,57 @@ namespace Mono.CSharp {
                public abstract void SetTypeArguments (ResolveContext ec, TypeArguments ta);
        }
 
+       public class ExtensionMethodCandidates
+       {
+               NamespaceContainer container;
+               Namespace ns;
+               IList<MethodSpec> methods;
+
+               public ExtensionMethodCandidates (IList<MethodSpec> methods, NamespaceContainer nsContainer)
+                       : this (methods, nsContainer, null)
+               {
+               }
+
+               public ExtensionMethodCandidates (IList<MethodSpec> methods, NamespaceContainer nsContainer, Namespace ns)
+               {
+                       this.methods = methods;
+                       this.container = nsContainer;
+                       this.ns = ns;
+               }
+
+               public NamespaceContainer Container {
+                       get {
+                               return container;
+                       }
+               }
+
+               public bool HasUninspectedMembers { get; set; }
+
+               public Namespace Namespace {
+                       get {
+                               return ns;
+                       }
+               }
+
+               public IList<MethodSpec> Methods {
+                       get {
+                               return methods;
+                       }
+               }
+       }
+
        // 
        // Represents a group of extension method candidates for whole namespace
        // 
        class ExtensionMethodGroupExpr : MethodGroupExpr, OverloadResolver.IErrorHandler
        {
-               NamespaceEntry namespace_entry;
+               ExtensionMethodCandidates candidates;
                public readonly Expression ExtensionExpression;
 
-               public ExtensionMethodGroupExpr (IList<MethodSpec> list, NamespaceEntry n, Expression extensionExpr, Location l)
-                       : base (list.Cast<MemberSpec>().ToList (), extensionExpr.Type, l)
+               public ExtensionMethodGroupExpr (ExtensionMethodCandidates candidates, Expression extensionExpr, Location loc)
+                       : base (candidates.Methods.Cast<MemberSpec>().ToList (), extensionExpr.Type, loc)
                {
-                       this.namespace_entry = n;
+                       this.candidates = candidates;
                        this.ExtensionExpression = extensionExpr;
                }
 
@@ -2813,21 +3088,55 @@ namespace Mono.CSharp {
                        get { return true; }
                }
 
+               //
+               // For extension methodgroup we are not looking for base members but parent
+               // namespace extension methods
+               //
                public override IList<MemberSpec> GetBaseMembers (TypeSpec baseType)
                {
-                       if (namespace_entry == null)
+                       // TODO: candidates are null only when doing error reporting, that's
+                       // incorrect. We have to discover same extension methods in error mode
+                       if (candidates == null)
                                return null;
 
+                       int arity = type_arguments == null ? 0 : type_arguments.Count;
+
                        //
-                       // For extension methodgroup we are not looking for base members but parent
-                       // namespace extension methods
+                       // Here we try to resume the search for extension method at the point
+                       // where the last bunch of candidates was found. It's more tricky than
+                       // it seems as we have to check both namespace containers and namespace
+                       // in correct order.
                        //
-                       int arity = type_arguments == null ? 0 : type_arguments.Count;
-                       var found = namespace_entry.LookupExtensionMethod (DeclaringType, Name, arity, ref namespace_entry);
-                       if (found == null)
+                       // Consider:
+                       // 
+                       // namespace A {
+                       //      using N1;
+                       //  namespace B.C.D {
+                       //              <our first search found candidates in A.B.C.D
+                       //  }
+                       // }
+                       //
+                       // In the example above namespace A.B.C.D, A.B.C and A.B have to be
+                       // checked before we hit A.N1 using
+                       //
+                       if (candidates.Namespace == null) {
+                               Namespace scope;
+                               var methods = candidates.Container.NS.LookupExtensionMethod (candidates.Container, ExtensionExpression.Type, Name, arity, out scope);
+                               if (methods != null) {
+                                       candidates = new ExtensionMethodCandidates (null, candidates.Container, scope);
+                                       return methods.Cast<MemberSpec> ().ToList ();
+                               }
+                       }
+
+                       var ns_container = candidates.HasUninspectedMembers ? candidates.Container : candidates.Container.Parent;
+                       if (ns_container == null)
+                               return null;
+
+                       candidates = ns_container.LookupExtensionMethod (ExtensionExpression.Type, Name, arity);
+                       if (candidates == null)
                                return null;
 
-                       return found.Cast<MemberSpec> ().ToList ();
+                       return candidates.Methods.Cast<MemberSpec> ().ToList ();
                }
 
                public override MethodGroupExpr LookupExtensionMethod (ResolveContext rc)
@@ -2938,6 +3247,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               public IList<MemberSpec> Candidates {
+                       get {
+                               return Methods;
+                       }
+               }
+
                protected override TypeSpec DeclaringType {
                        get {
                                return queried_type;
@@ -3030,7 +3345,9 @@ namespace Mono.CSharp {
                
                public void EmitCall (EmitContext ec, Arguments arguments)
                {
-                       Invocation.EmitCall (ec, InstanceExpression, best_candidate, arguments, loc);                   
+                       var call = new CallEmitter ();
+                       call.InstanceExpression = InstanceExpression;
+                       call.Emit (ec, best_candidate, arguments, loc);                 
                }
 
                public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
@@ -3072,6 +3389,7 @@ namespace Mono.CSharp {
                        var r = new OverloadResolver (Methods, type_arguments, restr, loc);
                        if ((restr & OverloadResolver.Restrictions.NoBaseMembers) == 0) {
                                r.BaseMembersProvider = this;
+                               r.InstanceQualifier = this;
                        }
 
                        if (cerrors != null)
@@ -3100,8 +3418,6 @@ namespace Mono.CSharp {
                                }
 
                                ResolveInstanceExpression (ec, null);
-                               if (InstanceExpression != null)
-                                       CheckProtectedMemberAccess (ec, best_candidate);
                        }
 
                        var base_override = CandidateToBaseOverride (ec, best_candidate);
@@ -3155,12 +3471,11 @@ namespace Mono.CSharp {
                                return null;
 
                        int arity = type_arguments == null ? 0 : type_arguments.Count;
-                       NamespaceEntry methods_scope = null;
-                       var methods = rc.LookupExtensionMethod (InstanceExpression.Type, Methods[0].Name, arity, ref methods_scope);
+                       var methods = rc.LookupExtensionMethod (InstanceExpression.Type, Methods[0].Name, arity);
                        if (methods == null)
                                return null;
 
-                       var emg = new ExtensionMethodGroupExpr (methods, methods_scope, InstanceExpression, loc);
+                       var emg = new ExtensionMethodGroupExpr (methods, InstanceExpression, loc);
                        emg.SetTypeArguments (rc, type_arguments);
                        return emg;
                }
@@ -3168,6 +3483,22 @@ namespace Mono.CSharp {
                #endregion
        }
 
+       struct ConstructorInstanceQualifier : OverloadResolver.IInstanceQualifier
+       {
+               public ConstructorInstanceQualifier (TypeSpec type)
+                       : this ()
+               {
+                       InstanceType = type;
+               }
+
+               public TypeSpec InstanceType { get; private set; }
+
+               public bool CheckProtectedMemberAccess (ResolveContext rc, MemberSpec member)
+               {
+                       return MemberExpr.CheckProtectedMemberAccess (rc, member, InstanceType);
+               }
+       }
+
        public struct OverloadResolver
        {
                [Flags]
@@ -3196,6 +3527,12 @@ namespace Mono.CSharp {
                        bool TypeInferenceFailed (ResolveContext rc, MemberSpec best);
                }
 
+               public interface IInstanceQualifier
+               {
+                       TypeSpec InstanceType { get; }
+                       bool CheckProtectedMemberAccess (ResolveContext rc, MemberSpec member);
+               }
+
                sealed class NoBaseMembers : IBaseMembersProvider
                {
                        public static readonly IBaseMembersProvider Instance = new NoBaseMembers ();
@@ -3235,6 +3572,7 @@ namespace Mono.CSharp {
                TypeArguments type_arguments;
                IBaseMembersProvider base_provider;
                IErrorHandler custom_errors;
+               IInstanceQualifier instance_qualifier;
                Restrictions restrictions;
                MethodGroupExpr best_candidate_extension_group;
                TypeSpec best_candidate_return_type;
@@ -3312,6 +3650,15 @@ namespace Mono.CSharp {
                        }
                }
 
+               public IInstanceQualifier InstanceQualifier {
+                       get {
+                               return instance_qualifier;
+                       }
+                       set {
+                               instance_qualifier = value;
+                       }
+               }
+
                bool IsProbingOnly {
                        get {
                                return (restrictions & Restrictions.ProbingOnly) != 0;
@@ -3361,7 +3708,7 @@ namespace Mono.CSharp {
                                //
                                // With identical parameter lists
                                //
-                               if (!TypeSpecComparer.Equals (p_m.Parameters.Types,q_m.Parameters.Types))
+                               if (!TypeSpecComparer.Equals (p_m.Parameters.Types, q_m.Parameters.Types))
                                        return 0;
 
                                p = p_m.ReturnType;
@@ -3380,6 +3727,28 @@ namespace Mono.CSharp {
                                if (q.Kind == MemberKind.Void) {
                                        return p.Kind != MemberKind.Void ? 1: 0;
                                }
+
+                               //
+                               // When anonymous method is an asynchronous, and P has a return type Task<Y1>, and Q has a return type Task<Y2>
+                               // better conversion is performed between underlying types Y1 and Y2
+                               //
+                               if (p.IsGenericTask || q.IsGenericTask) {
+                                       var async_am = a.Expr as AnonymousMethodExpression;
+                                       if (async_am != null && async_am.Block.IsAsync) {
+
+                                               if (p.IsGenericTask != q.IsGenericTask) {
+                                                       return 0;
+                                               }
+
+                                               q = q.TypeArguments[0];
+                                               p = p.TypeArguments[0];
+                                       }
+                               }
+
+                               //
+                               // The parameters are identicial and return type is not void, use better type conversion
+                               // on return type to determine better one
+                               //
                        } else {
                                if (argument_type == p)
                                        return 1;
@@ -3871,7 +4240,7 @@ namespace Mono.CSharp {
                                        // if the type matches
                                        //
                                        Expression e = pd.FixedParameters[i].DefaultValue;
-                                       if (!(e is Constant) || e.Type.IsGenericOrParentIsGeneric) {
+                                       if (!(e is Constant) || e.Type.IsGenericOrParentIsGeneric || e.Type.IsGenericParameter) {
                                                //
                                                // LAMESPEC: No idea what the exact rules are for System.Reflection.Missing.Value instead of null
                                                //
@@ -3905,9 +4274,11 @@ namespace Mono.CSharp {
                                                //
                                                // Indentity, implicit reference or boxing conversion must exist for the extension parameter
                                                //
+                                               // LAMESPEC: or implicit type parameter conversion
+                                               //
                                                var at = a.Type;
                                                if (at == pt || TypeSpecComparer.IsEqual (at, pt) ||
-                                                       Convert.ImplicitReferenceConversionExists (at, pt) ||
+                                                       Convert.ImplicitReferenceConversionExists (at, pt, false) ||
                                                        Convert.ImplicitBoxingConversion (null, at, pt) != null) {
                                                        score = 0;
                                                        continue;
@@ -4007,7 +4378,7 @@ namespace Mono.CSharp {
                                //
                                // Deploy custom error reporting for lambda methods. When probing lambda methods
                                // keep all errors reported in separate set and once we are done and no best
-                               // candidate found, this set is used to report more details about what was wrong
+                               // candidate was found, this set is used to report more details about what was wrong
                                // with lambda body
                                //
                                if (argument.Expr.Type == InternalType.AnonymousMethod) {
@@ -4017,6 +4388,10 @@ namespace Mono.CSharp {
                                        }
                                }
 
+                               //
+                               // Use implicit conversion in all modes to return same candidates when the expression
+                               // is used as argument or delegate conversion
+                               //
                                if (!Convert.ImplicitConversionExists (ec, argument.Expr, parameter)) {
                                        if (lambda_conv_msgs != null) {
                                                lambda_conv_msgs.EndSession ();
@@ -4038,7 +4413,10 @@ namespace Mono.CSharp {
 
                        var ac_p = p as ArrayContainer;
                        if (ac_p != null) {
-                               var ac_q = ((ArrayContainer) q);
+                               var ac_q = q as ArrayContainer;
+                               if (ac_q == null)
+                                       return null;
+
                                TypeSpec specific = MoreSpecific (ac_p.Element, ac_q.Element);
                                if (specific == ac_p.Element)
                                        return p;
@@ -4113,6 +4491,11 @@ namespace Mono.CSharp {
 
                                                                if (rc.IsRuntimeBinder && !member.DeclaringType.IsAccessible (rc))
                                                                        continue;
+
+                                                               if ((member.Modifiers & (Modifiers.PROTECTED | Modifiers.STATIC)) == Modifiers.PROTECTED &&
+                                                                       instance_qualifier != null && !instance_qualifier.CheckProtectedMemberAccess (rc, member)) {
+                                                                       continue;
+                                                               }
                                                        }
 
                                                        IParametersMember pm = member as IParametersMember;
@@ -4252,6 +4635,9 @@ namespace Mono.CSharp {
                                if (error_mode)
                                        break;
 
+                               if (lambda_conv_msgs != null && !lambda_conv_msgs.IsEmpty)
+                                       break;
+
                                lambda_conv_msgs = null;
                                error_mode = true;
                        }
@@ -4275,6 +4661,13 @@ namespace Mono.CSharp {
                                return null;
                        }
 
+                       //
+                       // These flags indicates we are running delegate probing conversion. No need to
+                       // do more expensive checks
+                       // 
+                       if ((restrictions & (Restrictions.ProbingOnly | Restrictions.CovariantDelegate)) == (Restrictions.CovariantDelegate | Restrictions.ProbingOnly))
+                               return (T) best_candidate;
+
                        if (ambiguous_candidates != null) {
                                //
                                // Now check that there are no ambiguities i.e the selected method
@@ -4374,14 +4767,13 @@ namespace Mono.CSharp {
                                else
                                        ec.Report.Error (1620, loc, "Argument `#{0}' is missing `{1}' modifier",
                                                index, Parameter.GetModifierSignature (mod));
-                       } else {
+                       } else if (a.Expr != ErrorExpression.Instance) {
                                string p1 = a.GetSignatureForError ();
                                string p2 = TypeManager.CSharpName (paramType);
 
                                if (p1 == p2) {
-                                       ec.Report.ExtraInformation (loc, "(equally named types possibly from different assemblies in previous ");
-                                       ec.Report.SymbolRelatedToPreviousError (a.Expr.Type);
-                                       ec.Report.SymbolRelatedToPreviousError (paramType);
+                                       p1 = a.Type.GetSignatureForErrorIncludingAssemblyName ();
+                                       p2 = paramType.GetSignatureForErrorIncludingAssemblyName ();
                                }
 
                                ec.Report.Error (1503, loc,
@@ -4399,7 +4791,7 @@ namespace Mono.CSharp {
 
                        if (ta_count != best_candidate.Arity && (ta_count > 0 || ((IParametersMember) best_candidate).Parameters.IsEmpty)) {
                                var mg = new MethodGroupExpr (new [] { best_candidate }, best_candidate.DeclaringType, loc);
-                               mg.Error_TypeArgumentsCannotBeUsed (rc.Report, loc, best_candidate, ta_count);
+                               mg.Error_TypeArgumentsCannotBeUsed (rc, best_candidate, ta_count, loc);
                                return;
                        }
 
@@ -4408,6 +4800,12 @@ namespace Mono.CSharp {
                                        return;
                        }
 
+
+                       if ((best_candidate.Modifiers & (Modifiers.PROTECTED | Modifiers.STATIC)) == Modifiers.PROTECTED &&
+                               InstanceQualifier != null && !InstanceQualifier.CheckProtectedMemberAccess (rc, best_candidate)) {
+                               MemberExpr.Error_ProtectedMemberAccess (rc, best_candidate, InstanceQualifier.InstanceType, loc);
+                       }
+
                        //
                        // For candidates which match on parameters count report more details about incorrect arguments
                        //
@@ -4626,7 +5024,7 @@ namespace Mono.CSharp {
 
        public class ConstantExpr : MemberExpr
        {
-               ConstSpec constant;
+               readonly ConstSpec constant;
 
                public ConstantExpr (ConstSpec constant, Location loc)
                {
@@ -4678,14 +5076,15 @@ namespace Mono.CSharp {
 
                public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
                {
-                       Error_TypeArgumentsCannotBeUsed (ec.Report, "constant", GetSignatureForError (), loc);
+                       Error_TypeArgumentsCannotBeUsed (ec, "constant", GetSignatureForError (), loc);
                }
        }
 
-       /// <summary>
-       ///   Fully resolved expression that evaluates to a Field
-       /// </summary>
-       public class FieldExpr : MemberExpr, IDynamicAssign, IMemoryLocation, IVariableReference {
+       //
+       // Fully resolved expression that references a Field
+       //
+       public class FieldExpr : MemberExpr, IDynamicAssign, IMemoryLocation, IVariableReference
+       {
                protected FieldSpec spec;
                VariableInfo variable_info;
                
@@ -4759,13 +5158,13 @@ namespace Mono.CSharp {
 
                public override string GetSignatureForError ()
                {
-                       return TypeManager.GetFullNameSignature (spec);
+                       return spec.GetSignatureForError ();
                }
 
                public bool IsMarshalByRefAccess (ResolveContext rc)
                {
                        // Checks possible ldflda of field access expression
-                       return !spec.IsStatic && TypeManager.IsValueType (spec.MemberType) && !(InstanceExpression is This) &&
+                       return !spec.IsStatic && TypeSpec.IsValueType (spec.MemberType) && !(InstanceExpression is This) &&
                                rc.Module.PredefinedTypes.MarshalByRefObject.Define () &&
                                TypeSpec.IsBaseClass (spec.DeclaringType, rc.Module.PredefinedTypes.MarshalByRefObject.TypeSpec, false);
                }
@@ -4773,8 +5172,9 @@ namespace Mono.CSharp {
                public void SetHasAddressTaken ()
                {
                        IVariableReference vr = InstanceExpression as IVariableReference;
-                       if (vr != null)
+                       if (vr != null) {
                                vr.SetHasAddressTaken ();
+                       }
                }
 
                public override Expression CreateExpressionTree (ResolveContext ec)
@@ -4807,37 +5207,39 @@ namespace Mono.CSharp {
                {
                        bool lvalue_instance = rhs != null && IsInstance && spec.DeclaringType.IsStruct;
 
-                       if (ResolveInstanceExpression (ec, rhs)) {
-                               // 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.
+                       if (rhs != this) {
+                               if (ResolveInstanceExpression (ec, rhs)) {
+                                       // 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.
 
-                               if (lvalue_instance) {
-                                       using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
-                                               bool out_access = rhs == EmptyExpression.OutAccess || rhs == EmptyExpression.LValueMemberOutAccess;
+                                       if (lvalue_instance) {
+                                               using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
+                                                       bool out_access = rhs == EmptyExpression.OutAccess || rhs == EmptyExpression.LValueMemberOutAccess;
 
-                                               Expression right_side =
-                                                       out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
+                                                       Expression right_side =
+                                                               out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
 
-                                               InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
-                                       }
-                               } else {
-                                       using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
-                                               InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue);
+                                                       InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
+                                               }
+                                       } else {
+                                               using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
+                                                       InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue);
+                                               }
                                        }
+
+                                       if (InstanceExpression == null)
+                                               return null;
                                }
 
-                               if (InstanceExpression == null)
-                                       return null;
+                               DoBestMemberChecks (ec, spec);
                        }
 
-                       DoBestMemberChecks (ec, spec);
-
                        var fb = spec as FixedFieldSpec;
                        IVariableReference var = InstanceExpression as IVariableReference;
 
                        if (lvalue_instance && var != null && var.VariableInfo != null) {
-                               var.VariableInfo.SetFieldAssigned (ec, Name);
+                               var.VariableInfo.SetStructFieldAssigned (ec, Name);
                        }
                        
                        if (fb != null) {
@@ -4853,22 +5255,47 @@ namespace Mono.CSharp {
                                } else if (var != null && var.IsHoisted) {
                                        AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, var, loc);
                                }
-                               
+
                                return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec);
                        }
 
+                       //
+                       // Set flow-analysis variable info for struct member access. It will be check later
+                       // for precise error reporting
+                       //
+                       if (var != null && var.VariableInfo != null && InstanceExpression.Type.IsStruct) {
+                               variable_info = var.VariableInfo.GetStructFieldInfo (Name);
+                               if (rhs != null && variable_info != null)
+                                       variable_info.SetStructFieldAssigned (ec, Name);
+                       }
+
                        eclass = ExprClass.Variable;
+                       return this;
+               }
 
-                       // If the instance expression is a local variable or parameter.
-                       if (var == null || var.VariableInfo == null)
-                               return this;
+               public void VerifyAssignedStructField (ResolveContext rc, Expression rhs)
+               {
+                       var fe = this;
 
-                       VariableInfo vi = var.VariableInfo;
-                       if (!vi.IsFieldAssigned (ec, Name, loc))
-                               return null;
+                       do {
+                               var var = fe.InstanceExpression as IVariableReference;
+                               if (var != null) {
+                                       var vi = var.VariableInfo;
 
-                       variable_info = vi.GetSubStruct (Name);
-                       return this;
+                                       if (vi != null && !vi.IsStructFieldAssigned (rc, fe.Name) && (rhs == null || !fe.type.IsStruct)) {
+                                               if (rhs != null) {
+                                                       rc.Report.Warning (1060, 1, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
+                                               } else {
+                                                       rc.Report.Error (170, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
+                                               }
+
+                                               return;
+                                       }
+                               }
+
+                               fe = fe.InstanceExpression as FieldExpr;
+
+                       } while (fe != null);
                }
 
                static readonly int [] codes = {
@@ -4990,10 +5417,7 @@ namespace Mono.CSharp {
                
                public void Emit (EmitContext ec, bool leave_copy)
                {
-                       bool is_volatile = false;
-
-                       if ((spec.Modifiers & Modifiers.VOLATILE) != 0)
-                               is_volatile = true;
+                       bool is_volatile = (spec.Modifiers & Modifiers.VOLATILE) != 0;
 
                        spec.MemberDefinition.SetIsUsed ();
                        
@@ -5032,13 +5456,27 @@ namespace Mono.CSharp {
                        }
                }
 
-               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
+               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
                {
-                       prepared = prepare_for_load && !(source is DynamicExpressionStatement);
-                       if (IsInstance)
+                       bool has_await_source = ec.HasSet (BuilderContext.Options.AsyncBody) && source.ContainsEmitWithAwait ();
+                       if (isCompound && !(source is DynamicExpressionStatement)) {
+                               if (has_await_source) {
+                                       if (IsInstance)
+                                               InstanceExpression = InstanceExpression.EmitToField (ec);
+                               } else {
+                                       prepared = true;
+                               }
+                       }
+
+                       if (IsInstance) {
+                               if (has_await_source)
+                                       source = source.EmitToField (ec);
+
                                EmitInstance (ec, prepared);
+                       }
 
                        source.Emit (ec);
+
                        if (leave_copy) {
                                ec.Emit (OpCodes.Dup);
                                if (!IsStatic) {
@@ -5064,6 +5502,18 @@ namespace Mono.CSharp {
                        }
                }
 
+               //
+               // Emits store to field with prepared values on stack
+               //
+               public void EmitAssignFromStack (EmitContext ec)
+               {
+                       if (IsStatic) {
+                               ec.Emit (OpCodes.Stsfld, spec);
+                       } else {
+                               ec.Emit (OpCodes.Stfld, spec);
+                       }
+               }
+
                public override void Emit (EmitContext ec)
                {
                        Emit (ec, false);
@@ -5101,12 +5551,12 @@ namespace Mono.CSharp {
                        } else
                                need_copy = false;
                        
-                       if (need_copy){
-                               LocalBuilder local;
+                       if (need_copy) {
                                Emit (ec);
-                               local = ec.DeclareLocal (type, false);
-                               ec.Emit (OpCodes.Stloc, local);
-                               ec.Emit (OpCodes.Ldloca, local);
+                               var temp = ec.GetTemporaryLocal (type);
+                               ec.Emit (OpCodes.Stloc, temp);
+                               ec.Emit (OpCodes.Ldloca, temp);
+                               ec.FreeTemporaryLocal (temp, type);
                                return;
                        }
 
@@ -5138,19 +5588,18 @@ namespace Mono.CSharp {
 
                public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
                {
-                       Error_TypeArgumentsCannotBeUsed (ec.Report, "field", GetSignatureForError (), loc);
+                       Error_TypeArgumentsCannotBeUsed (ec, "field", GetSignatureForError (), loc);
                }
        }
 
        
-       /// <summary>
-       ///   Expression that evaluates to a Property.  The Assign class
-       ///   might set the `Value' expression if we are in an assignment.
-       ///
-       ///   This is not an LValue because we need to re-write the expression, we
-       ///   can not take data from the stack and store it.  
-       /// </summary>
-       class PropertyExpr : PropertyOrIndexerExpr<PropertySpec>
+       //
+       // Expression that evaluates to a Property.
+       //
+       // This is not an LValue because we need to re-write the expression. We
+       // can not take data from the stack and store it.
+       //
+       sealed class PropertyExpr : PropertyOrIndexerExpr<PropertySpec>
        {
                public PropertyExpr (PropertySpec spec, Location l)
                        : base (l)
@@ -5161,6 +5610,14 @@ namespace Mono.CSharp {
 
                #region Properties
 
+               protected override Arguments Arguments {
+                       get {
+                               return null;
+                       }
+                       set {
+                       }
+               }
+
                protected override TypeSpec DeclaringType {
                        get {
                                return best_candidate.DeclaringType;
@@ -5193,6 +5650,14 @@ namespace Mono.CSharp {
 
                #endregion
 
+               public static PropertyExpr CreatePredefined (PropertySpec spec, Location loc)
+               {
+                       return new PropertyExpr (spec, loc) {
+                               Getter = spec.Get,
+                               Setter = spec.Set
+                       };
+               }
+
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
                        Arguments args;
@@ -5211,8 +5676,9 @@ namespace Mono.CSharp {
                        return CreateExpressionFactoryCall (ec, "Property", args);
                }
 
-               public Expression CreateSetterTypeOfExpression ()
+               public Expression CreateSetterTypeOfExpression (ResolveContext rc)
                {
+                       DoResolveLValue (rc, null);
                        return new TypeOfMethod (Setter, loc);
                }
 
@@ -5261,36 +5727,41 @@ namespace Mono.CSharp {
                        // Special case: length of single dimension array property is turned into ldlen
                        //
                        if (IsSingleDimensionalArrayLength ()) {
-                               if (!prepared)
-                                       EmitInstance (ec, false);
+                               EmitInstance (ec, false);
                                ec.Emit (OpCodes.Ldlen);
                                ec.Emit (OpCodes.Conv_I4);
                                return;
                        }
 
-                       Invocation.EmitCall (ec, InstanceExpression, Getter, null, loc, prepared, false);
-                       
-                       if (leave_copy) {
-                               ec.Emit (OpCodes.Dup);
-                               if (!IsStatic) {
-                                       temp = new LocalTemporary (this.Type);
-                                       temp.Store (ec);
-                               }
-                       }
+                       base.Emit (ec, leave_copy);
                }
 
-               public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
+               public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
                {
                        Arguments args;
+                       LocalTemporary await_source_arg = null;
 
-                       if (prepare_for_load && !(source is DynamicExpressionStatement)) {
-                               args = new Arguments (0);
-                               prepared = true;
+                       if (isCompound && !(source is DynamicExpressionStatement)) {
+                               emitting_compound_assignment = true;
                                source.Emit (ec);
-                               
-                               if (leave_copy) {
-                                       ec.Emit (OpCodes.Dup);
-                                       if (!IsStatic) {
+
+                               if (has_await_arguments) {
+                                       await_source_arg = new LocalTemporary (Type);
+                                       await_source_arg.Store (ec);
+
+                                       args = new Arguments (1);
+                                       args.Add (new Argument (await_source_arg));
+
+                                       if (leave_copy) {
+                                               temp = await_source_arg;
+                                       }
+
+                                       has_await_arguments = false;
+                               } else {
+                                       args = null;
+
+                                       if (leave_copy) {
+                                               ec.Emit (OpCodes.Dup);
                                                temp = new LocalTemporary (this.Type);
                                                temp.Store (ec);
                                        }
@@ -5308,19 +5779,30 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       Invocation.EmitCall (ec, InstanceExpression, Setter, args, loc, false, prepared);
-                       
+                       emitting_compound_assignment = false;
+
+                       var call = new CallEmitter ();
+                       call.InstanceExpression = InstanceExpression;
+                       if (args == null)
+                               call.InstanceExpressionOnStack = true;
+
+                       call.Emit (ec, Setter, args, loc);
+
                        if (temp != null) {
                                temp.Emit (ec);
                                temp.Release (ec);
                        }
+
+                       if (await_source_arg != null) {
+                               await_source_arg.Release (ec);
+                       }
                }
 
                protected override Expression OverloadResolve (ResolveContext rc, Expression right_side)
                {
                        eclass = ExprClass.PropertyAccess;
 
-                       if (best_candidate.IsNotRealProperty) {
+                       if (best_candidate.IsNotCSharpCompatible) {
                                Error_PropertyNotValid (rc);
                        }
 
@@ -5340,7 +5822,7 @@ namespace Mono.CSharp {
 
                public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
                {
-                       Error_TypeArgumentsCannotBeUsed (ec.Report, "property", GetSignatureForError (), loc);
+                       Error_TypeArgumentsCannotBeUsed (ec, "property", GetSignatureForError (), loc);
                }
        }
 
@@ -5351,7 +5833,8 @@ namespace Mono.CSharp {
                protected T best_candidate;
 
                protected LocalTemporary temp;
-               protected bool prepared;
+               protected bool emitting_compound_assignment;
+               protected bool has_await_arguments;
 
                protected PropertyOrIndexerExpr (Location l)
                {
@@ -5360,6 +5843,8 @@ namespace Mono.CSharp {
 
                #region Properties
 
+               protected abstract Arguments Arguments { get; set; }
+
                public MethodSpec Getter {
                        get {
                                return getter;
@@ -5413,7 +5898,7 @@ namespace Mono.CSharp {
 
                        // if the property/indexer returns a value type, and we try to set a field in it
                        if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) {
-                               Error_CannotModifyIntermediateExpressionValue (ec);
+                               Error_ValueAssignment (ec, right_side);
                        }
 
                        if (eclass == ExprClass.Unresolved) {
@@ -5434,14 +5919,43 @@ namespace Mono.CSharp {
                //
                // Implements the IAssignMethod interface for assignments
                //
-               public abstract void Emit (EmitContext ec, bool leave_copy);
-               public abstract void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load);
+               public virtual void Emit (EmitContext ec, bool leave_copy)
+               {
+                       var call = new CallEmitter ();
+                       call.InstanceExpression = InstanceExpression;
+                       if (has_await_arguments)
+                               call.HasAwaitArguments = true;
+                       else
+                               call.DuplicateArguments = emitting_compound_assignment;
+
+                       call.Emit (ec, Getter, Arguments, loc);
+
+                       if (call.HasAwaitArguments) {
+                               InstanceExpression = call.InstanceExpression;
+                               Arguments = call.EmittedArguments;
+                               has_await_arguments = true;
+                       }
+
+                       if (leave_copy) {
+                               ec.Emit (OpCodes.Dup);
+                               temp = new LocalTemporary (Type);
+                               temp.Store (ec);
+                       }
+               }
+
+               public abstract void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound);
 
                public override void Emit (EmitContext ec)
                {
                        Emit (ec, false);
                }
 
+               protected override void EmitToFieldSource (EmitContext ec)
+               {
+                       has_await_arguments = true;
+                       Emit (ec, false);
+               }
+
                public abstract SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source);
 
                protected abstract Expression OverloadResolve (ResolveContext rc, Expression right_side);
@@ -5630,14 +6144,17 @@ namespace Mono.CSharp {
                        throw new NotImplementedException ();
                }
 
-               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
+               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
                {
-                       if (leave_copy || !prepare_for_load)
+                       if (leave_copy || !isCompound)
                                throw new NotImplementedException ("EventExpr::EmitAssign");
 
                        Arguments args = new Arguments (1);
                        args.Add (new Argument (source));
-                       Invocation.EmitCall (ec, InstanceExpression, op, args, loc);
+
+                       var call = new CallEmitter ();
+                       call.InstanceExpression = InstanceExpression;
+                       call.Emit (ec, op, args, loc);
                }
 
                #endregion
@@ -5668,7 +6185,7 @@ namespace Mono.CSharp {
 
                public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
                {
-                       Error_TypeArgumentsCannotBeUsed (ec.Report, "event", GetSignatureForError (), loc);
+                       Error_TypeArgumentsCannotBeUsed (ec, "event", GetSignatureForError (), loc);
                }
        }
 
@@ -5724,20 +6241,15 @@ namespace Mono.CSharp {
                        return new TemporaryVariableReference (li, loc);
                }
 
-               public override Expression CreateExpressionTree (ResolveContext ec)
-               {
-                       throw new NotSupportedException ("ET");
-               }
-
                protected override Expression DoResolve (ResolveContext ec)
                {
                        eclass = ExprClass.Variable;
 
                        //
                        // Don't capture temporary variables except when using
-                       // iterator redirection
+                       // state machine redirection
                        //
-                       if (ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.IsIterator && ec.IsVariableCapturingRequired) {
+                       if (ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod is StateMachineInitializer && ec.IsVariableCapturingRequired) {
                                AnonymousMethodStorey storey = li.Block.Explicit.CreateAnonymousMethodStorey (ec);
                                storey.CaptureLocalVariable (ec, li);
                        }
@@ -5791,7 +6303,11 @@ namespace Mono.CSharp {
                }
 
                public override VariableInfo VariableInfo {
-                       get { throw new NotImplementedException (); }
+                       get { return null; }
+               }
+
+               public override void VerifyAssigned (ResolveContext rc)
+               {
                }
        }