**** Merged from MCS ****
[mono.git] / mcs / gmcs / expression.cs
index c47e0578fc01a01ba3bad6929ba088c9805c74d5..cc1983e649309396d74e0a1a9137145e88001b80 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;
@@ -254,16 +255,16 @@ namespace Mono.CSharp {
 
                                        result = null;
                                        if (Convert.ImplicitConversionExists (ec, e, TypeManager.int32_type)){
-                                               result = new Cast (new TypeExpr (TypeManager.int32_type, loc), e, loc);
+                                               result = new Cast (new TypeExpression (TypeManager.int32_type, loc), e, loc);
                                                result = result.Resolve (ec);
                                        } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.uint32_type)){
-                                               result = new Cast (new TypeExpr (TypeManager.uint32_type, loc), e, loc);
+                                               result = new Cast (new TypeExpression (TypeManager.uint32_type, loc), e, loc);
                                                result = result.Resolve (ec);
                                        } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.int64_type)){
-                                               result = new Cast (new TypeExpr (TypeManager.int64_type, loc), e, loc);
+                                               result = new Cast (new TypeExpression (TypeManager.int64_type, loc), e, loc);
                                                result = result.Resolve (ec);
                                        } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.uint64_type)){
-                                               result = new Cast (new TypeExpr (TypeManager.uint64_type, loc), e, loc);
+                                               result = new Cast (new TypeExpression (TypeManager.uint64_type, loc), e, loc);
                                                result = result.Resolve (ec);
                                        }
 
@@ -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))
@@ -562,18 +568,36 @@ namespace Mono.CSharp {
                        return ResolveOperator (ec);
                }
 
+               public override Expression DoResolveLValue (EmitContext ec, Expression right)
+               {
+                       if (Oper == Operator.Indirection)
+                               return base.DoResolveLValue (ec, right);
+
+                       Error (131, "The left-hand side of an assignment must be a " +
+                              "variable, property or indexer");
+                       return null;
+               }
+
                public override void Emit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
-                       Type expr_type = Expr.Type;
                        
                        switch (Oper) {
                        case Operator.UnaryPlus:
                                throw new Exception ("This should be caught by Resolve");
                                
                        case Operator.UnaryNegation:
+                               if (ec.CheckState) {
+                                       ig.Emit (OpCodes.Ldc_I4_0);
+                                       if (type == TypeManager.int64_type)
+                                               ig.Emit (OpCodes.Conv_U8);
+                                       Expr.Emit (ec);
+                                       ig.Emit (OpCodes.Sub_Ovf);
+                               } else {
                                Expr.Emit (ec);
                                ig.Emit (OpCodes.Neg);
+                               }
+                               
                                break;
                                
                        case Operator.LogicalNot:
@@ -597,16 +621,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 ()
@@ -643,14 +663,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);
                        
@@ -967,6 +987,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
@@ -975,7 +1002,8 @@ namespace Mono.CSharp {
                                // For now: only localvariables when not remapped
                                //
 
-                               if (method == null && (expr is FieldExpr && ((FieldExpr) expr).FieldInfo.IsStatic)){
+                               if (method == null &&
+                                   ((expr is LocalVariableReference) ||(expr is FieldExpr && ((FieldExpr) expr).FieldInfo.IsStatic))){
                                        if (empty_expr == null)
                                                empty_expr = new EmptyExpression ();
                                        
@@ -1041,6 +1069,8 @@ namespace Mono.CSharp {
                                ia.EmitAssign (ec, temp_storage);
                                break;
                        }
+
+                       temp_storage.Release (ec);
                }
 
                public override void Emit (EmitContext ec)
@@ -1089,6 +1119,8 @@ namespace Mono.CSharp {
                        if (probe_type == null)
                                return null;
 
+                       CheckObsoleteAttribute (probe_type);
+
                        expr = expr.Resolve (ec);
                        if (expr == null)
                                return null;
@@ -1143,6 +1175,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);
@@ -1241,7 +1302,7 @@ namespace Mono.CSharp {
 
                        if (TypeManager.IsValueType (probe_type)){
                                Report.Error (77, loc, "The as operator should be used with a reference type only (" +
-                                             TypeManager.CSharpName (probe_type) + " is a value type");
+                                             TypeManager.CSharpName (probe_type) + " is a value type)");
                                return null;
                        
                        }
@@ -1719,9 +1780,9 @@ namespace Mono.CSharp {
                        if (real_expr is DoubleConstant){
                                double v = ((DoubleConstant) real_expr).Value;
        
-                               if (target_type == TypeManager.byte_type)
+                               if (target_type == TypeManager.byte_type){
                                        return new ByteConstant ((byte) v);
-                               if (target_type == TypeManager.sbyte_type)
+                               if (target_type == TypeManager.sbyte_type)
                                        return new SByteConstant ((sbyte) v);
                                if (target_type == TypeManager.short_type)
                                        return new ShortConstant ((short) v);
@@ -1791,13 +1852,13 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return null;
 
-                       int errors = Report.Errors;
-
                        type = ec.DeclSpace.ResolveType (target_type, false, Location);
                        
                        if (type == null)
                                return null;
 
+                       CheckObsoleteAttribute (type);
+
                        eclass = ExprClass.Value;
 
                        if (expr is Constant){
@@ -1807,6 +1868,10 @@ namespace Mono.CSharp {
                                        return e;
                        }
 
+                       if (type.IsPointer && !ec.InUnsafe) {
+                               UnsafeError (loc);
+                               return null;
+                       }
                        expr = Convert.ExplicitConversion (ec, expr, type, loc);
                        return expr;
                }
@@ -2042,7 +2107,7 @@ namespace Mono.CSharp {
                                                } else if (right is LongConstant){
                                                        long ll = ((LongConstant) right).Value;
 
-                                                       if (ll > 0)
+                                                       if (ll >= 0)
                                                                right = new ULongConstant ((ulong) ll);
                                                } else {
                                                        e = Convert.ImplicitNumericConversion (ec, right, l, loc);
@@ -2090,7 +2155,7 @@ namespace Mono.CSharp {
                                //
                                // If either operand is of type uint, and the other
                                // operand is of type sbyte, short or int, othe operands are
-                               // converted to type long.
+                               // converted to type long (unless we have an int constant).
                                //
                                Type other = null;
                                
@@ -2167,12 +2232,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 ||
@@ -2187,12 +2246,32 @@ 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)
                {
                        Expression e;
-                       Type l = left.Type;
-                       Type r = right.Type;
 
                        e = ForceConversion (ec, right, TypeManager.int32_type);
                        if (e == null){
@@ -2208,6 +2287,14 @@ namespace Mono.CSharp {
                                left = e;
                                type = e.Type;
 
+                               if (type == TypeManager.int32_type || type == TypeManager.uint32_type){
+                                       right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (31), loc);
+                                       right = right.DoResolve (ec);
+                               } else {
+                                       right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (63), loc);
+                                       right = right.DoResolve (ec);
+                               }
+
                                return this;
                        }
                        Error_OperatorCannotBeApplied ();
@@ -2222,7 +2309,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)) ||
@@ -2231,6 +2318,35 @@ 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;
+                               }
+                               
+                               // IntPtr equality
+                               if (l == TypeManager.intptr_type && r == TypeManager.intptr_type) {
+                                       Type = TypeManager.bool_type;
+                                       
+                                       return this;
+                               }
                        }
 
                        //
@@ -2259,7 +2375,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;
                                                
@@ -2270,10 +2388,6 @@ namespace Mono.CSharp {
                                }
                        }
                        
-                       //
-                       // Step 2: Default operations on CLI native types.
-                       //
-
                        //
                        // Step 0: String concatenation (because overloading will get this wrong)
                        //
@@ -2282,89 +2396,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){
-                                                               ArrayList bargs = b.Arguments;
-                                                               int count = bargs.Count;
-                                                               
-                                                               if (count == 2){
-                                                                       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){
-                                                                       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 4 arguments
-                                       //
-                                       ArrayList args = new ArrayList (4);
-                                       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);
                                }
 
                                //
@@ -2446,8 +2506,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);
                                        
@@ -2467,6 +2535,7 @@ namespace Mono.CSharp {
 
                                        return new BinaryDelegate (l, method, args);
                                }
+                               }
 
                                //
                                // Pointer arithmetic:
@@ -2494,12 +2563,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);
+                               }
                        }
                        
                        //
@@ -2511,7 +2584,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;
@@ -2519,6 +2593,7 @@ namespace Mono.CSharp {
                                        Error_OperatorCannotBeApplied ();
                                        return null;
                                }
+                               }
                                        
                                //
                                // operator + (E e, U x)
@@ -2528,9 +2603,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;
                                        }
@@ -2652,13 +2736,17 @@ namespace Mono.CSharp {
                            oper == Operator.BitwiseOr ||
                            oper == Operator.ExclusiveOr){
                                if (l == r){
-                                       if (!((l == TypeManager.int32_type) ||
-                                             (l == TypeManager.uint32_type) ||
-                                             (l == TypeManager.short_type) ||
-                                             (l == TypeManager.ushort_type) ||
-                                             (l == TypeManager.int64_type) ||
-                                             (l == TypeManager.uint64_type)))
+                                       if (((l == TypeManager.int32_type) ||
+                                            (l == TypeManager.uint32_type) ||
+                                            (l == TypeManager.short_type) ||
+                                            (l == TypeManager.ushort_type) ||
+                                            (l == TypeManager.int64_type) ||
+                                            (l == TypeManager.uint64_type))){
                                                type = l;
+                                       } else {
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
                                } else {
                                        Error_OperatorCannotBeApplied ();
                                        return null;
@@ -2719,7 +2807,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;
 
@@ -2729,135 +2817,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:
@@ -2901,9 +2931,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);
@@ -2918,8 +2945,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);
@@ -2931,82 +2956,53 @@ 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)
                {
                        ILGenerator ig = ec.ig;
                        Type l = left.Type;
-                       Type r = right.Type;
                        OpCode opcode;
 
                        //
                        // 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);
                                return;
                        }
-                       
+
                        left.Emit (ec);
                        right.Emit (ec);
 
                        bool isUnsigned = is_unsigned (left.Type);
-
+                       
                        switch (oper){
                        case Operator.Multiply:
                                if (ec.CheckState){
@@ -3115,9 +3111,9 @@ namespace Mono.CSharp {
                                else
                                        ig.Emit (OpCodes.Clt);
                                
-                               ig.Emit (OpCodes.Ldc_I4_1);
+                               ig.Emit (OpCodes.Ldc_I4_0);
                                
-                               opcode = OpCodes.Sub;
+                               opcode = OpCodes.Ceq;
                                break;
 
                        case Operator.BitwiseOr:
@@ -3177,34 +3173,165 @@ namespace Mono.CSharp {
        }
 
        //
-       // Object created with +/= on delegates
+       // Represents the operation a + b [+ c [+ d [+ ...]]], where a is a string
+       // b, c, d... may be strings or objects.
        //
-       public class BinaryDelegate : Expression {
-               MethodInfo method;
-               ArrayList  args;
-
-               public BinaryDelegate (Type t, MethodInfo mi, ArrayList args)
+       public class StringConcat : Expression {
+               ArrayList operands;
+               bool invalid = false;
+               
+               
+               public StringConcat (EmitContext ec, Location loc, Expression left, Expression right)
                {
-                       method = mi;
-                       this.args = args;
-                       type = t;
+                       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 override void Emit (EmitContext ec)
+               
+               public void Append (EmitContext ec, Expression operand)
                {
-                       ILGenerator ig = ec.ig;
-                       
-                       Invocation.EmitArguments (ec, method, args);
+                       //
+                       // 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;
+                               }
+                       }
                        
-                       ig.Emit (OpCodes.Call, (MethodInfo) method);
-                       ig.Emit (OpCodes.Castclass, type);
-               }
+                       //
+                       // 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
+       //
+       public class BinaryDelegate : Expression {
+               MethodInfo method;
+               ArrayList  args;
+
+               public BinaryDelegate (Type t, MethodInfo mi, ArrayList args)
+               {
+                       method = mi;
+                       this.args = args;
+                       type = t;
+                       eclass = ExprClass.Value;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       Invocation.EmitArguments (ec, method, args);
+                       
+                       ig.Emit (OpCodes.Call, (MethodInfo) method);
+                       ig.Emit (OpCodes.Castclass, type);
+               }
 
                public Expression Right {
                        get {
@@ -3248,6 +3375,7 @@ namespace Mono.CSharp {
                }
 
                Expression op_true, op_false, op;
+               LocalTemporary left_temp;
 
                public override Expression DoResolve (EmitContext ec)
                {
@@ -3260,10 +3388,14 @@ namespace Mono.CSharp {
                                return null;
                        }
 
+                       left_temp = new LocalTemporary (ec, type);
+
                        ArrayList arguments = new ArrayList ();
-                       arguments.Add (new Argument (left, Argument.AType.Expression));
+                       arguments.Add (new Argument (left_temp, 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;
@@ -3271,8 +3403,8 @@ namespace Mono.CSharp {
 
                        op = new StaticCallExpr (method, arguments, loc);
 
-                       op_true = GetOperatorTrue (ec, left, loc);
-                       op_false = GetOperatorFalse (ec, left, loc);
+                       op_true = GetOperatorTrue (ec, left_temp, loc);
+                       op_false = GetOperatorFalse (ec, left_temp, loc);
                        if ((op_true == null) || (op_false == null)) {
                                Error218 ();
                                return null;
@@ -3289,8 +3421,11 @@ namespace Mono.CSharp {
 
                        ig.Emit (OpCodes.Nop);
 
-                       Statement.EmitBoolExpression (ec, is_and ? op_false : op_true, false_target, false);
                        left.Emit (ec);
+                       left_temp.Store (ec);
+
+                       (is_and ? op_false : op_true).EmitBranchable (ec, false_target, false);
+                       left_temp.Emit (ec);
                        ig.Emit (OpCodes.Br, end_target);
                        ig.MarkLabel (false_target);
                        op.Emit (ec);
@@ -3493,7 +3628,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);
@@ -3554,10 +3689,8 @@ namespace Mono.CSharp {
 #endif
                }
                
-               public override Expression DoResolve (EmitContext ec)
+               protected Expression DoResolve (EmitContext ec, bool is_lvalue)
                {
-                       DoResolveBase (ec);
-
                        Expression e = Block.GetConstantExpression (Name);
                        if (e != null) {
                                local_info.Used = true;
@@ -3569,12 +3702,22 @@ namespace Mono.CSharp {
                        if ((variable_info != null) && !variable_info.IsAssigned (ec, loc))
                                return null;
 
+                       if (!is_lvalue)
+                               local_info.Used = true;
+
                        if (local_info.LocalBuilder == null)
                                return ec.RemapLocal (local_info);
                        
                        return this;
                }
 
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       DoResolveBase (ec);
+
+                       return DoResolve (ec, false);
+               }
+
                override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
                        DoResolveBase (ec);
@@ -3583,7 +3726,7 @@ namespace Mono.CSharp {
                        if (variable_info != null)
                                variable_info.SetAssigned (ec);
 
-                       Expression e = DoResolve (ec);
+                       Expression e = DoResolve (ec, true);
 
                        if (e == null)
                                return null;
@@ -3593,6 +3736,8 @@ namespace Mono.CSharp {
                                return null;
                        }
 
+                       CheckObsoleteAttribute (e.Type);
+
                        if (local_info.LocalBuilder == null)
                                return ec.RemapLocalLValue (local_info, right_side);
                        
@@ -3615,8 +3760,6 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
 
-                       local_info.Assigned = true;
-
                        source.Emit (ec);
                        ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
                }
@@ -3853,7 +3996,8 @@ namespace Mono.CSharp {
                public enum AType : byte {
                        Expression,
                        Ref,
-                       Out
+                       Out,
+                       ArgList
                };
 
                public readonly AType ArgType;
@@ -3890,6 +4034,9 @@ namespace Mono.CSharp {
 
                public static string FullDesc (Argument a)
                {
+                       if (a.ArgType == AType.ArgList)
+                               return "__arglist";
+
                        return (a.ArgType == AType.Ref ? "ref " :
                                (a.ArgType == AType.Out ? "out " : "")) +
                                TypeManager.CSharpName (a.Expr.Type);
@@ -3897,6 +4044,10 @@ namespace Mono.CSharp {
 
                public bool ResolveMethodGroup (EmitContext ec, Location loc)
                {
+                       ConstructedType ctype = Expr as ConstructedType;
+                       if (ctype != null)
+                               Expr = ctype.GetSimpleName (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);
@@ -3924,6 +4075,24 @@ namespace Mono.CSharp {
 
                        if (ArgType == AType.Expression)
                                return true;
+                       else {
+                               //
+                               // Catch errors where fields of a MarshalByRefObject are passed as ref or out
+                               // This is only allowed for `this'
+                               //
+                               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){
                                //
@@ -3969,8 +4138,9 @@ namespace Mono.CSharp {
                                                
                                                pr.AddressOf (ec, mode);
                                        }
-                               } else
+                               } else {
                                        ((IMemoryLocation)Expr).AddressOf (ec, mode);
+                               }
                        } else
                                Expr.Emit (ec);
                }
@@ -4025,15 +4195,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;
@@ -4056,8 +4224,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 &&
@@ -4068,6 +4235,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;
                        
@@ -4132,6 +4318,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)
@@ -4210,10 +4404,32 @@ namespace Mono.CSharp {
 
                        int cand_count = candidate_pd.Count;
 
+                       //
+                       // If there is no best method, than this one
+                       // is better, however, if we already found a
+                       // best method, we cant tell. This happens
+                       // if we have:
+                       // 
+                       //      interface IFoo {
+                       //              void DoIt ();
+                       //      }
+                       //      
+                       //      interface IBar {
+                       //              void DoIt ();
+                       //      }
+                       //      
+                       //      interface IFooBar : IFoo, IBar {}
+                       //
+                       // We cant tell if IFoo.DoIt is better than IBar.DoIt
+                       //
+                       // However, we have to consider that
+                       // Trim (); is better than Trim (params char[] chars);
+                        //
                        if (cand_count == 0 && argument_count == 0)
-                               return 1;
+                               return best == null || best_params ? 1 : 0;
 
-                       if (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS)
+                       if ((candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS) &&
+                           (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.ARGLIST))
                                if (cand_count != argument_count)
                                        return 0;
 
@@ -4295,6 +4511,9 @@ namespace Mono.CSharp {
                {
                        string ret_type = "";
 
+                        if (mb == null)
+                                return "";
+
                        if (mb is MethodInfo)
                                ret_type = TypeManager.CSharpName (((MethodInfo) mb).ReturnType);
                        
@@ -4366,6 +4585,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
@@ -4386,10 +4615,15 @@ namespace Mono.CSharp {
                        if (pd_count == 0)
                                return false;
                        
-                       if (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS)
+                       int count = pd_count - 1;
+
+                       bool is_varargs = false;
+                       if (pd.ParameterModifier (count) == Parameter.Modifier.ARGLIST)
+                               is_varargs = true;
+                       else if (pd.ParameterModifier (count) != Parameter.Modifier.PARAMS)
                                return false;
                        
-                       if (pd_count - 1 > arg_count)
+                       if (count > arg_count)
                                return false;
                        
                        if (pd_count == 1 && arg_count == 0)
@@ -4400,7 +4634,7 @@ namespace Mono.CSharp {
                        // 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) {
+                       for (int i = 0; i < count; ++i) {
 
                                Argument a = (Argument) arguments [i];
 
@@ -4431,6 +4665,9 @@ namespace Mono.CSharp {
                                
                        }
 
+                       if (is_varargs)
+                               return true;
+
                        Type element_type = TypeManager.GetElementType (pd.ParameterType (pd_count - 1));
 
                        for (int i = pd_count - 1; i < arg_count; i++) {
@@ -4443,6 +4680,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
@@ -4459,8 +4706,6 @@ namespace Mono.CSharp {
 
                        ParameterData pd = GetParameterData (candidate);
 
-                       int pd_count = pd.Count;
-
                        if (arg_count != pd.Count)
                                return false;
 
@@ -4500,8 +4745,6 @@ namespace Mono.CSharp {
                        return true;
                }
                
-               
-
                /// <summary>
                ///   Find the Applicable Function Members (7.4.2.1)
                ///
@@ -4519,7 +4762,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;
@@ -4531,6 +4775,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 ();
 
 
@@ -4548,8 +4794,11 @@ 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
@@ -4559,31 +4808,38 @@ namespace Mono.CSharp {
                                     (applicable_type.IsSubclassOf (decl_type) ||
                                      TypeManager.ImplementsInterface (applicable_type, decl_type)) &&
                                     found_applicable)
-                                                continue;
-
+                                       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
                         //
-                        foreach (MethodBase candidate in candidates) {
+                       int candidate_top = candidates.Count;
+                       for (int ix = 0; ix < candidate_top; ix++){
+                               MethodBase candidate = (MethodBase) candidates [ix];
+                               
                                 bool cand_params = (bool) candidate_to_form [candidate];
                                 bool method_params = false;
                                
@@ -4600,37 +4856,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;
                        }
@@ -4641,7 +4921,8 @@ namespace Mono.CSharp {
                        //
                         bool best_params = (bool) candidate_to_form [method];
 
-                       foreach (MethodBase candidate in candidates){
+                       for (int ix = 0; ix < candidate_top; ix++){
+                               MethodBase candidate = (MethodBase) candidates [ix];
 
                                 if (candidate == method)
                                         continue;
@@ -4654,9 +4935,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,
@@ -4732,8 +5013,6 @@ namespace Mono.CSharp {
                                Parameter.Modifier pm = pd.ParameterModifier (j);
                                
                                if (pm == Parameter.Modifier.PARAMS){
-                                       Parameter.Modifier am = a.GetParameterModifier ();
-
                                        if ((pm & ~Parameter.Modifier.PARAMS) != a.GetParameterModifier ()) {
                                                if (!Location.IsNull (loc))
                                                        Error_InvalidArguments (
@@ -4744,6 +5023,8 @@ namespace Mono.CSharp {
 
                                        if (chose_params_expanded)
                                                parameter_type = TypeManager.GetElementType (parameter_type);
+                               } else if (pm == Parameter.Modifier.ARGLIST){
+                                       continue;
                                } else {
                                        //
                                        // Check modifiers
@@ -4766,11 +5047,6 @@ namespace Mono.CSharp {
                                        conv = Convert.ImplicitConversion (ec, a_expr, parameter_type, loc);
 
                                        if (conv == null) {
-                                                Console.WriteLine ("GAA: {0} {1} {2}",
-                                                                   pd.ParameterType (j),
-                                                                   pd.ParameterType (j).Assembly == CodeGen.AssemblyBuilder,
-                                                                   method.DeclaringType.Assembly == CodeGen.AssemblyBuilder);
-
                                                if (!Location.IsNull (loc)) 
                                                        Error_InvalidArguments (
                                                                loc, j, method, delegate_type,
@@ -4809,6 +5085,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)
                {
                        //
@@ -4818,8 +5326,9 @@ namespace Mono.CSharp {
                        if (expr is BaseAccess)
                                is_base = true;
 
-                       Expression old = expr;
-                       
+                       if (expr is ConstructedType)
+                               expr = ((ConstructedType) expr).GetSimpleName (ec);
+
                        expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
                        if (expr == null)
                                return null;
@@ -4851,19 +5360,28 @@ 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) {
                                type = TypeManager.TypeToCoreType (mi.ReturnType);
-                               if (!mi.IsStatic && !mg.IsExplicitImpl && (mg.InstanceExpression == null))
+                               if (!mi.IsStatic && !mg.IsExplicitImpl && (mg.InstanceExpression == null)) {
                                        SimpleName.Error_ObjectRefRequired (ec, loc, mi.Name);
+                                       return null;
+                               }
+
+                               Expression iexpr = mg.InstanceExpression;
+                               if (mi.IsStatic && (iexpr != null) && !(iexpr is This)) {
+                                       if (mg.IdenticalTypeName)
+                                               mg.InstanceExpression = null;
+                                       else {
+                                               MemberAccess.error176 (loc, mi.Name);
+                                               return null;
+                                       }
+                               }
                        }
 
                        if (type.IsPointer){
@@ -4900,34 +5418,29 @@ 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;
-                               OpCode op = ArrayAccess.GetStoreOpcode (t, out is_stobj);
+                               bool is_stobj, has_type_arg;
+                               OpCode op = ArrayAccess.GetStoreOpcode (t, out is_stobj, out has_type_arg);
                                if (is_stobj)
                                        ig.Emit (OpCodes.Ldelema, t);
 
                                a.Emit (ec);
 
-                               if (is_stobj)
-                                       ig.Emit (OpCodes.Stobj, t);
+                               if (has_type_arg)
+                                       ig.Emit (op, t);
                                else
                                        ig.Emit (op);
                        }
-                       ig.Emit (OpCodes.Ldloc, array);
                }
                
                /// <summary>
@@ -4984,13 +5497,47 @@ namespace Mono.CSharp {
                                a.Emit (ec);
                        }
 
-                       if (pd != null && pd.Count > top &&
-                           pd.ParameterModifier (top) == Parameter.Modifier.PARAMS){
-                               ILGenerator ig = ec.ig;
+                       if (pd != null && pd.Count > top &&
+                           pd.ParameterModifier (top) == Parameter.Modifier.PARAMS){
+                               ILGenerator ig = ec.ig;
+
+                               IntConstant.EmitInt (ig, 0);
+                               ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (pd.ParameterType (top)));
+                       }
+               }
+
+               static Type[] GetVarargsTypes (EmitContext ec, MethodBase mb,
+                                              ArrayList arguments)
+               {
+                       ParameterData pd = GetParameterData (mb);
+
+                       if (arguments == null)
+                               return new Type [0];
+
+                       Argument a = (Argument) arguments [pd.Count - 1];
+                       Arglist list = (Arglist) a.Expr;
+
+                       return list.ArgumentTypes;
+               }
+
+               /// <summary>
+               /// This checks the ConditionalAttribute on the method 
+               /// </summary>
+               static bool IsMethodExcluded (MethodBase method, EmitContext ec)
+               {
+                       if (method.IsConstructor)
+                               return false;
+
+                       IMethodData md = TypeManager.GetMethod (method);
+                       if (md != null)
+                               return md.IsExcluded (ec);
 
-                               IntConstant.EmitInt (ig, 0);
-                               ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (pd.ParameterType (top)));
-                       }
+                       // For some methods (generated by delegate class) GetMethod returns null
+                       // because they are not included in builder_to_method table
+                       if (method.DeclaringType is TypeBuilder)
+                               return false;
+
+                       return AttributeTester.IsConditionalMethodExcluded (method);
                }
 
                /// <remarks>
@@ -5014,6 +5561,7 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
                        bool struct_call = false;
+                       bool this_call = false;
 
                        Type decl_type = method.DeclaringType;
 
@@ -5037,35 +5585,47 @@ namespace Mono.CSharp {
                        }
 
                        //
-                       // This checks the `ConditionalAttribute' on the method, and the
-                       // ObsoleteAttribute
+                       // This checks ObsoleteAttribute on the method and on the declaring type
                        //
-                       TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (method, loc);
-                       if ((flags & TypeManager.MethodFlags.IsObsoleteError) != 0)
-                               return;
-                       if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
+                       ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (method);
+                       if (oa != null)
+                               AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (method), loc);
+
+                       oa = AttributeTester.GetObsoleteAttribute (method.DeclaringType);
+                       if (oa != null) {
+                               AttributeTester.Report_ObsoleteMessage (oa, method.DeclaringType.FullName, loc);
+                       }
+
+
+                       oa = AttributeTester.GetObsoleteAttribute (method.DeclaringType);
+                       if (oa != null) {
+                               AttributeTester.Report_ObsoleteMessage (oa, method.DeclaringType.FullName, loc);
+                       }
+
+                       if (IsMethodExcluded (method, ec))
                                return;
                        
                        if (!is_static){
-                               if (decl_type.IsValueType)
+                               if (TypeManager.IsValueType (decl_type))
                                        struct_call = true;
                                //
                                // 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 (instance_expr.Type.IsValueType){
+                                       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.  
-
-                                               struct_call = true;
-                                               if (decl_type.IsValueType){
+                                               if (decl_type.IsValueType || itype.IsGenericParameter){
                                                        //
                                                        // If the expression implements IMemoryLocation, then
                                                        // we can optimize and use AddressOf on the
@@ -5078,16 +5638,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);
@@ -5096,17 +5658,28 @@ namespace Mono.CSharp {
 
                        EmitArguments (ec, method, Arguments);
 
-                       if (is_static || struct_call || is_base){
-                               if (method is MethodInfo) {
-                                       ig.Emit (OpCodes.Call, (MethodInfo) method);
-                               } else
-                                       ig.Emit (OpCodes.Call, (ConstructorInfo) method);
-                       } else {
+                       OpCode call_op;
+                       if (is_static || struct_call || is_base || (this_call && !method.IsVirtual))
+                               call_op = OpCodes.Call;
+                       else
+                               call_op = OpCodes.Callvirt;
+
+                       if ((method.CallingConvention & CallingConventions.VarArgs) != 0) {
+                               Type[] varargs_types = GetVarargsTypes (ec, method, Arguments);
+                               ig.EmitCall (call_op, (MethodInfo) method, varargs_types);
+                               return;
+                       }
+
+                       //
+                       // 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 (method is MethodInfo)
-                                       ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
+                               ig.Emit (call_op, (MethodInfo) method);
                                else
-                                       ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
-                       }
+                               ig.Emit (call_op, (ConstructorInfo) method);
                }
                
                public override void Emit (EmitContext ec)
@@ -5150,7 +5723,7 @@ namespace Mono.CSharp {
                        //
                        type = ec.DeclSpace.ResolveType (expr, true, loc);
                        if (type != null) {
-                               Cast cast = new Cast (new TypeExpr (type, loc), argument, loc);
+                               Cast cast = new Cast (new TypeExpression (type, loc), argument, loc);
                                return cast.Resolve (ec);
                        }
 
@@ -5166,7 +5739,7 @@ namespace Mono.CSharp {
                        // Ok, so it's a Cast.
                        //
                        if (expr.eclass == ExprClass.Type) {
-                               Cast cast = new Cast (new TypeExpr (expr.Type, loc), argument, loc);
+                               Cast cast = new Cast (new TypeExpression (expr.Type, loc), argument, loc);
                                return cast.Resolve (ec);
                        }
 
@@ -5252,7 +5825,13 @@ namespace Mono.CSharp {
        /// </summary>
        public class New : ExpressionStatement, IMemoryLocation {
                public readonly ArrayList Arguments;
-               public readonly Expression RequestedType;
+
+               //
+               // During bootstrap, it contains the RequestedType,
+               // but if `type' is not null, it *might* contain a NewDelegate
+               // (because of field multi-initialization)
+               //
+               public Expression RequestedType;
 
                MethodBase method = null;
 
@@ -5262,6 +5841,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)
                {
@@ -5318,20 +5898,51 @@ namespace Mono.CSharp {
                        //
                        // This leads to bugs (#37014)
                        //
-                       if (type != null)
+                       if (type != null){
+                               if (RequestedType is NewDelegate)
+                                       return RequestedType;
                                return this;
+                       }
                        
                        type = ec.DeclSpace.ResolveType (RequestedType, false, loc);
                        
                        if (type == null)
                                return null;
                        
+                       CheckObsoleteAttribute (type);
+
                        bool IsDelegate = TypeManager.IsDelegateType (type);
                        
-                       if (IsDelegate)
-                               return (new NewDelegate (type, Arguments, loc)).Resolve (ec);
+                       if (IsDelegate){
+                               RequestedType = (new NewDelegate (type, Arguments, loc)).Resolve (ec);
+                               if (RequestedType != null)
+                                       if (!(RequestedType is NewDelegate))
+                                               throw new Exception ("NewDelegate.Resolve returned a non NewDelegate: " + RequestedType.GetType ());
+                               return RequestedType;
+                       }
+
+                       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 (type.IsInterface || type.IsAbstract){
+                               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;
                        }
@@ -5347,7 +5958,8 @@ namespace Mono.CSharp {
                                return this;
                        
                        Expression ml;
-                       ml = MemberLookupFinal (ec, null, type, ".ctor",
+                       ml = MemberLookupFinal (ec, type, type, ".ctor",
+                                               // For member-lookup, treat 'new Foo (bar)' as call to 'foo.ctor (bar)', where 'foo' is of type 'Foo'.
                                                MemberTypes.Constructor,
                                                AllBindingFlags | BindingFlags.DeclaredOnly, loc);
 
@@ -5369,7 +5981,8 @@ namespace Mono.CSharp {
                                        }
                                }
 
-                               method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, Arguments, loc);
+                               method = Invocation.OverloadResolve (
+                                       ec, (MethodGroupExpr) ml, Arguments, false, loc);
                                
                        }
 
@@ -5385,6 +5998,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)
@@ -5448,17 +6073,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
@@ -5496,7 +6130,7 @@ namespace Mono.CSharp {
        ///   initialization data and the other which does not need dimensions
        ///   specified but where initialization data is mandatory.
        /// </remarks>
-       public class ArrayCreation : ExpressionStatement {
+       public class ArrayCreation : Expression {
                Expression requested_base_type;
                ArrayList initializers;
 
@@ -5554,9 +6188,9 @@ namespace Mono.CSharp {
                        this.rank = rank;
                        loc = l;
 
-                       //this.rank = rank.Substring (0, rank.LastIndexOf ("["));
+                       //this.rank = rank.Substring (0, rank.LastIndexOf ('['));
                        //
-                       //string tmp = rank.Substring (rank.LastIndexOf ("["));
+                       //string tmp = rank.Substring (rank.LastIndexOf ('['));
                        //
                        //dimensions = tmp.Length - 1;
                        expect_initializers = true;
@@ -5643,9 +6277,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
@@ -5867,7 +6506,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 " +
@@ -5878,7 +6518,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) {
@@ -6054,7 +6694,7 @@ namespace Mono.CSharp {
                //
                // Emits the initializers for the array
                //
-               void EmitStaticInitializers (EmitContext ec, bool is_expression)
+               void EmitStaticInitializers (EmitContext ec)
                {
                        //
                        // First, the static data
@@ -6066,35 +6706,31 @@ namespace Mono.CSharp {
 
                        fb = RootContext.MakeStaticData (data);
 
-                       if (is_expression)
-                               ig.Emit (OpCodes.Dup);
+                       ig.Emit (OpCodes.Dup);
                        ig.Emit (OpCodes.Ldtoken, fb);
                        ig.Emit (OpCodes.Call,
                                 TypeManager.void_initializearray_array_fieldhandle);
                }
-               
+
                //
                // Emits pieces of the array that can not be computed at compile
                // time (variables and string locations).
                //
                // This always expect the top value on the stack to be the array
                //
-               void EmitDynamicInitializers (EmitContext ec, bool is_expression)
+               void EmitDynamicInitializers (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
                        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;
@@ -6129,7 +6765,7 @@ namespace Mono.CSharp {
                                            num_automatic_initializers <= max_automatic_initializers) {
                                                Type etype = e.Type;
                                                
-                                               ig.Emit (OpCodes.Ldloc, temp);
+                                               ig.Emit (OpCodes.Dup);
 
                                                for (int idx = 0; idx < dims; idx++) 
                                                        IntConstant.EmitInt (ig, current_pos [idx]);
@@ -6138,9 +6774,9 @@ namespace Mono.CSharp {
                                                // If we are dealing with a struct, get the
                                                // address of it, so we can store it.
                                                //
-                                               if ((dims == 1) &&
+                                               if ((dims == 1) && 
                                                    etype.IsSubclassOf (TypeManager.value_type) &&
-                                                   (!TypeManager.IsBuiltinType (etype) ||
+                                                   (!TypeManager.IsBuiltinOrEnum (etype) ||
                                                     etype == TypeManager.decimal_type)) {
                                                        if (e is New){
                                                                New n = (New) e;
@@ -6175,9 +6811,6 @@ namespace Mono.CSharp {
                                        current_pos [j] = 0;
                                }
                        }
-
-                       if (is_expression)
-                               ig.Emit (OpCodes.Ldloc, temp);
                }
 
                void EmitArrayArguments (EmitContext ec)
@@ -6195,7 +6828,7 @@ namespace Mono.CSharp {
                        }
                }
                
-               void DoEmit (EmitContext ec, bool is_statement)
+               public override void Emit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
                        
@@ -6215,28 +6848,17 @@ 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);
-                               }
+                                               EmitStaticInitializers (ec);
                                
                                if (dynamic_initializers)
-                                       EmitDynamicInitializers (ec, !is_statement);
+                                       EmitDynamicInitializers (ec);
                        }
                }
                
-               public override void Emit (EmitContext ec)
-               {
-                       DoEmit (ec, false);
-               }
-
-               public override void EmitStatement (EmitContext ec)
-               {
-                       DoEmit (ec, true);
-               }
-
                public object EncodeAsAttribute ()
                {
                        if (!is_one_dimensional){
@@ -6264,6 +6886,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>
@@ -6300,7 +6932,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");
@@ -6353,8 +6989,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);
                }
@@ -6364,7 +7000,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 {
@@ -6375,7 +7011,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
@@ -6388,6 +7024,85 @@ namespace Mono.CSharp {
                }
        }
 
+       /// <summary>
+       ///   Represents the `__arglist' construct
+       /// </summary>
+       public class ArglistAccess : Expression
+       {
+               public ArglistAccess (Location loc)
+               {
+                       this.loc = loc;
+               }
+
+               public bool ResolveBase (EmitContext ec)
+               {
+                       eclass = ExprClass.Variable;
+                       type = TypeManager.runtime_argument_handle_type;
+                       return true;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (!ResolveBase (ec))
+                               return null;
+
+                       if (ec.IsFieldInitializer || !ec.CurrentBlock.HasVarargs) {
+                               Error (190, "The __arglist construct is valid only within " +
+                                      "a variable argument method.");
+                               return null;
+                       }
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Arglist);
+               }
+       }
+
+       /// <summary>
+       ///   Represents the `__arglist (....)' construct
+       /// </summary>
+       public class Arglist : Expression
+       {
+               public readonly Argument[] Arguments;
+
+               public Arglist (Argument[] args, Location l)
+               {
+                       Arguments = args;
+                       loc = l;
+               }
+
+               public Type[] ArgumentTypes {
+                       get {
+                               Type[] retval = new Type [Arguments.Length];
+                               for (int i = 0; i < Arguments.Length; i++)
+                                       retval [i] = Arguments [i].Type;
+                               return retval;
+                       }
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       eclass = ExprClass.Variable;
+                       type = TypeManager.runtime_argument_handle_type;
+
+                       foreach (Argument arg in Arguments) {
+                               if (!arg.Resolve (ec, loc))
+                                       return null;
+                       }
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       foreach (Argument arg in Arguments)
+                               arg.Emit (ec);
+               }
+       }
+
        //
        // This produces the value that renders an instance, used by the iterators code
        //
@@ -6410,13 +7125,13 @@ namespace Mono.CSharp {
                        ec.ig.Emit (OpCodes.Ldarg_0);
                }
        }
-       
+
        /// <summary>
        ///   Implements the typeof operator
        /// </summary>
        public class TypeOf : Expression {
                public readonly Expression QueriedType;
-               Type typearg;
+               protected Type typearg;
                
                public TypeOf (Expression queried_type, Location l)
                {
@@ -6437,6 +7152,8 @@ namespace Mono.CSharp {
                                return null;
                        }
 
+                       CheckObsoleteAttribute (typearg);
+
                        type = TypeManager.type_type;
                        eclass = ExprClass.Type;
                        return this;
@@ -6456,8 +7173,8 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Implements the `typeof (void)' operator
        /// </summary>
-       public class TypeOfVoid : Expression {
-               public TypeOfVoid (Location l)
+       public class TypeOfVoid : TypeOf {
+               public TypeOfVoid (Location l) : base (null, l)
                {
                        loc = l;
                }
@@ -6465,19 +7182,10 @@ namespace Mono.CSharp {
                public override Expression DoResolve (EmitContext ec)
                {
                        type = TypeManager.type_type;
+                       typearg = TypeManager.void_type;
                        eclass = ExprClass.Type;
                        return this;
                }
-
-               public override void Emit (EmitContext ec)
-               {
-                       ec.ig.Emit (OpCodes.Ldtoken, TypeManager.void_type);
-                       ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
-               }
-
-               public Type TypeArg { 
-                       get { return TypeManager.void_type; }
-               }
        }
 
        /// <summary>
@@ -6510,7 +7218,13 @@ namespace Mono.CSharp {
                                ((TypeParameterExpr)QueriedType).Error_CannotUseAsUnmanagedType (loc);
                                return null;
                        }
-                       
+
+                       type_queried = QueriedType.Type;
+                       if (type_queried == null)
+                               return null;
+
+                       CheckObsoleteAttribute (type_queried);
+
                        if (!TypeManager.IsUnmanagedType (type_queried)){
                                Report.Error (208, loc, "Cannot take the size of an unmanaged type (" + TypeManager.CSharpName (type_queried) + ")");
                                return null;
@@ -6536,8 +7250,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)
                {
@@ -6546,13 +7261,20 @@ 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;
                        }
                }
 
-               static void error176 (Location loc, string name)
+               public static void error176 (Location loc, string name)
                {
                        Report.Error (176, loc, "Static member `" +
                                      name + "' cannot be accessed " +
@@ -6560,21 +7282,13 @@ namespace Mono.CSharp {
                                      "type name instead");
                }
 
-               static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Location loc)
+               public static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Expression left, Location loc)
                {
-                       if (left_original == null)
-                               return false;
-
-                       if (!(left_original is SimpleName))
+                       SimpleName sn = left_original as SimpleName;
+                       if (sn == null || left == null || left.Type.Name != sn.Name)
                                return false;
 
-                       SimpleName sn = (SimpleName) left_original;
-
-                       Type t = RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc);
-                       if (t != null)
-                               return true;
-
-                       return false;
+                       return RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc) != null;
                }
                
                public static Expression ResolveMemberAccess (EmitContext ec, Expression member_lookup,
@@ -6606,10 +7320,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);
@@ -6628,7 +7342,7 @@ namespace Mono.CSharp {
                                        
                                        if (decl_type.IsSubclassOf (TypeManager.enum_type)) {
                                                if (left_is_explicit && !left_is_type &&
-                                                   !IdenticalNameAndTypeName (ec, left_original, loc)) {
+                                                   !IdenticalNameAndTypeName (ec, left_original, member_lookup, loc)) {
                                                        error176 (loc, fe.FieldInfo.Name);
                                                        return null;
                                                }                                       
@@ -6672,7 +7386,8 @@ namespace Mono.CSharp {
                                // a FieldExpr
                                //
 
-                               if (ee.EventInfo.DeclaringType == ec.ContainerType) {
+                               if (ee.EventInfo.DeclaringType == ec.ContainerType ||
+                                   TypeManager.IsNestedChildOf(ec.ContainerType, ee.EventInfo.DeclaringType)) {
                                        MemberInfo mi = GetFieldFromEvent (ee);
 
                                        if (mi == null) {
@@ -6681,6 +7396,7 @@ namespace Mono.CSharp {
                                                // accessors and private field etc so there's no need
                                                // to transform ourselves.
                                                //
+                                               ee.InstanceExpression = left;
                                                return ee;
                                        }
 
@@ -6694,21 +7410,23 @@ namespace Mono.CSharp {
                                        if (!left_is_explicit)
                                                left = null;
                                        
+                                       ee.InstanceExpression = left;
+
                                        return ResolveMemberAccess (ec, ml, left, loc, left_original);
                                }
                        }
 
                        if (member_lookup is IMemberExpr) {
                                IMemberExpr me = (IMemberExpr) member_lookup;
+                               MethodGroupExpr mg = me as MethodGroupExpr;
 
                                if (left_is_type){
-                                       MethodGroupExpr mg = me as MethodGroupExpr;
                                        if ((mg != null) && left_is_explicit && left.Type.IsInterface)
                                                mg.IsExplicitImpl = left_is_explicit;
 
                                        if (!me.IsStatic){
                                                if ((ec.IsFieldInitializer || ec.IsStatic) &&
-                                                   IdenticalNameAndTypeName (ec, left_original, loc))
+                                                   IdenticalNameAndTypeName (ec, left_original, member_lookup, loc))
                                                        return member_lookup;
 
                                                SimpleName.Error_ObjectRefRequired (ec, loc, me.Name);
@@ -6717,7 +7435,7 @@ namespace Mono.CSharp {
 
                                } else {
                                        if (!me.IsInstance){
-                                               if (IdenticalNameAndTypeName (ec, left_original, loc))
+                                               if (IdenticalNameAndTypeName (ec, left_original, left, loc))
                                                        return member_lookup;
 
                                                if (left_is_explicit) {
@@ -6747,6 +7465,9 @@ namespace Mono.CSharp {
                                                }
                                        }
 
+                                       if ((mg != null) && IdenticalNameAndTypeName (ec, left_original, left, loc))
+                                               mg.IdenticalTypeName = true;
+
                                        me.InstanceExpression = left;
                                }
 
@@ -6755,11 +7476,12 @@ namespace Mono.CSharp {
 
                        Console.WriteLine ("Left is: " + left);
                        Report.Error (-100, loc, "Support for [" + member_lookup + "] is not present yet");
-                       Environment.Exit (0);
+                       Environment.Exit (1);
                        return null;
                }
                
-               public Expression DoResolve (EmitContext ec, Expression right_side, ResolveFlags flags)
+               public virtual Expression DoResolve (EmitContext ec, Expression right_side,
+                                                    ResolveFlags flags)
                {
                        if (type != null)
                                throw new Exception ();
@@ -6772,7 +7494,7 @@ namespace Mono.CSharp {
                        //
 
                        Expression original = expr;
-                       expr = expr.Resolve (ec, flags | ResolveFlags.DisableFlowAnalysis);
+                       expr = expr.Resolve (ec, flags | ResolveFlags.Intermediate | ResolveFlags.DisableFlowAnalysis);
                        if (expr == null)
                                return null;
 
@@ -6793,13 +7515,12 @@ namespace Mono.CSharp {
                        // it will fail to find any members at all
                        //
 
-                       int errors = Report.Errors;
-                       
-                       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");
+                                       Report.Error_T (122, loc, expr_type);
                                        return null;
                                }
 
@@ -6810,12 +7531,27 @@ namespace Mono.CSharp {
                                                object value = en.LookupEnumValue (ec, Identifier, loc);
                                                
                                                if (value != null){
+                                                       ObsoleteAttribute oa = en.GetObsoleteAttribute (ec, Identifier);
+                                                       if (oa != null) {
+                                                               AttributeTester.Report_ObsoleteMessage (oa, en.GetSignatureForError (), Location);
+                                                       }
+
                                                        Constant c = Constantify (value, en.UnderlyingType);
                                                        return new EnumConstant (c, expr_type);
                                                }
+                                       } else {
+                                               CheckObsoleteAttribute (expr_type);
+
+                                               FieldInfo fi = expr_type.GetField (Identifier);
+                                               if (fi != null) {
+                                                       ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (fi);
+                                                       if (oa != null)
+                                                               AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (fi), Location);
+                                               }
                                        }
                                }
-                       }
+                       } else
+                               expr_type = expr.Type;
                        
                        if (expr_type.IsPointer){
                                Error (23, "The `.' operator can not be applied to pointer operands (" +
@@ -6823,10 +7559,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)) {
@@ -6837,11 +7584,37 @@ 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 ();
+
+                               return mg.ResolveGeneric (ec, args);
+                       }
+
                        // The following DoResolve/DoResolveLValue will do the definite assignment
                        // check.
 
@@ -6879,7 +7652,7 @@ namespace Mono.CSharp {
                                        string full_name = String.Concat (((SimpleName) full_expr.Expr).Name, ".", fname);
                                        Type fully_qualified = ec.DeclSpace.FindType (loc, full_name);
                                        if (fully_qualified != null)
-                                               return new TypeExpr (fully_qualified, loc);
+                                               return new TypeExpression (fully_qualified, loc);
                                }
 
                                full_expr = full_expr.Expr as MemberAccess;
@@ -6898,25 +7671,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);
 
-                       return null;                    
+                               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;
+                       }
+
+                       if (args != null) {
+                               ConstructedType ctype = new ConstructedType (t, args, loc);
+                               return ctype.ResolveAsTypeStep (ec);
+                       }
+
+                       return texpr;
                }
 
                public override void Emit (EmitContext ec)
@@ -6926,7 +7726,10 @@ namespace Mono.CSharp {
 
                public override string ToString ()
                {
-                       return expr + "." + Identifier;
+                       if (args != null)
+                               return expr + "." + Identifier + "!" + args.Count;
+                       else
+                               return expr + "." + Identifier;
                }
        }
 
@@ -7155,9 +7958,9 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
+#if false
                        ExprClass eclass = ea.Expr.eclass;
 
-#if false
                        // As long as the type is valid
                        if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess ||
                              eclass == ExprClass.Value)) {
@@ -7234,10 +8037,14 @@ 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 
+                       } else if (type.IsGenericParameter)
+                               ig.Emit (OpCodes.Ldelem_Any, type);
+                       else
                                ig.Emit (OpCodes.Ldelem_Ref);
                }
 
@@ -7247,10 +8054,10 @@ namespace Mono.CSharp {
                /// </summary>
                static public void EmitStoreOpcode (ILGenerator ig, Type t)
                {
-                       bool is_stobj;
-                       OpCode op = GetStoreOpcode (t, out is_stobj);
-                       if (is_stobj)
-                               ig.Emit (OpCodes.Stobj, t);
+                       bool is_stobj, has_type_arg;
+                       OpCode op = GetStoreOpcode (t, out is_stobj, out has_type_arg);
+                       if (has_type_arg)
+                               ig.Emit (op, t);
                        else
                                ig.Emit (op);
                }
@@ -7259,10 +8066,10 @@ namespace Mono.CSharp {
                ///    Returns the right opcode to store an object of Type `t'
                ///    from an array of T.  
                /// </summary>
-               static public OpCode GetStoreOpcode (Type t, out bool is_stobj)
+               static public OpCode GetStoreOpcode (Type t, out bool is_stobj, out bool has_type_arg)
                {
                        //Console.WriteLine (new System.Diagnostics.StackTrace ());
-                       is_stobj = false;
+                       has_type_arg = false; is_stobj = false;
                        t = TypeManager.TypeToCoreType (t);
                        if (TypeManager.IsEnumType (t) && t != TypeManager.enum_type)
                                t = TypeManager.EnumToUnderlying (t);
@@ -7281,18 +8088,23 @@ namespace Mono.CSharp {
                        else if (t == TypeManager.double_type)
                                return OpCodes.Stelem_R8;
                        else if (t == TypeManager.intptr_type) {
-                                is_stobj = true;
+                                has_type_arg = true;
+                               is_stobj = true;
                                 return OpCodes.Stobj;
                        } else if (t.IsValueType) {
+                               has_type_arg = true;
                                is_stobj = true;
                                return OpCodes.Stobj;
+                       } else if (t.IsGenericParameter) {
+                               has_type_arg = true;
+                               return OpCodes.Stelem_Any;
                        } else
                                return OpCodes.Stelem_Ref;
                }
 
                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;
@@ -7313,7 +8125,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;
@@ -7436,7 +8248,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;
@@ -7519,7 +8331,7 @@ namespace Mono.CSharp {
                        MemberInfo [] mi = TypeManager.MemberLookup (
                                caller_type, caller_type, lookup_type, MemberTypes.Property,
                                BindingFlags.Public | BindingFlags.Instance |
-                               BindingFlags.DeclaredOnly, p_name);
+                               BindingFlags.DeclaredOnly, p_name, null);
 
                        if (mi == null || mi.Length == 0)
                                return null;
@@ -7551,9 +8363,10 @@ namespace Mono.CSharp {
                        if (!lookup_type.IsInterface)
                                return ix;
 
-                       Type [] ifaces = TypeManager.GetInterfaces (lookup_type);
+                       TypeExpr [] ifaces = TypeManager.GetInterfaces (lookup_type);
                        if (ifaces != null) {
-                               foreach (Type itype in ifaces) {
+                               foreach (TypeExpr iface in ifaces) {
+                                       Type itype = iface.Type;
                                        MemberInfo [] mi = GetIndexersForTypeOrInterface (caller_type, itype);
                                        if (mi != null){
                                                if (ix == null)
@@ -7637,7 +8450,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) {
@@ -7683,8 +8497,6 @@ namespace Mono.CSharp {
                        if (!CommonResolve (ec))
                                return null;
 
-                       Type right_type = right_side.Type;
-
                        bool found_any = false, found_any_setters = false;
 
                        Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type, loc);
@@ -7703,7 +8515,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) {
@@ -7818,18 +8630,25 @@ 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;
                        }
 
                        Expression left;
                        
                        if (ec.IsStatic)
-                               left = new TypeExpr (base_type, loc);
+                               left = new TypeExpression (base_type, loc);
                        else
                                left = ec.GetThis (loc);
                        
@@ -7965,7 +8784,7 @@ namespace Mono.CSharp {
        //   the type specification, we just use this to construct the type
        //   one bit at a time.
        // </summary>
-       public class ComposedCast : Expression {
+       public class ComposedCast : TypeExpr {
                Expression left;
                string dim;
                
@@ -7976,17 +8795,53 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public override Expression ResolveAsTypeStep (EmitContext ec)
+               public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
                {
                        Type ltype = ec.DeclSpace.ResolveType (left, false, loc);
                        if (ltype == null)
                                return null;
 
+                       if ((ltype == TypeManager.void_type) && (dim != "*")) {
+                               Report.Error (1547, Location,
+                                             "Keyword 'void' cannot be used in this context");
+                               return null;
+                       }
+
+                       int pos = 0;
+                       while ((pos < dim.Length) && (dim [pos] == '[')) {
+                               pos++;
+
+                               if (dim [pos] == ']') {
+                                       ltype = ltype.MakeArrayType ();
+                                       pos++;
+
+                                       if (pos < dim.Length)
+                                               continue;
+
+                                       type = ltype;
+                                       eclass = ExprClass.Type;
+                                       return this;
+                               }
+
+                               int rank = 0;
+                               while (dim [pos] == ',') {
+                                       pos++; rank++;
+                               }
+
+                               if ((dim [pos] != ']') || (pos != dim.Length-1))
+                                       return null;
+                                               
+                               type = ltype.MakeArrayType (rank + 1);
+                               eclass = ExprClass.Type;
+                               return this;
+                       }
+
                        //
                        // 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){
                                //
@@ -7995,9 +8850,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;
                        }
@@ -8017,19 +8876,10 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       return ResolveAsTypeStep (ec);
-               }
-
-               public override void Emit (EmitContext ec)
-               {
-                       throw new Exception ("This should never be called");
-               }
-
-               public override string ToString ()
-               {
-                       return left + dim;
+               public override string Name {
+                       get {
+                               return left + dim;
+                       }
                }
        }
 
@@ -8129,7 +8979,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;