**** Merged from MCS ****
[mono.git] / mcs / gmcs / expression.cs
index 45866fd0654d2c97898ca51d0dd293630db3f70a..47b58f93e06031c35dc247695d651a959f6aa506 100755 (executable)
@@ -4,8 +4,8 @@
 // Author:
 //   Miguel de Icaza (miguel@ximian.com)
 //
-// (C) 2001 Ximian, Inc.
-//
+// (C) 2001, 2002, 2003 Ximian, Inc.
+// (C) 2003, 2004 Novell, Inc.
 //
 #define USE_OLD
 
@@ -66,7 +66,8 @@ namespace Mono.CSharp {
                                 return null;
 
                         args.Add (a);
-                       method = Invocation.OverloadResolve (ec, (MethodGroupExpr) mg, args, loc);
+                       method = Invocation.OverloadResolve (
+                               ec, (MethodGroupExpr) mg, args, false, loc);
 
                        if (method == null)
                                return null;
@@ -429,6 +430,11 @@ namespace Mono.CSharp {
                                        return null;
                                }
 
+                               if (ec.InFixedInitializer && ((variable != null) && variable.VerifyFixed (false))) {
+                                       Error (213, "You can not fix an already fixed expression");
+                                       return null;
+                               }
+
                                // According to the specs, a variable is considered definitely assigned if you take
                                // its address.
                                if ((variable != null) && (variable.VariableInfo != null))
@@ -605,16 +611,12 @@ namespace Mono.CSharp {
                        }
                }
 
-               /// <summary>
-               ///   This will emit the child expression for `ec' avoiding the logical
-               ///   not.  The parent will take care of changing brfalse/brtrue
-               /// </summary>
-               public void EmitLogicalNot (EmitContext ec)
+               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
                {
-                       if (Oper != Operator.LogicalNot)
-                               throw new Exception ("EmitLogicalNot can only be called with !expr");
-
-                       Expr.Emit (ec);
+                       if (Oper == Operator.LogicalNot)
+                               Expr.EmitBranchable (ec, target, !onTrue);
+                       else
+                               base.EmitBranchable (ec, target, onTrue);
                }
 
                public override string ToString ()
@@ -651,14 +653,14 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
 
                        if (temporary != null){
-                               if (have_temporary){
+                               if (have_temporary) {
                                        temporary.Emit (ec);
-                                       return;
-                               }
+                               } else {
                                expr.Emit (ec);
                                ec.ig.Emit (OpCodes.Dup);
                                temporary.Store (ec);
                                have_temporary = true;
+                               }
                        } else
                                expr.Emit (ec);
                        
@@ -975,6 +977,13 @@ namespace Mono.CSharp {
 
                        ia.CacheTemporaries (ec);
 
+                       //
+                       // NOTE: We should probably handle three cases:
+                       //
+                       //     * method invocation required.
+                       //     * direct stack manipulation possible
+                       //     * the object requires an "instance" field
+                       //
                        if (temp_storage == null){
                                //
                                // Temporary improvement: if we are dealing with something that does
@@ -1050,6 +1059,8 @@ namespace Mono.CSharp {
                                ia.EmitAssign (ec, temp_storage);
                                break;
                        }
+
+                       temp_storage.Release (ec);
                }
 
                public override void Emit (EmitContext ec)
@@ -1152,6 +1163,35 @@ namespace Mono.CSharp {
                        throw new Exception ("never reached");
                }
 
+               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       switch (action){
+                       case Action.AlwaysFalse:
+                               if (! onTrue)
+                                       ig.Emit (OpCodes.Br, target);
+                               
+                               return;
+                       case Action.AlwaysTrue:
+                               if (onTrue)
+                                       ig.Emit (OpCodes.Br, target);
+                               
+                               return;
+                       case Action.LeaveOnStack:
+                               // the `e != null' rule.
+                               expr.Emit (ec);
+                               ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+                               return;
+                       case Action.Probe:
+                               expr.Emit (ec);
+                               ig.Emit (OpCodes.Isinst, probe_type);
+                               ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+                               return;
+                       }
+                       throw new Exception ("never reached");
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        Expression e = base.DoResolve (ec);
@@ -2174,12 +2214,6 @@ namespace Mono.CSharp {
                        Error_OperatorCannotBeApplied (loc, OperName (oper), left.Type, right.Type);
                }
 
-               static bool is_32_or_64 (Type t)
-               {
-                       return (t == TypeManager.int32_type || t == TypeManager.uint32_type ||
-                               t == TypeManager.int64_type || t == TypeManager.uint64_type);
-               }
-
                static bool is_unsigned (Type t)
                {
                        return (t == TypeManager.uint32_type || t == TypeManager.uint64_type ||
@@ -2194,6 +2228,28 @@ namespace Mono.CSharp {
                        else
                                return false;
                }
+
+               Expression Make32or64 (EmitContext ec, Expression e)
+               {
+                       Type t= e.Type;
+                       
+                       if (t == TypeManager.int32_type || t == TypeManager.uint32_type ||
+                           t == TypeManager.int64_type || t == TypeManager.uint64_type)
+                               return e;
+                       Expression ee = Convert.ImplicitConversion (ec, e, TypeManager.int32_type, loc);
+                       if (ee != null)
+                               return ee;
+                       ee = Convert.ImplicitConversion (ec, e, TypeManager.uint32_type, loc);
+                       if (ee != null)
+                               return ee;
+                       ee = Convert.ImplicitConversion (ec, e, TypeManager.int64_type, loc);
+                       if (ee != null)
+                               return ee;
+                       ee = Convert.ImplicitConversion (ec, e, TypeManager.uint64_type, loc);
+                       if (ee != null)
+                               return ee;
+                       return null;
+               }
                                        
                Expression CheckShiftArguments (EmitContext ec)
                {
@@ -2235,7 +2291,7 @@ namespace Mono.CSharp {
                        bool overload_failed = false;
 
                        //
-                       // Special cases: string comapred to null
+                       // Special cases: string or type parameter comapred to null
                        //
                        if (oper == Operator.Equality || oper == Operator.Inequality){
                                if ((l == TypeManager.string_type && (right is NullLiteral)) ||
@@ -2244,6 +2300,28 @@ namespace Mono.CSharp {
                                        
                                        return this;
                                }
+
+                               if (l.IsGenericParameter && (right is NullLiteral)) {
+                                       if (l.BaseType == TypeManager.value_type) {
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+
+                                       left = new BoxedCast (left);
+                                       Type = TypeManager.bool_type;
+                                       return this;
+                               }
+
+                               if (r.IsGenericParameter && (left is NullLiteral)) {
+                                       if (r.BaseType == TypeManager.value_type) {
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+
+                                       right = new BoxedCast (right);
+                                       Type = TypeManager.bool_type;
+                                       return this;
+                               }
                        }
 
                        //
@@ -2272,7 +2350,9 @@ namespace Mono.CSharp {
                                        args.Add (new Argument (left, Argument.AType.Expression));
                                        args.Add (new Argument (right, Argument.AType.Expression));
                                        
-                                       MethodBase method = Invocation.OverloadResolve (ec, union, args, Location.Null);
+                                       MethodBase method = Invocation.OverloadResolve (
+                                               ec, union, args, true, Location.Null);
+
                                        if (method != null) {
                                                MethodInfo mi = (MethodInfo) method;
                                                
@@ -2283,10 +2363,6 @@ namespace Mono.CSharp {
                                }
                        }
                        
-                       //
-                       // Step 2: Default operations on CLI native types.
-                       //
-
                        //
                        // Step 0: String concatenation (because overloading will get this wrong)
                        //
@@ -2295,93 +2371,35 @@ namespace Mono.CSharp {
                                // If any of the arguments is a string, cast to string
                                //
                                
-                               if (l == TypeManager.string_type){
-                                       MethodBase method;
-                                       
-                                       if (r == TypeManager.void_type) {
-                                               Error_OperatorCannotBeApplied ();
-                                               return null;
-                                       }
-                                       
-                                       if (r == TypeManager.string_type){
-                                               if (left is Constant && right is Constant){
-                                                       StringConstant ls = (StringConstant) left;
-                                                       StringConstant rs = (StringConstant) right;
-                                                       
-                                                       return new StringConstant (
-                                                               ls.Value + rs.Value);
-                                               }
-
-                                               if (left is BinaryMethod){
-                                                       BinaryMethod b = (BinaryMethod) left;
-
-                                                       //
-                                                       // Call String.Concat (string, string, string) or
-                                                       // String.Concat (string, string, string, string)
-                                                       // if possible.
-                                                       //
-                                                       if (b.method == TypeManager.string_concat_string_string ||
-                                                            b.method == TypeManager.string_concat_string_string_string){
-                                                               int count = b.Arguments.Count;
-                                                               
-                                                               if (count == 2){
-                                                                       ArrayList bargs = new ArrayList (3);
-                                                                       bargs.AddRange (b.Arguments);
-                                                                       bargs.Add (new Argument (right, Argument.AType.Expression));
-                                                                       return new BinaryMethod (
-                                                                               TypeManager.string_type,
-                                                                               TypeManager.string_concat_string_string_string, bargs);
-                                                               } else if (count == 3){
-                                                                       ArrayList bargs = new ArrayList (4);
-                                                                       bargs.AddRange (b.Arguments);
-                                                                       bargs.Add (new Argument (right, Argument.AType.Expression));
-                                                                       return new BinaryMethod (
-                                                                               TypeManager.string_type,
-                                                                               TypeManager.string_concat_string_string_string_string, bargs);
-                                                               }
-                                                       }
-                                               }
-
-                                               // string + string
-                                               method = TypeManager.string_concat_string_string;
-                                       } else {
-                                               // string + object
-                                               method = TypeManager.string_concat_object_object;
-                                               right = Convert.ImplicitConversion (
-                                                       ec, right, TypeManager.object_type, loc);
-                                               if (right == null){
-                                                       Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
-                                                       return null;
-                                               }
-                                       }
-
-                                       //
-                                       // Cascading concats will hold up to 2 arguments, any extras will be
-                                       // reallocated above.
-                                       //
-                                       ArrayList args = new ArrayList (2);
-                                       args.Add (new Argument (left, Argument.AType.Expression));
-                                       args.Add (new Argument (right, Argument.AType.Expression));
+                               // Simple constant folding
+                               if (left is StringConstant && right is StringConstant)
+                                       return new StringConstant (((StringConstant) left).Value + ((StringConstant) right).Value);
 
-                                       return new BinaryMethod (TypeManager.string_type, method, args);
-                               } else if (r == TypeManager.string_type){
-                                       // object + string
+                               if (l == TypeManager.string_type || r == TypeManager.string_type) {
 
-                                       if (l == TypeManager.void_type) {
+                                       if (r == TypeManager.void_type || l == TypeManager.void_type) {
                                                Error_OperatorCannotBeApplied ();
                                                return null;
                                        }
                                        
-                                       left = Convert.ImplicitConversion (ec, left, TypeManager.object_type, loc);
-                                       if (left == null){
-                                               Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
-                                               return null;
+                                       // try to fold it in on the left
+                                       if (left is StringConcat) {
+
+                                               //
+                                               // We have to test here for not-null, since we can be doubly-resolved
+                                               // take care of not appending twice
+                                               //
+                                               if (type == null){
+                                                       type = TypeManager.string_type;
+                                                       ((StringConcat) left).Append (ec, right);
+                                                       return left.Resolve (ec);
+                                               } else {
+                                                       return left;
+                                               }
                                        }
-                                       ArrayList args = new ArrayList (2);
-                                       args.Add (new Argument (left, Argument.AType.Expression));
-                                       args.Add (new Argument (right, Argument.AType.Expression));
 
-                                       return new BinaryMethod (TypeManager.string_type, TypeManager.string_concat_object_object, args);
+                                       // Otherwise, start a new concat expression
+                                       return new StringConcat (ec, loc, left, right).Resolve (ec);
                                }
 
                                //
@@ -2463,8 +2481,16 @@ namespace Mono.CSharp {
                        // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
                        //
                        if (oper == Operator.Addition || oper == Operator.Subtraction) {
-                               if (l.IsSubclassOf (TypeManager.delegate_type) &&
-                                   r.IsSubclassOf (TypeManager.delegate_type)) {
+                               if (TypeManager.IsDelegateType (l)){
+                                       if (right.eclass == ExprClass.MethodGroup && RootContext.V2){
+                                               Expression tmp = Convert.ImplicitConversionRequired (ec, right, l, loc);
+                                               if (tmp == null)
+                                                       return null;
+                                               right = tmp;
+                                               r = right.Type;
+                                       }
+                               
+                                       if (TypeManager.IsDelegateType (r)){
                                        MethodInfo method;
                                        ArrayList args = new ArrayList (2);
                                        
@@ -2484,6 +2510,7 @@ namespace Mono.CSharp {
 
                                        return new BinaryDelegate (l, method, args);
                                }
+                               }
 
                                //
                                // Pointer arithmetic:
@@ -2511,12 +2538,16 @@ namespace Mono.CSharp {
                                                        return new PointerArithmetic (
                                                                false, left, right, TypeManager.int64_type,
                                                                loc);
-                                       } else if (is_32_or_64 (r))
-                                               return new PointerArithmetic (
-                                                       oper == Operator.Addition, left, right, l, loc);
-                               } else if (r.IsPointer && is_32_or_64 (l) && oper == Operator.Addition)
-                                       return new PointerArithmetic (
-                                               true, right, left, r, loc);
+                                       } else {
+                                               Expression t = Make32or64 (ec, right);
+                                               if (t != null)
+                                                       return new PointerArithmetic (oper == Operator.Addition, left, t, l, loc);
+                                       }
+                               } else if (r.IsPointer && oper == Operator.Addition){
+                                       Expression t = Make32or64 (ec, left);
+                                       if (t != null)
+                                               return new PointerArithmetic (true, right, t, r, loc);
+                               }
                        }
                        
                        //
@@ -2528,7 +2559,8 @@ namespace Mono.CSharp {
                                Expression temp;
 
                                // U operator - (E e, E f)
-                               if (lie && rie && oper == Operator.Subtraction){
+                               if (lie && rie){
+                                       if (oper == Operator.Subtraction){
                                        if (l == r){
                                                type = TypeManager.EnumToUnderlying (l);
                                                return this;
@@ -2536,6 +2568,7 @@ namespace Mono.CSharp {
                                        Error_OperatorCannotBeApplied ();
                                        return null;
                                }
+                               }
                                        
                                //
                                // operator + (E e, U x)
@@ -2545,9 +2578,18 @@ namespace Mono.CSharp {
                                        Type enum_type = lie ? l : r;
                                        Type other_type = lie ? r : l;
                                        Type underlying_type = TypeManager.EnumToUnderlying (enum_type);
-;
                                        
                                        if (underlying_type != other_type){
+                                               temp = Convert.ImplicitConversion (ec, lie ? right : left, underlying_type, loc);
+                                               if (temp != null){
+                                                       if (lie)
+                                                               right = temp;
+                                                       else
+                                                               left = temp;
+                                                       type = enum_type;
+                                                       return this;
+                                               }
+                                                       
                                                Error_OperatorCannotBeApplied ();
                                                return null;
                                        }
@@ -2737,7 +2779,7 @@ namespace Mono.CSharp {
                ///   The expression's code is generated, and we will generate a branch to `target'
                ///   if the resulting expression value is equal to isTrue
                /// </remarks>
-               public bool EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
                {
                        ILGenerator ig = ec.ig;
 
@@ -2747,135 +2789,77 @@ namespace Mono.CSharp {
                        // but on top of that we want for == and != to use a special path
                        // if we are comparing against null
                        //
-                       if (oper == Operator.Equality || oper == Operator.Inequality){
+                       if ((oper == Operator.Equality || oper == Operator.Inequality) && (left is Constant || right is Constant)) {
                                bool my_on_true = oper == Operator.Inequality ? onTrue : !onTrue;
 
-                               if (left is NullLiteral){
-                                       right.Emit (ec);
-                                       if (my_on_true)
-                                               ig.Emit (OpCodes.Brtrue, target);
-                                       else
-                                               ig.Emit (OpCodes.Brfalse, target);
-                                       return true;
-                               } else if (right is NullLiteral){
+                               //
+                               // put the constant on the rhs, for simplicity
+                               //
+                               if (left is Constant) {
+                                       Expression swap = right;
+                                       right = left;
+                                       left = swap;
+                               }
+                                       
+                               if (((Constant) right).IsZeroInteger) {
                                        left.Emit (ec);
                                        if (my_on_true)
                                                ig.Emit (OpCodes.Brtrue, target);
                                        else
                                                ig.Emit (OpCodes.Brfalse, target);
-                                       return true;
-                               } else if (left is BoolConstant){
-                                       right.Emit (ec);
-                                       if (my_on_true != ((BoolConstant) left).Value)
-                                               ig.Emit (OpCodes.Brtrue, target);
-                                       else
-                                               ig.Emit (OpCodes.Brfalse, target);
-                                       return true;
+                                       
+                                       return;
                                } else if (right is BoolConstant){
                                        left.Emit (ec);
                                        if (my_on_true != ((BoolConstant) right).Value)
                                                ig.Emit (OpCodes.Brtrue, target);
                                        else
                                                ig.Emit (OpCodes.Brfalse, target);
-                                       return true;
+                                       
+                                       return;
                                }
 
-                       } else if (oper == Operator.LogicalAnd){
-                               if (left is Binary){
-                                       Binary left_binary = (Binary) left;
+                       } else if (oper == Operator.LogicalAnd) {
 
-                                       if (onTrue){
+                               if (onTrue) {
                                                Label tests_end = ig.DefineLabel ();
                                                
-                                               if (left_binary.EmitBranchable (ec, tests_end, false)){
-                                                       if (right is Binary){
-                                                               Binary right_binary = (Binary) right;
-
-                                                               if (right_binary.EmitBranchable (ec, target, true)){
-                                                                       ig.MarkLabel (tests_end);
-                                                                       return true;
-                                                               }
-                                                       }
-                                                       right.Emit (ec);
-                                                       ig.Emit (OpCodes.Brtrue, target);
+                                       left.EmitBranchable (ec, tests_end, false);
+                                       right.EmitBranchable (ec, target, true);
                                                        ig.MarkLabel (tests_end);
-                                                       return true;
-                                               }
                                        } else {
-                                               if (left_binary.EmitBranchable (ec, target, false)){
-                                                       if (right is Binary){
-                                                               Binary right_binary = (Binary) right;
-                                                               
-                                                               if (right_binary.EmitBranchable (ec, target, false))
-                                                                       return true;
-                                                       }
-                                                       right.Emit (ec);
-                                                       if (onTrue)
-                                                               ig.Emit (OpCodes.Brtrue, target);
-                                                       else
-                                                               ig.Emit (OpCodes.Brfalse, target);
-                                                       return true;
-                                               }
+                                       left.EmitBranchable (ec, target, false);
+                                       right.EmitBranchable (ec, target, false);
                                        }
-                                       //
-                                       // Give up, and let the regular Emit work, but we could
-                                       // also optimize the left-non-Branchable, but-right-Branchable
-                                       //
-                               }
-                               return false;
-                       } else if (oper == Operator.LogicalOr){
-                               if (left is Binary){
-                                       Binary left_binary = (Binary) left;
 
-                                       if (onTrue){
-                                               if (left_binary.EmitBranchable (ec, target, true)){
-                                                       if (right is Binary){
-                                                               Binary right_binary = (Binary) right;
+                               return;
                                                                
-                                                               if (right_binary.EmitBranchable (ec, target, true))
-                                                                       return true;
-                                                       }
-                                                       right.Emit (ec);
-                                                       ig.Emit (OpCodes.Brtrue, target);
-                                                       return true;
-                                               }
+                       } else if (oper == Operator.LogicalOr){
+                               if (onTrue) {
+                                       left.EmitBranchable (ec, target, true);
+                                       right.EmitBranchable (ec, target, true);
                                                
-                                               //
-                                               // Give up, and let the regular Emit work, but we could
-                                               // also optimize the left-non-Branchable, but-right-Branchable
-                                               //
                                        } else {
                                                Label tests_end = ig.DefineLabel ();
+                                       left.EmitBranchable (ec, tests_end, true);
+                                       right.EmitBranchable (ec, target, false);
+                                       ig.MarkLabel (tests_end);
+                               }
                                                
-                                               if (left_binary.EmitBranchable (ec, tests_end, true)){
-                                                       if (right is Binary){
-                                                               Binary right_binary = (Binary) right;
-
-                                                               if (right_binary.EmitBranchable (ec, target, false)){
-                                                                       ig.MarkLabel (tests_end);
-                                                                       return true;
-                                                               }
-                                                       }
-                                                       right.Emit (ec);
-                                                       ig.Emit (OpCodes.Brfalse, target);
-                                                       ig.MarkLabel (tests_end);
-                                                       return true;
-                                               }
-                                       }
+                               return;
+
+                       } else if (!(oper == Operator.LessThan        || oper == Operator.GreaterThan ||
+                                    oper == Operator.LessThanOrEqual || oper == Operator.GreaterThanOrEqual ||
+                                    oper == Operator.Equality        || oper == Operator.Inequality)) {
+                               base.EmitBranchable (ec, target, onTrue);
+                               return;
                                }
                                
-                               return false;
-                       } else if (!(oper == Operator.LessThan ||
-                               oper == Operator.GreaterThan ||
-                               oper == Operator.LessThanOrEqual ||
-                               oper == Operator.GreaterThanOrEqual))
-                               return false;
-                       
                        left.Emit (ec);
                        right.Emit (ec);
 
                        Type t = left.Type;
-                       bool isUnsigned = is_unsigned (t);
+                       bool isUnsigned = is_unsigned (t) || t == TypeManager.double_type || t == TypeManager.float_type;
 
                        switch (oper){
                        case Operator.Equality:
@@ -2919,9 +2903,6 @@ namespace Mono.CSharp {
                                break;
 
                        case Operator.LessThanOrEqual:
-                               if (t == TypeManager.double_type || t == TypeManager.float_type)
-                                       isUnsigned = true;
-
                                if (onTrue)
                                        if (isUnsigned)
                                                ig.Emit (OpCodes.Ble_Un, target);
@@ -2936,8 +2917,6 @@ namespace Mono.CSharp {
 
 
                        case Operator.GreaterThanOrEqual:
-                               if (t == TypeManager.double_type || t == TypeManager.float_type)
-                                       isUnsigned = true;
                                if (onTrue)
                                        if (isUnsigned)
                                                ig.Emit (OpCodes.Bge_Un, target);
@@ -2949,12 +2928,10 @@ namespace Mono.CSharp {
                                        else
                                                ig.Emit (OpCodes.Blt, target);
                                break;
-
                        default:
-                               return false;
+                               Console.WriteLine (oper);
+                               throw new Exception ("what is THAT");
                        }
-                       
-                       return true;
                }
                
                public override void Emit (EmitContext ec)
@@ -2967,52 +2944,26 @@ namespace Mono.CSharp {
                        // Handle short-circuit operators differently
                        // than the rest
                        //
-                       if (oper == Operator.LogicalAnd){
+                       if (oper == Operator.LogicalAnd) {
                                Label load_zero = ig.DefineLabel ();
                                Label end = ig.DefineLabel ();
-                               bool process = true;
 
-                               if (left is Binary){
-                                       Binary left_binary = (Binary) left;
-
-                                       if (left_binary.EmitBranchable (ec, load_zero, false)){
+                               left.EmitBranchable (ec, load_zero, false);
                                                right.Emit (ec);
                                                ig.Emit (OpCodes.Br, end);
-                                               process = false;
-                                       }
-                               }
 
-                               if (process){
-                                       left.Emit (ec);
-                                       ig.Emit (OpCodes.Brfalse, load_zero);
-                                       right.Emit (ec);
-                                       ig.Emit (OpCodes.Br, end);
-                               }
                                ig.MarkLabel (load_zero);
                                ig.Emit (OpCodes.Ldc_I4_0);
                                ig.MarkLabel (end);
                                return;
-                       } else if (oper == Operator.LogicalOr){
+                       } else if (oper == Operator.LogicalOr) {
                                Label load_one = ig.DefineLabel ();
                                Label end = ig.DefineLabel ();
-                               bool process = true;
                                
-                               if (left is Binary){
-                                       Binary left_binary = (Binary) left;
-
-                                       if (left_binary.EmitBranchable (ec, load_one, true)){
+                               left.EmitBranchable (ec, load_one, true);
                                                right.Emit (ec);
                                                ig.Emit (OpCodes.Br, end);
-                                               process = false;
-                                       } 
-                               }
 
-                               if (process){
-                                       left.Emit (ec);
-                                       ig.Emit (OpCodes.Brtrue, load_one);
-                                       right.Emit (ec);
-                                       ig.Emit (OpCodes.Br, end);
-                               }
                                ig.MarkLabel (load_one);
                                ig.Emit (OpCodes.Ldc_I4_1);
                                ig.MarkLabel (end);
@@ -3193,6 +3144,137 @@ namespace Mono.CSharp {
                }
        }
 
+       //
+       // Represents the operation a + b [+ c [+ d [+ ...]]], where a is a string
+       // b, c, d... may be strings or objects.
+       //
+       public class StringConcat : Expression {
+               ArrayList operands;
+               bool invalid = false;
+               
+               
+               public StringConcat (EmitContext ec, Location loc, Expression left, Expression right)
+               {
+                       this.loc = loc;
+                       type = TypeManager.string_type;
+                       eclass = ExprClass.Value;
+               
+                       operands = new ArrayList (2);
+                       Append (ec, left);
+                       Append (ec, right);
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (invalid)
+                               return null;
+                       
+                       return this;
+               }
+               
+               public void Append (EmitContext ec, Expression operand)
+               {
+                       //
+                       // Constant folding
+                       //
+                       if (operand is StringConstant && operands.Count != 0) {
+                               StringConstant last_operand = operands [operands.Count - 1] as StringConstant;
+                               if (last_operand != null) {
+                                       operands [operands.Count - 1] = new StringConstant (last_operand.Value + ((StringConstant) operand).Value);
+                                       return;
+                               }
+                       }
+                       
+                       //
+                       // Conversion to object
+                       //
+                       if (operand.Type != TypeManager.string_type) {
+                               Expression no = Convert.ImplicitConversion (ec, operand, TypeManager.object_type, loc);
+                               
+                               if (no == null) {
+                                       Binary.Error_OperatorCannotBeApplied (loc, "+", TypeManager.string_type, operand.Type);
+                                       invalid = true;
+                               }
+                               operand = no;
+                       }
+                       
+                       operands.Add (operand);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       MethodInfo concat_method = null;
+                       
+                       //
+                       // Are we also concating objects?
+                       //
+                       bool is_strings_only = true;
+                       
+                       //
+                       // Do conversion to arguments; check for strings only
+                       //
+                       for (int i = 0; i < operands.Count; i ++) {
+                               Expression e = (Expression) operands [i];
+                               is_strings_only &= e.Type == TypeManager.string_type;
+                       }
+                       
+                       for (int i = 0; i < operands.Count; i ++) {
+                               Expression e = (Expression) operands [i];
+                               
+                               if (! is_strings_only && e.Type == TypeManager.string_type) {
+                                       // need to make sure this is an object, because the EmitParams
+                                       // method might look at the type of this expression, see it is a
+                                       // string and emit a string [] when we want an object [];
+                                       
+                                       e = Convert.ImplicitConversion (ec, e, TypeManager.object_type, loc);
+                               }
+                               operands [i] = new Argument (e, Argument.AType.Expression);
+                       }
+                       
+                       //
+                       // Find the right method
+                       //
+                       switch (operands.Count) {
+                       case 1:
+                               //
+                               // This should not be possible, because simple constant folding
+                               // is taken care of in the Binary code.
+                               //
+                               throw new Exception ("how did you get here?");
+                       
+                       case 2:
+                               concat_method = is_strings_only ? 
+                                       TypeManager.string_concat_string_string :
+                                       TypeManager.string_concat_object_object ;
+                               break;
+                       case 3:
+                               concat_method = is_strings_only ? 
+                                       TypeManager.string_concat_string_string_string :
+                                       TypeManager.string_concat_object_object_object ;
+                               break;
+                       case 4:
+                               //
+                               // There is not a 4 param overlaod for object (the one that there is
+                               // is actually a varargs methods, and is only in corlib because it was
+                               // introduced there before.).
+                               //
+                               if (!is_strings_only)
+                                       goto default;
+                               
+                               concat_method = TypeManager.string_concat_string_string_string_string;
+                               break;
+                       default:
+                               concat_method = is_strings_only ? 
+                                       TypeManager.string_concat_string_dot_dot_dot :
+                                       TypeManager.string_concat_object_dot_dot_dot ;
+                               break;
+                       }
+                       
+                       Invocation.EmitArguments (ec, concat_method, operands);
+                       ec.ig.Emit (OpCodes.Call, concat_method);
+               }
+       }
+
        //
        // Object created with +/= on delegates
        //
@@ -3280,7 +3362,9 @@ namespace Mono.CSharp {
                        ArrayList arguments = new ArrayList ();
                        arguments.Add (new Argument (left, Argument.AType.Expression));
                        arguments.Add (new Argument (right, Argument.AType.Expression));
-                       method = Invocation.OverloadResolve (ec, (MethodGroupExpr) operator_group, arguments, loc) as MethodInfo;
+                       method = Invocation.OverloadResolve (
+                               ec, (MethodGroupExpr) operator_group, arguments, false, loc)
+                               as MethodInfo;
                        if ((method == null) || (method.ReturnType != type)) {
                                Error19 ();
                                return null;
@@ -3306,7 +3390,7 @@ namespace Mono.CSharp {
 
                        ig.Emit (OpCodes.Nop);
 
-                       Statement.EmitBoolExpression (ec, is_and ? op_false : op_true, false_target, false);
+                       (is_and ? op_false : op_true).EmitBranchable (ec, false_target, false);
                        left.Emit (ec);
                        ig.Emit (OpCodes.Br, end_target);
                        ig.MarkLabel (false_target);
@@ -3510,7 +3594,7 @@ namespace Mono.CSharp {
                        Label false_target = ig.DefineLabel ();
                        Label end_target = ig.DefineLabel ();
 
-                       Statement.EmitBoolExpression (ec, expr, false_target, false);
+                       expr.EmitBranchable (ec, false_target, false);
                        trueExpr.Emit (ec);
                        ig.Emit (OpCodes.Br, end_target);
                        ig.MarkLabel (false_target);
@@ -3920,6 +4004,10 @@ namespace Mono.CSharp {
 
                public bool ResolveMethodGroup (EmitContext ec, Location loc)
                {
+                       ConstructedType ctype = Expr as ConstructedType;
+                       if (ctype != null)
+                               Expr = ctype.GetMemberAccess (ec);
+
                        // FIXME: csc doesn't report any error if you try to use `ref' or
                        //        `out' in a delegate creation expression.
                        Expr = Expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
@@ -3947,12 +4035,30 @@ namespace Mono.CSharp {
 
                        if (ArgType == AType.Expression)
                                return true;
-
-                       if (Expr.eclass != ExprClass.Variable){
+                       else {
                                //
-                               // We just probe to match the CSC output
+                               // Catch errors where fields of a MarshalByRefObject are passed as ref or out
+                               // This is only allowed for `this'
                                //
-                               if (Expr.eclass == ExprClass.PropertyAccess ||
+                               FieldExpr fe = Expr as FieldExpr;
+                               if (fe != null && !fe.IsStatic){
+                                       Expression instance = fe.InstanceExpression;
+
+                                       if (instance.GetType () != typeof (This)){
+                                               if (fe.InstanceExpression.Type.IsSubclassOf (TypeManager.mbr_type)){
+                                                       Report.Error (197, loc,
+                                                                     "Can not pass a type that derives from MarshalByRefObject with out or ref");
+                                                       return false;
+                                               }
+                                       }
+                               }
+                       }
+
+                       if (Expr.eclass != ExprClass.Variable){
+                               //
+                               // We just probe to match the CSC output
+                               //
+                               if (Expr.eclass == ExprClass.PropertyAccess ||
                                    Expr.eclass == ExprClass.IndexerAccess){
                                        Report.Error (
                                                206, loc,
@@ -3992,8 +4098,9 @@ namespace Mono.CSharp {
                                                
                                                pr.AddressOf (ec, mode);
                                        }
-                               } else
+                               } else {
                                        ((IMemoryLocation)Expr).AddressOf (ec, mode);
+                               }
                        } else
                                Expr.Emit (ec);
                }
@@ -4048,15 +4155,13 @@ namespace Mono.CSharp {
                        if (pd != null)
                                return (ParameterData) pd;
 
-                       
                        ip = TypeManager.LookupParametersByBuilder (mb);
                        if (ip != null){
                                method_parameter_cache [mb] = ip;
 
                                return (ParameterData) ip;
                        } else {
-                               ParameterInfo [] pi = mb.GetParameters ();
-                               ReflectionParameters rp = new ReflectionParameters (pi);
+                               ReflectionParameters rp = new ReflectionParameters (mb);
                                method_parameter_cache [mb] = rp;
 
                                return (ParameterData) rp;
@@ -4079,8 +4184,7 @@ namespace Mono.CSharp {
                                                      " does not resolve its type");
 
                        //
-                       // This is a special case since csc behaves this way. I can't find
-                       // it anywhere in the spec but oh well ...
+                       // This is a special case since csc behaves this way.
                        //
                        if (argument_expr is NullLiteral &&
                             p == TypeManager.string_type &&
@@ -4091,6 +4195,25 @@ namespace Mono.CSharp {
                                  q == TypeManager.string_type)
                                return 0;
                        
+                        //
+                        // csc behaves this way so we emulate it. Basically, if the argument
+                        // is null and one of the types to compare is 'object' and the other
+                        // is a reference type, we prefer the other.
+                        //
+                        // I can't find this anywhere in the spec but we can interpret this
+                        // to mean that null can be of any type you wish in such a context
+                        //
+                        if (p != null && q != null) {
+                                if (argument_expr is NullLiteral &&
+                                    !p.IsValueType &&
+                                    q == TypeManager.object_type)
+                                        return 1;
+                                else if (argument_expr is NullLiteral &&
+                                         !q.IsValueType &&
+                                         p == TypeManager.object_type)
+                                        return 0;
+                        }
+                                
                        if (p == q)
                                return 0;
                        
@@ -4155,6 +4278,14 @@ namespace Mono.CSharp {
                                        // we can optimize this case: a positive int32
                                        // always fits on a uint64
                                        //
+
+                                        //
+                                        // This special case is needed because csc behaves like this.
+                                        // int -> uint is better than int -> ulong!
+                                        //
+                                        if (q == TypeManager.uint32_type)
+                                                return 0;
+                                        
                                        if (q == TypeManager.int64_type)
                                                return 0;
                                        else if (value >= 0)
@@ -4239,7 +4370,6 @@ namespace Mono.CSharp {
                        // best method, we cant tell. This happens
                        // if we have:
                        // 
-                       //
                        //      interface IFoo {
                        //              void DoIt ();
                        //      }
@@ -4254,6 +4384,7 @@ namespace Mono.CSharp {
                        //
                        // However, we have to consider that
                        // Trim (); is better than Trim (params char[] chars);
+                        //
                        if (cand_count == 0 && argument_count == 0)
                                return best == null || best_params ? 1 : 0;
 
@@ -4339,6 +4470,9 @@ namespace Mono.CSharp {
                {
                        string ret_type = "";
 
+                        if (mb == null)
+                                return "";
+
                        if (mb is MethodInfo)
                                ret_type = TypeManager.CSharpName (((MethodInfo) mb).ReturnType);
                        
@@ -4410,6 +4544,16 @@ namespace Mono.CSharp {
                        return union;
                }
 
+               static bool IsParamsMethodApplicable (EmitContext ec, MethodGroupExpr me,
+                                                     ArrayList arguments, ref MethodBase candidate)
+               {
+                       if (!me.HasTypeArguments &&
+                           !InferParamsTypeArguments (ec, arguments, ref candidate))
+                               return false;
+
+                       return IsParamsMethodApplicable (ec, arguments, candidate);
+               }
+
                /// <summary>
                ///   Determines if the candidate method, if a params method, is applicable
                ///   in its expanded form to the given set of arguments
@@ -4487,6 +4631,16 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               static bool IsApplicable (EmitContext ec, MethodGroupExpr me,
+                                         ArrayList arguments, ref MethodBase candidate)
+               {
+                       if (!me.HasTypeArguments &&
+                           !InferTypeArguments (ec, arguments, ref candidate))
+                               return false;
+
+                       return IsApplicable (ec, arguments, candidate);
+               }
+
                /// <summary>
                ///   Determines if the candidate method is applicable (section 14.4.2.1)
                ///   to the given set of arguments
@@ -4542,8 +4696,6 @@ namespace Mono.CSharp {
                        return true;
                }
                
-               
-
                /// <summary>
                ///   Find the Applicable Function Members (7.4.2.1)
                ///
@@ -4561,7 +4713,8 @@ namespace Mono.CSharp {
                ///
                /// </summary>
                public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
-                                                         ArrayList Arguments, Location loc)
+                                                         ArrayList Arguments, bool may_fail,
+                                                         Location loc)
                {
                        MethodBase method = null;
                        Type applicable_type = null;
@@ -4573,6 +4726,8 @@ namespace Mono.CSharp {
                         // and whether it is being considered in its
                         // normal or expanded form
                         //
+                        // false is normal form, true is expanded form
+                        //
                         Hashtable candidate_to_form = new PtrHashtable ();
 
 
@@ -4591,8 +4746,10 @@ namespace Mono.CSharp {
 
                         bool found_applicable = false;
 
-                       foreach (MethodBase candidate in me.Methods){
-                                Type decl_type = candidate.DeclaringType;
+                       MethodBase[] methods = me.Methods;
+
+                       for (int i = 0; i < methods.Length; i++) {
+                                Type decl_type = methods [i].DeclaringType;
 
                                 //
                                 // If we have already found an applicable method
@@ -4604,25 +4761,29 @@ namespace Mono.CSharp {
                                     found_applicable)
                                        continue;
 
-
                                // Check if candidate is applicable (section 14.4.2.1)
-                               if (IsApplicable (ec, Arguments, candidate)) {
+                               if (IsApplicable (ec, me, Arguments, ref methods [i])) {
                                        // Candidate is applicable in normal form
+                                       MethodBase candidate = methods [i];
                                        candidates.Add (candidate);
                                        applicable_type = candidate.DeclaringType;
                                        found_applicable = true;
                                        candidate_to_form [candidate] = false;
-                               } else {
-                                        if (IsParamsMethodApplicable (ec, Arguments, candidate)) {
-                                                // Candidate is applicable in expanded form
-                                                candidates.Add (candidate);
-                                                applicable_type = candidate.DeclaringType;
-                                                found_applicable = true; 
-                                                candidate_to_form [candidate] = true;
-                                        }
+                               } else if (IsParamsMethodApplicable (ec, me, Arguments, ref methods [i])) {
+                                       // Candidate is applicable in expanded form
+                                       MethodBase candidate = methods [i];
+                                       candidates.Add (candidate);
+                                       applicable_type = candidate.DeclaringType;
+                                       found_applicable = true; 
+                                       candidate_to_form [candidate] = true;
                                }
                        }
 
+                       if (Arguments == null)
+                               argument_count = 0;
+                       else
+                               argument_count = Arguments.Count;
+
                         //
                         // Now we actually find the best method
                         //
@@ -4646,37 +4807,61 @@ namespace Mono.CSharp {
                                 method = candidate;
                         }
 
-                       if (Arguments == null)
-                               argument_count = 0;
-                       else
-                               argument_count = Arguments.Count;
-                       
-
                        if (method == null) {
+                               int errors = Report.Errors;
+
                                //
                                // Okay so we have failed to find anything so we
                                // return by providing info about the closest match
                                //
-                               for (int i = 0; i < me.Methods.Length; ++i) {
+                               for (int i = 0; i < methods.Length; ++i) {
 
-                                       MethodBase c = (MethodBase) me.Methods [i];
-                                       ParameterData pd = GetParameterData (c);
+                                       MethodBase c = methods [i];
+                                       if (c == null)
+                                               continue;
 
+                                       ParameterData pd = GetParameterData (c);
                                        if (pd.Count != argument_count)
                                                continue;
 
-                                       VerifyArgumentsCompat (ec, Arguments, argument_count, c, false,
-                                                              null, loc);
+                                       if (!InferTypeArguments (ec, Arguments, ref c))
+                                               continue;
+
+                                       VerifyArgumentsCompat (ec, Arguments, argument_count,
+                                                              c, false, null, loc);
                                         break;
                                }
 
-                                if (!Location.IsNull (loc)) {
-                                        string report_name = me.Name;
-                                        if (report_name == ".ctor")
-                                                report_name = me.DeclaringType.ToString ();
+                               if (Report.Errors > errors)
+                                       return null;
+
+                               string report_name = me.Name;
+                               if (report_name == ".ctor")
+                                       report_name = me.DeclaringType.ToString ();
                                         
-                                        Error_WrongNumArguments (loc, report_name, argument_count);
-                                }
+                               for (int i = 0; i < methods.Length; ++i) {
+
+                                       MethodBase c = methods [i];
+                                       if (c == null)
+                                               continue;
+
+                                       ParameterData pd = GetParameterData (c);
+                                       if (pd.Count != argument_count)
+                                               continue;
+
+                                       if (InferTypeArguments (ec, Arguments, ref c))
+                                               continue;
+
+                                       Report.Error (411, loc, "The type arguments for " +
+                                                     "method `{0}' cannot be infered from " +
+                                                     "the usage. Try specifying the type " +
+                                                     "arguments explicitly.", report_name);
+                                        break;
+                               }
+
+                                if (!may_fail && (errors == Report.Errors))
+                                        Error_WrongNumArguments (loc, report_name,
+                                                                argument_count);
                                 
                                return null;
                        }
@@ -4701,9 +4886,9 @@ namespace Mono.CSharp {
                                // applicable so we debar the params
                                // method.
                                //
-                                if ((IsParamsMethodApplicable (ec, Arguments, candidate) &&
-                                     IsApplicable (ec, Arguments, method)))
-                                        continue;
+                                // if ((IsParamsMethodApplicable (ec, Arguments, candidate) &&
+//                                      IsApplicable (ec, Arguments, method)))
+//                                         continue;
                                 
                                 bool cand_params = (bool) candidate_to_form [candidate];
                                int x = BetterFunction (ec, Arguments,
@@ -4849,6 +5034,238 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               static bool InferType (Type pt, Type at, ref Type[] infered)
+               {
+                       if (pt.IsGenericParameter) {
+                               int pos = pt.GenericParameterPosition;
+
+                               if (infered [pos] == null) {
+                                       Type check = at;
+                                       while (check.IsArray)
+                                               check = check.GetElementType ();
+
+                                       if (pt.Equals (check))
+                                               return false;
+
+                                       infered [pos] = at;
+                                       return true;
+                               }
+
+                               if (infered [pos] != at)
+                                       return false;
+
+                               return true;
+                       }
+
+                       if (!pt.ContainsGenericParameters)
+                               return true;
+
+                       if (at.IsArray) {
+                               if (!pt.IsArray ||
+                                   (at.GetArrayRank () != pt.GetArrayRank ()))
+                                       return false;
+
+                               return InferType (pt.GetElementType (), at.GetElementType (),
+                                                 ref infered);
+                       }
+
+                       if (pt.IsArray) {
+                               if (!at.IsArray ||
+                                   (pt.GetArrayRank () != at.GetArrayRank ()))
+                                       return false;
+
+                               return InferType (pt.GetElementType (), at.GetElementType (),
+                                                 ref infered);
+                       }
+
+                       if (!at.IsGenericInstance)
+                               return false;
+
+                       Type[] at_args = at.GetGenericArguments ();
+                       Type[] pt_args = pt.GetGenericArguments ();
+
+                       if (at_args.Length != pt_args.Length)
+                               return false;
+
+                       Type[] infered_types = new Type [at_args.Length];
+
+                       for (int i = 0; i < at_args.Length; i++)
+                               if (!InferType (pt_args [i], at_args [i], ref infered_types))
+                                       return false;
+
+                       for (int i = 0; i < infered_types.Length; i++)
+                               if (infered_types [i] == null)
+                                       return false;
+
+                       for (int i = 0; i < infered_types.Length; i++) {
+                               if (infered [i] == null) {
+                                       infered [i] = infered_types [i];
+                                       continue;
+                               }
+
+                               if (infered [i] != infered_types [i])
+                                       return false;
+                       }
+
+                       return true;
+               }
+
+               static bool InferParamsTypeArguments (EmitContext ec, ArrayList arguments,
+                                                     ref MethodBase method)
+               {
+                       if ((arguments == null) || !TypeManager.IsGenericMethod (method))
+                               return true;
+
+                       int arg_count;
+                       
+                       if (arguments == null)
+                               arg_count = 0;
+                       else
+                               arg_count = arguments.Count;
+                       
+                       ParameterData pd = GetParameterData (method);
+
+                       int pd_count = pd.Count;
+
+                       if (pd_count == 0)
+                               return false;
+                       
+                       if (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS)
+                               return false;
+                       
+                       if (pd_count - 1 > arg_count)
+                               return false;
+                       
+                       if (pd_count == 1 && arg_count == 0)
+                               return true;
+
+                       Type[] method_args = method.GetGenericArguments ();
+                       Type[] infered_types = new Type [method_args.Length];
+
+                       //
+                       // If we have come this far, the case which
+                       // remains is when the number of parameters is
+                       // less than or equal to the argument count.
+                       //
+                       for (int i = 0; i < pd_count - 1; ++i) {
+                               Argument a = (Argument) arguments [i];
+
+                               if ((a.Expr is NullLiteral) || (a.Expr is MethodGroupExpr))
+                                       continue;
+
+                               Type pt = pd.ParameterType (i);
+                               Type at = a.Type;
+
+                               if (!InferType (pt, at, ref infered_types))
+                                       return false;
+                       }
+
+                       Type element_type = TypeManager.GetElementType (pd.ParameterType (pd_count - 1));
+
+                       for (int i = pd_count - 1; i < arg_count; i++) {
+                               Argument a = (Argument) arguments [i];
+
+                               if ((a.Expr is NullLiteral) || (a.Expr is MethodGroupExpr))
+                                       continue;
+
+                               if (!InferType (element_type, a.Type, ref infered_types))
+                                       return false;
+                       }
+
+                       for (int i = 0; i < infered_types.Length; i++)
+                               if (infered_types [i] == null)
+                                       return false;
+
+                       method = method.BindGenericParameters (infered_types);
+                       return true;
+               }
+
+               public static bool InferTypeArguments (Type[] param_types, Type[] arg_types,
+                                                      ref Type[] infered_types)
+               {
+                       for (int i = 0; i < arg_types.Length; i++) {
+                               if (arg_types [i] == null)
+                                       continue;
+
+                               if (!InferType (param_types [i], arg_types [i],
+                                               ref infered_types))
+                                       return false;
+                       }
+
+                       for (int i = 0; i < infered_types.Length; i++)
+                               if (infered_types [i] == null)
+                                       return false;
+
+                       return true;
+               }
+
+               static bool InferTypeArguments (EmitContext ec, ArrayList arguments,
+                                               ref MethodBase method)
+               {
+                       if (!TypeManager.IsGenericMethod (method))
+                               return true;
+
+                       int arg_count;
+                       if (arguments != null)
+                               arg_count = arguments.Count;
+                       else
+                               arg_count = 0;
+
+                       ParameterData pd = GetParameterData (method);
+                       if (arg_count != pd.Count)
+                               return false;
+
+                       Type[] method_args = method.GetGenericArguments ();
+                       Type[] infered_types = new Type [method_args.Length];
+
+                       Type[] param_types = new Type [pd.Count];
+                       Type[] arg_types = new Type [pd.Count];
+
+                       for (int i = 0; i < arg_count; i++) {
+                               param_types [i] = pd.ParameterType (i);
+
+                               Argument a = (Argument) arguments [i];
+                               if ((a.Expr is NullLiteral) || (a.Expr is MethodGroupExpr))
+                                       continue;
+
+                               arg_types [i] = a.Type;
+                       }
+
+                       if (!InferTypeArguments (param_types, arg_types, ref infered_types))
+                               return false;
+
+                       method = method.BindGenericParameters (infered_types);
+                       return true;
+               }
+
+               public static bool InferTypeArguments (EmitContext ec, ParameterData apd,
+                                                      ref MethodBase method)
+               {
+                       if (!TypeManager.IsGenericMethod (method))
+                               return true;
+
+                       ParameterData pd = GetParameterData (method);
+                       if (apd.Count != pd.Count)
+                               return false;
+
+                       Type[] method_args = method.GetGenericArguments ();
+                       Type[] infered_types = new Type [method_args.Length];
+
+                       Type[] param_types = new Type [pd.Count];
+                       Type[] arg_types = new Type [pd.Count];
+
+                       for (int i = 0; i < apd.Count; i++) {
+                               param_types [i] = pd.ParameterType (i);
+                               arg_types [i] = apd.ParameterType (i);
+                       }
+
+                       if (!InferTypeArguments (param_types, arg_types, ref infered_types))
+                               return false;
+
+                       method = method.BindGenericParameters (infered_types);
+                       return true;
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        //
@@ -4858,6 +5275,9 @@ namespace Mono.CSharp {
                        if (expr is BaseAccess)
                                is_base = true;
 
+                       if (expr is ConstructedType)
+                               expr = ((ConstructedType) expr).GetMemberAccess (ec);
+
                        expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
                        if (expr == null)
                                return null;
@@ -4889,13 +5309,10 @@ namespace Mono.CSharp {
                        }
 
                        MethodGroupExpr mg = (MethodGroupExpr) expr;
-                       method = OverloadResolve (ec, mg, Arguments, loc);
+                       method = OverloadResolve (ec, mg, Arguments, false, loc);
 
-                       if (method == null){
-                               Error (-6,
-                                      "Could not find any applicable function for this argument list");
+                       if (method == null)
                                return null;
-                       }
 
                        MethodInfo mi = method as MethodInfo;
                        if (mi != null) {
@@ -4938,19 +5355,15 @@ namespace Mono.CSharp {
                        int count = arguments.Count - idx;
                        Argument a = (Argument) arguments [idx];
                        Type t = a.Expr.Type;
-                       string array_type = t.FullName + "[]";
-                       LocalBuilder array;
 
-                       array = ig.DeclareLocal (TypeManager.LookupType (array_type));
                        IntConstant.EmitInt (ig, count);
                        ig.Emit (OpCodes.Newarr, TypeManager.TypeToCoreType (t));
-                       ig.Emit (OpCodes.Stloc, array);
 
                        int top = arguments.Count;
                        for (int j = idx; j < top; j++){
                                a = (Argument) arguments [j];
                                
-                               ig.Emit (OpCodes.Ldloc, array);
+                               ig.Emit (OpCodes.Dup);
                                IntConstant.EmitInt (ig, j - idx);
 
                                bool is_stobj, has_type_arg;
@@ -4965,7 +5378,6 @@ namespace Mono.CSharp {
                                else
                                        ig.Emit (op);
                        }
-                       ig.Emit (OpCodes.Ldloc, array);
                }
                
                /// <summary>
@@ -5052,6 +5464,7 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
                        bool struct_call = false;
+                       bool this_call = false;
 
                        Type decl_type = method.DeclaringType;
 
@@ -5091,20 +5504,20 @@ namespace Mono.CSharp {
                                // If this is ourselves, push "this"
                                //
                                if (instance_expr == null){
+                                       this_call = true;
                                        ig.Emit (OpCodes.Ldarg_0);
                                } else {
+                                       Type itype = instance_expr.Type;
+
                                        //
                                        // Push the instance expression
                                        //
-                                       if (TypeManager.IsValueType (instance_expr.Type)){
+                                       if (TypeManager.IsValueType (itype)){
                                                //
                                                // Special case: calls to a function declared in a 
                                                // reference-type with a value-type argument need
                                                // to have their value boxed.  
-
-                                               if (!instance_expr.Type.IsGenericParameter)
-                                                       struct_call = true;
-                                               if (TypeManager.IsValueType (decl_type)){
+                                               if (decl_type.IsValueType || itype.IsGenericParameter){
                                                        //
                                                        // If the expression implements IMemoryLocation, then
                                                        // we can optimize and use AddressOf on the
@@ -5117,16 +5530,18 @@ namespace Mono.CSharp {
                                                                        AddressOf (ec, AddressOp.LoadStore);
                                                        }
                                                        else {
-                                                               Type t = instance_expr.Type;
-                                                               
                                                                instance_expr.Emit (ec);
-                                                               LocalBuilder temp = ig.DeclareLocal (t);
+                                                               LocalBuilder temp = ig.DeclareLocal (itype);
                                                                ig.Emit (OpCodes.Stloc, temp);
                                                                ig.Emit (OpCodes.Ldloca, temp);
                                                        }
+                                                       if (itype.IsGenericParameter)
+                                                               ig.Emit (OpCodes.Constrained, itype);
+                                                       else
+                                                               struct_call = true;
                                                } else {
                                                        instance_expr.Emit (ec);
-                                                       ig.Emit (OpCodes.Box, instance_expr.Type);
+                                                       ig.Emit (OpCodes.Box, itype);
                                                } 
                                        } else
                                                instance_expr.Emit (ec);
@@ -5134,8 +5549,13 @@ namespace Mono.CSharp {
                        }
 
                        EmitArguments (ec, method, Arguments);
-
-                       if (is_static || struct_call || is_base){
+                       //
+                       // If you have:
+                       // this.DoFoo ();
+                       // and DoFoo is not virtual, you can omit the callvirt,
+                       // because you don't need the null checking behavior.
+                       //
+                       if (is_static || struct_call || is_base || (this_call && !method.IsVirtual)){
                                if (method is MethodInfo) {
                                        ig.Emit (OpCodes.Call, (MethodInfo) method);
                                } else
@@ -5307,6 +5727,7 @@ namespace Mono.CSharp {
                //
                Expression value_target;
                bool value_target_set = false;
+               bool is_type_parameter = false;
                
                public New (Expression requested_type, ArrayList arguments, Location l)
                {
@@ -5384,7 +5805,28 @@ namespace Mono.CSharp {
                                return RequestedType;
                        }
 
-                       if (type.IsInterface || type.IsAbstract){
+                       if (type.IsGenericParameter) {
+                               if (!TypeManager.HasConstructorConstraint (type)) {
+                                       Error (304, String.Format (
+                                                      "Cannot create an instance of the " +
+                                                      "variable type '{0}' because it " +
+                                                      "doesn't have the new() constraint",
+                                                      type));
+                                       return null;
+                               }
+
+                               if ((Arguments != null) && (Arguments.Count != 0)) {
+                                       Error (417, String.Format (
+                                                      "`{0}': cannot provide arguments " +
+                                                      "when creating an instance of a " +
+                                                      "variable type.", type));
+                                       return null;
+                               }
+
+                               is_type_parameter = true;
+                               eclass = ExprClass.Value;
+                               return this;
+                       } else if (type.IsInterface || type.IsAbstract){
                                Error (144, "It is not possible to create instances of interfaces or abstract classes");
                                return null;
                        }
@@ -5422,7 +5864,8 @@ namespace Mono.CSharp {
                                        }
                                }
 
-                               method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, Arguments, loc);
+                               method = Invocation.OverloadResolve (
+                                       ec, (MethodGroupExpr) ml, Arguments, false, loc);
                                
                        }
 
@@ -5438,6 +5881,18 @@ namespace Mono.CSharp {
                        return this;
                }
 
+               bool DoEmitTypeParameter (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       ig.Emit (OpCodes.Ldtoken, type);
+                       ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
+                       ig.Emit (OpCodes.Call, TypeManager.activator_create_instance);
+                       ig.Emit (OpCodes.Unbox_Any, type);
+
+                       return true;
+               }
+
                //
                // This DoEmit can be invoked in two contexts:
                //    * As a mechanism that will leave a value on the stack (new object)
@@ -5501,17 +5956,26 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       DoEmit (ec, true);
+                       if (is_type_parameter)
+                               DoEmitTypeParameter (ec);
+                       else
+                               DoEmit (ec, true);
                }
                
                public override void EmitStatement (EmitContext ec)
                {
+                       if (is_type_parameter)
+                               throw new InvalidOperationException ();
+
                        if (DoEmit (ec, false))
                                ec.ig.Emit (OpCodes.Pop);
                }
 
                public void AddressOf (EmitContext ec, AddressOp Mode)
                {
+                       if (is_type_parameter)
+                               throw new InvalidOperationException ();
+
                        if (!type.IsValueType){
                                //
                                // We throw an exception.  So far, I believe we only need to support
@@ -5696,9 +6160,14 @@ namespace Mono.CSharp {
                                        if (conv == null) 
                                                return false;
 
-                                       if (conv is StringConstant)
+                                       if (conv is StringConstant || conv is DecimalConstant || conv is NullCast) {
+                                               // These are subclasses of Constant that can appear as elements of an
+                                               // array that cannot be statically initialized (with num_automatic_initializers
+                                               // > max_automatic_initializers), so num_automatic_initializers should be left as zero.
                                                array_data.Add (conv);
-                                       else if (conv is Constant) {
+                                       } else if (conv is Constant) {
+                                               // These are the types of Constant that can appear in arrays that can be
+                                               // statically allocated.
                                                array_data.Add (conv);
                                                num_automatic_initializers++;
                                        } else
@@ -5920,7 +6389,8 @@ namespace Mono.CSharp {
                                        return null;
                                }
                                
-                               new_method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, arguments, loc);
+                               new_method = Invocation.OverloadResolve (
+                                       ec, (MethodGroupExpr) ml, arguments, false, loc);
 
                                if (new_method == null) {
                                        Error (-6, "New invocation: Can not find a constructor for " +
@@ -5931,7 +6401,7 @@ namespace Mono.CSharp {
                                eclass = ExprClass.Value;
                                return this;
                        } else {
-                               ModuleBuilder mb = CodeGen.ModuleBuilder;
+                               ModuleBuilder mb = CodeGen.Module.Builder;
                                ArrayList args = new ArrayList ();
                                
                                if (arguments != null) {
@@ -6138,16 +6608,13 @@ namespace Mono.CSharp {
                        int dims = bounds.Count;
                        int [] current_pos = new int [dims];
                        int top = array_data.Count;
-                       LocalBuilder temp = ig.DeclareLocal (type);
-
-                       ig.Emit (OpCodes.Stloc, temp);
 
                        MethodInfo set = null;
 
                        if (dims != 1){
                                Type [] args;
                                ModuleBuilder mb = null;
-                               mb = CodeGen.ModuleBuilder;
+                               mb = CodeGen.Module.Builder;
                                args = new Type [dims + 1];
 
                                int j;
@@ -6182,7 +6649,8 @@ namespace Mono.CSharp {
                                            num_automatic_initializers <= max_automatic_initializers) {
                                                Type etype = e.Type;
                                                
-                                               ig.Emit (OpCodes.Ldloc, temp);
+                                               if (is_expression || i != top - 1)
+                                                       ig.Emit (OpCodes.Dup);
 
                                                for (int idx = 0; idx < dims; idx++) 
                                                        IntConstant.EmitInt (ig, current_pos [idx]);
@@ -6208,10 +6676,7 @@ namespace Mono.CSharp {
                                                        ig.Emit (OpCodes.Ldelema, etype);
                                                }
 
-                                               ig.Emit (OpCodes.Nop);
                                                e.Emit (ec);
-                                               ig.Emit (OpCodes.Nop);
-                                               ig.Emit (OpCodes.Nop);
 
                                                 if (dims == 1)
                                                         ArrayAccess.EmitStoreOpcode (ig, array_element_type);
@@ -6231,9 +6696,6 @@ namespace Mono.CSharp {
                                        current_pos [j] = 0;
                                }
                        }
-
-                       if (is_expression)
-                               ig.Emit (OpCodes.Ldloc, temp);
                }
 
                void EmitArrayArguments (EmitContext ec)
@@ -6271,12 +6733,11 @@ namespace Mono.CSharp {
                                // 
                                bool dynamic_initializers = true;
 
-                               if (underlying_type != TypeManager.string_type &&
-                                   underlying_type != TypeManager.decimal_type &&
-                                   underlying_type != TypeManager.object_type) {
+                               // This will never be true for array types that cannot be statically
+                               // initialized. num_automatic_initializers will always be zero.  See
+                               // CheckIndices.
                                        if (num_automatic_initializers > max_automatic_initializers)
                                                EmitStaticInitializers (ec, dynamic_initializers || !is_statement);
-                               }
                                
                                if (dynamic_initializers)
                                        EmitDynamicInitializers (ec, !is_statement);
@@ -6320,6 +6781,16 @@ namespace Mono.CSharp {
                        }
                        return ret;
                }
+
+               public Expression TurnIntoConstant ()
+               {
+                       //
+                       // Should use something like the above attribute thing.
+                       // It should return a subclass of Constant that just returns
+                       // the computed value of the array
+                       //
+                       throw new Exception ("Does not support yet Turning array into a Constant");
+               }
        }
        
        /// <summary>
@@ -6356,7 +6827,11 @@ namespace Mono.CSharp {
                public bool ResolveBase (EmitContext ec)
                {
                        eclass = ExprClass.Variable;
-                       type = ec.ContainerType;
+
+                       if (ec.TypeContainer.CurrentType != null)
+                               type = ec.TypeContainer.CurrentType.ResolveType (ec);
+                       else
+                               type = ec.ContainerType;
 
                        if (ec.IsStatic) {
                                Error (26, "Keyword this not valid in static code");
@@ -6409,8 +6884,8 @@ namespace Mono.CSharp {
                public override void Emit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
-                       
-                       ig.Emit (OpCodes.Ldarg_0);
+
+                       ec.EmitThis ();
                        if (ec.TypeContainer is Struct)
                                ig.Emit (OpCodes.Ldobj, type);
                }
@@ -6420,7 +6895,7 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
                        
                        if (ec.TypeContainer is Struct){
-                               ig.Emit (OpCodes.Ldarg_0);
+                               ec.EmitThis ();
                                source.Emit (ec);
                                ig.Emit (OpCodes.Stobj, type);
                        } else {
@@ -6431,7 +6906,7 @@ namespace Mono.CSharp {
 
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
-                       ec.ig.Emit (OpCodes.Ldarg_0);
+                       ec.EmitThis ();
 
                        // FIMXE
                        // FIGURE OUT WHY LDARG_S does not work
@@ -6584,8 +7059,9 @@ namespace Mono.CSharp {
        ///   Implements the member access expression
        /// </summary>
        public class MemberAccess : Expression {
-               public readonly string Identifier;
-               Expression expr;
+               public string Identifier;
+               protected Expression expr;
+               protected TypeArguments args;
                
                public MemberAccess (Expression expr, string id, Location l)
                {
@@ -6594,6 +7070,13 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               public MemberAccess (Expression expr, string id, TypeArguments args,
+                                    Location l)
+                       : this (expr, id, l)
+               {
+                       this.args = args;
+               }
+
                public Expression Expr {
                        get {
                                return expr;
@@ -6618,7 +7101,7 @@ namespace Mono.CSharp {
 
                        SimpleName sn = (SimpleName) left_original;
 
-                       Type t = RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc);
+                       TypeExpr t = RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc);
                        if (t != null)
                                return true;
 
@@ -6654,10 +7137,10 @@ namespace Mono.CSharp {
                                        Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
                                        
                                        if (c != null) {
-                                               object o = c.LookupConstantValue ();
-                                               if (o == null)
+                                               object o;
+                                               if (!c.LookupConstantValue (out o))
                                                        return null;
-                                               
+
                                                object real_value = ((Constant) c.Expr).GetValue ();
 
                                                return Constantify (real_value, fi.FieldType);
@@ -6843,8 +7326,10 @@ namespace Mono.CSharp {
                        // it will fail to find any members at all
                        //
 
-                       Type expr_type = expr.Type;
+                       Type expr_type;
                        if (expr is TypeExpr){
+                               expr_type = ((TypeExpr) expr).ResolveType (ec);
+
                                if (!ec.DeclSpace.CheckAccessLevel (expr_type)){
                                        Error (122, "`" + expr_type + "' " +
                                               "is inaccessible because of its protection level");
@@ -6863,7 +7348,8 @@ namespace Mono.CSharp {
                                                }
                                        }
                                }
-                       }
+                       } else
+                               expr_type = expr.Type;
                        
                        if (expr_type.IsPointer){
                                Error (23, "The `.' operator can not be applied to pointer operands (" +
@@ -6871,10 +7357,21 @@ namespace Mono.CSharp {
                                return null;
                        }
 
+                       int errors = Report.Errors;
+
                        Expression member_lookup;
-                       member_lookup = MemberLookupFinal (ec, expr_type, expr_type, Identifier, loc);
-                       if (member_lookup == null)
+                       member_lookup = MemberLookup (
+                               ec, expr_type, expr_type, Identifier, loc);
+                       if ((member_lookup == null) && (args != null)) {
+                               string lookup_id = Identifier + "!" + args.Count;
+                               member_lookup = MemberLookup (
+                                       ec, expr_type, expr_type, lookup_id, loc);
+                       }
+                       if (member_lookup == null) {
+                               MemberLookupFailed (
+                                       ec, expr_type, expr_type, Identifier, null, loc);
                                return null;
+                       }
 
                        if (member_lookup is TypeExpr) {
                                if (!(expr is TypeExpr) && !(expr is SimpleName)) {
@@ -6885,11 +7382,84 @@ namespace Mono.CSharp {
 
                                return member_lookup;
                        }
+
+                       if (args != null) {
+                               string full_name = expr_type + "." + Identifier;
+
+                               if (member_lookup is FieldExpr) {
+                                       Report.Error (307, loc, "The field `{0}' cannot " +
+                                                     "be used with type arguments", full_name);
+                                       return null;
+                               } else if (member_lookup is EventExpr) {
+                                       Report.Error (307, loc, "The event `{0}' cannot " +
+                                                     "be used with type arguments", full_name);
+                                       return null;
+                               } else if (member_lookup is PropertyExpr) {
+                                       Report.Error (307, loc, "The property `{0}' cannot " +
+                                                     "be used with type arguments", full_name);
+                                       return null;
+                               }
+                       }
                        
                        member_lookup = ResolveMemberAccess (ec, member_lookup, expr, loc, original);
                        if (member_lookup == null)
                                return null;
 
+                       if (args != null) {
+                               MethodGroupExpr mg = member_lookup as MethodGroupExpr;
+                               if (mg == null)
+                                       throw new InternalErrorException ();
+
+                               if (args.Resolve (ec) == false)
+                                       return null;
+
+                               Type[] atypes = args.Arguments;
+
+                               int first_count = 0;
+                               MethodInfo first = null;
+
+                               ArrayList list = new ArrayList ();
+                               foreach (MethodBase mb in mg.Methods) {
+                                       MethodInfo mi = mb as MethodInfo;
+                                       if ((mi == null) || !mi.HasGenericParameters)
+                                               continue;
+
+                                       Type[] gen_params = mi.GetGenericArguments ();
+
+                                       if (first == null) {
+                                               first = mi;
+                                               first_count = gen_params.Length;
+                                       }
+
+                                       if (gen_params.Length != atypes.Length)
+                                               continue;
+
+                                       list.Add (mi.BindGenericParameters (atypes));
+                               }
+
+                               if (list.Count > 0) {
+                                       MethodGroupExpr new_mg = new MethodGroupExpr (
+                                               list, mg.Location);
+                                       new_mg.InstanceExpression = mg.InstanceExpression;
+                                       new_mg.HasTypeArguments = true;
+                                       return new_mg;
+                               }
+
+                               string name = expr_type + "." + Identifier;
+
+                               if (first != null)
+                                       Report.Error (
+                                               305, loc, "Using the generic method `{0}' " +
+                                               "requires {1} type arguments", name,
+                                               first_count);
+                               else
+                                       Report.Error (
+                                               308, loc, "The non-generic method `{0}' " +
+                                               "cannot be used with type arguments", name);
+
+                               return null;
+                       }
+
                        // The following DoResolve/DoResolveLValue will do the definite assignment
                        // check.
 
@@ -6946,25 +7516,52 @@ namespace Mono.CSharp {
                                return new_expr.ResolveAsTypeStep (ec);
                        }
 
-                       Type expr_type = new_expr.Type;
-                     
+                       Type expr_type = ((TypeExpr) new_expr).ResolveType (ec);
+
                        if (expr_type.IsPointer){
                                Error (23, "The `.' operator can not be applied to pointer operands (" +
                                       TypeManager.CSharpName (expr_type) + ")");
                                return null;
                        }
-                       
+
                        Expression member_lookup;
-                       member_lookup = MemberLookupFinal (ec, expr_type, expr_type, Identifier, loc);
+                       string lookup_id;
+                       if (args != null)
+                               lookup_id = Identifier + "!" + args.Count;
+                       else
+                               lookup_id = Identifier;
+                       member_lookup = MemberLookupFinal (
+                               ec, expr_type, expr_type, lookup_id, loc);
                        if (member_lookup == null)
                                return null;
 
-                       if (member_lookup is TypeExpr){
-                               member_lookup.Resolve (ec, ResolveFlags.Type);
-                               return member_lookup;
-                       } 
+                       TypeExpr texpr = member_lookup as TypeExpr;
+                       if (texpr == null)
+                               return null;
+
+                       Type t = texpr.ResolveType (ec);
+                       if (t == null)
+                               return null;
+
+                       if (TypeManager.HasGenericArguments (expr_type)) {
+                               Type[] decl_args = TypeManager.GetTypeArguments (expr_type);
+
+                               TypeArguments new_args = new TypeArguments (loc);
+                               foreach (Type decl in decl_args)
+                                       new_args.Add (new TypeExpression (decl, loc));
+
+                               if (args != null)
+                                       new_args.Add (args);
+
+                               args = new_args;
+                       }
 
-                       return null;                    
+                       if (args != null) {
+                               ConstructedType ctype = new ConstructedType (t, args, loc);
+                               return ctype.ResolveAsTypeStep (ec);
+                       }
+
+                       return texpr;
                }
 
                public override void Emit (EmitContext ec)
@@ -6974,7 +7571,10 @@ namespace Mono.CSharp {
 
                public override string ToString ()
                {
-                       return expr + "." + Identifier;
+                       if (args != null)
+                               return expr + "." + Identifier + "!" + args.Count;
+                       else
+                               return expr + "." + Identifier;
                }
        }
 
@@ -7282,7 +7882,9 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Ldelem_R8);
                        else if (type == TypeManager.intptr_type)
                                ig.Emit (OpCodes.Ldelem_I);
-                       else if (type.IsValueType){
+                       else if (TypeManager.IsEnumType (type)){
+                               EmitLoadOpcode (ig, TypeManager.EnumToUnderlying (type));
+                       } else if (type.IsValueType){
                                ig.Emit (OpCodes.Ldelema, type);
                                ig.Emit (OpCodes.Ldobj, type);
                        } else if (type.IsGenericParameter)
@@ -7347,7 +7949,7 @@ namespace Mono.CSharp {
 
                MethodInfo FetchGetMethod ()
                {
-                       ModuleBuilder mb = CodeGen.ModuleBuilder;
+                       ModuleBuilder mb = CodeGen.Module.Builder;
                        int arg_count = ea.Arguments.Count;
                        Type [] args = new Type [arg_count];
                        MethodInfo get;
@@ -7368,7 +7970,7 @@ namespace Mono.CSharp {
 
                MethodInfo FetchAddressMethod ()
                {
-                       ModuleBuilder mb = CodeGen.ModuleBuilder;
+                       ModuleBuilder mb = CodeGen.Module.Builder;
                        int arg_count = ea.Arguments.Count;
                        Type [] args = new Type [arg_count];
                        MethodInfo address;
@@ -7491,7 +8093,7 @@ namespace Mono.CSharp {
                        if (rank == 1)
                                EmitStoreOpcode (ig, t);
                        else {
-                               ModuleBuilder mb = CodeGen.ModuleBuilder;
+                               ModuleBuilder mb = CodeGen.Module.Builder;
                                int arg_count = ea.Arguments.Count;
                                Type [] args = new Type [arg_count + 1];
                                MethodInfo set;
@@ -7693,7 +8295,8 @@ namespace Mono.CSharp {
                        if (AllGetters.Count > 0) {
                                found_any_getters = true;
                                get = (MethodInfo) Invocation.OverloadResolve (
-                                       ec, new MethodGroupExpr (AllGetters, loc), arguments, loc);
+                                       ec, new MethodGroupExpr (AllGetters, loc),
+                                       arguments, false, loc);
                        }
 
                        if (!found_any) {
@@ -7757,7 +8360,7 @@ namespace Mono.CSharp {
                                set_arguments.Add (new Argument (right_side, Argument.AType.Expression));
                                set = (MethodInfo) Invocation.OverloadResolve (
                                        ec, new MethodGroupExpr (AllSetters, loc),
-                                       set_arguments, loc);
+                                       set_arguments, false, loc);
                        }
 
                        if (!found_any) {
@@ -7872,11 +8475,18 @@ namespace Mono.CSharp {
                                Error (1511, "Keyword base is not allowed in static method");
                                return null;
                        }
+
+                       if (ec.IsFieldInitializer){
+                               Error (1512, "Keyword base is not available in the current context");
+                               return null;
+                       }
                        
-                       member_lookup = MemberLookup (ec, ec.ContainerType, null, base_type, member,
-                                                     AllMemberTypes, AllBindingFlags, loc);
+                       member_lookup = MemberLookup (ec, ec.ContainerType, null, base_type,
+                                                     member, AllMemberTypes, AllBindingFlags,
+                                                     loc);
                        if (member_lookup == null) {
-                               MemberLookupFailed (ec, base_type, base_type, member, null, loc);
+                               MemberLookupFailed (
+                                       ec, base_type, base_type, member, null, loc);
                                return null;
                        }
 
@@ -8039,6 +8649,7 @@ namespace Mono.CSharp {
                        int pos = 0;
                        while ((pos < dim.Length) && (dim [pos] == '[')) {
                                pos++;
+
                                if (dim [pos] == ']') {
                                        ltype = ltype.MakeArrayType ();
                                        pos++;
@@ -8052,8 +8663,9 @@ namespace Mono.CSharp {
                                }
 
                                int rank = 0;
-                               while (dim [pos++] == ',')
-                                       rank++;
+                               while (dim [pos] == ',') {
+                                       pos++; rank++;
+                               }
 
                                if ((dim [pos] != ']') || (pos != dim.Length-1))
                                        return null;
@@ -8067,7 +8679,8 @@ namespace Mono.CSharp {
                        // ltype.Fullname is already fully qualified, so we can skip
                        // a lot of probes, and go directly to TypeManager.LookupType
                        //
-                       string cname = ltype.FullName + dim;
+                       string fname = ltype.FullName != null ? ltype.FullName : ltype.Name;
+                       string cname = fname + dim;
                        type = TypeManager.LookupTypeDirect (cname);
                        if (type == null){
                                //
@@ -8076,9 +8689,13 @@ namespace Mono.CSharp {
                                //
                                // For now, fall back to the full lookup in that case.
                                //
-                               type = RootContext.LookupType (
+                               TypeExpr texpr = RootContext.LookupType (
                                        ec.DeclSpace, cname, false, loc);
 
+                               if (texpr == null)
+                                       return null;
+
+                               type = texpr.ResolveType (ec);
                                if (type == null)
                                        return null;
                        }
@@ -8201,7 +8818,8 @@ namespace Mono.CSharp {
                                        return null;
                        }
 
-                       if (ec.InCatch || ec.InFinally){
+                       if (ec.CurrentBranching.InCatch () ||
+                           ec.CurrentBranching.InFinally (true)) {
                                Error (255,
                                              "stackalloc can not be used in a catch or finally block");
                                return null;