**** Merged from MCS ****
[mono.git] / mcs / gmcs / expression.cs
index dc42926e01ec8ff85924e27af8dc51de95be20a8..47b58f93e06031c35dc247695d651a959f6aa506 100755 (executable)
@@ -66,7 +66,8 @@ namespace Mono.CSharp {
                                 return null;
 
                         args.Add (a);
-                       method = Invocation.OverloadResolve (ec, (MethodGroupExpr) mg, args, loc);
+                       method = Invocation.OverloadResolve (
+                               ec, (MethodGroupExpr) mg, args, false, loc);
 
                        if (method == null)
                                return null;
@@ -429,6 +430,11 @@ namespace Mono.CSharp {
                                        return null;
                                }
 
+                               if (ec.InFixedInitializer && ((variable != null) && variable.VerifyFixed (false))) {
+                                       Error (213, "You can not fix an already fixed expression");
+                                       return null;
+                               }
+
                                // According to the specs, a variable is considered definitely assigned if you take
                                // its address.
                                if ((variable != null) && (variable.VariableInfo != null))
@@ -971,6 +977,13 @@ namespace Mono.CSharp {
 
                        ia.CacheTemporaries (ec);
 
+                       //
+                       // NOTE: We should probably handle three cases:
+                       //
+                       //     * method invocation required.
+                       //     * direct stack manipulation possible
+                       //     * the object requires an "instance" field
+                       //
                        if (temp_storage == null){
                                //
                                // Temporary improvement: if we are dealing with something that does
@@ -2278,7 +2291,7 @@ namespace Mono.CSharp {
                        bool overload_failed = false;
 
                        //
-                       // Special cases: string comapred to null
+                       // Special cases: string or type parameter comapred to null
                        //
                        if (oper == Operator.Equality || oper == Operator.Inequality){
                                if ((l == TypeManager.string_type && (right is NullLiteral)) ||
@@ -2287,6 +2300,28 @@ namespace Mono.CSharp {
                                        
                                        return this;
                                }
+
+                               if (l.IsGenericParameter && (right is NullLiteral)) {
+                                       if (l.BaseType == TypeManager.value_type) {
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+
+                                       left = new BoxedCast (left);
+                                       Type = TypeManager.bool_type;
+                                       return this;
+                               }
+
+                               if (r.IsGenericParameter && (left is NullLiteral)) {
+                                       if (r.BaseType == TypeManager.value_type) {
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+
+                                       right = new BoxedCast (right);
+                                       Type = TypeManager.bool_type;
+                                       return this;
+                               }
                        }
 
                        //
@@ -2315,7 +2350,9 @@ namespace Mono.CSharp {
                                        args.Add (new Argument (left, Argument.AType.Expression));
                                        args.Add (new Argument (right, Argument.AType.Expression));
                                        
-                                       MethodBase method = Invocation.OverloadResolve (ec, union, args, Location.Null);
+                                       MethodBase method = Invocation.OverloadResolve (
+                                               ec, union, args, true, Location.Null);
+
                                        if (method != null) {
                                                MethodInfo mi = (MethodInfo) method;
                                                
@@ -2334,93 +2371,35 @@ namespace Mono.CSharp {
                                // If any of the arguments is a string, cast to string
                                //
                                
-                               if (l == TypeManager.string_type){
-                                       MethodBase method;
-                                       
-                                       if (r == TypeManager.void_type) {
-                                               Error_OperatorCannotBeApplied ();
-                                               return null;
-                                       }
-                                       
-                                       if (r == TypeManager.string_type){
-                                               if (left is Constant && right is Constant){
-                                                       StringConstant ls = (StringConstant) left;
-                                                       StringConstant rs = (StringConstant) right;
-                                                       
-                                                       return new StringConstant (
-                                                               ls.Value + rs.Value);
-                                               }
-
-                                               if (left is BinaryMethod){
-                                                       BinaryMethod b = (BinaryMethod) left;
-
-                                                       //
-                                                       // Call String.Concat (string, string, string) or
-                                                       // String.Concat (string, string, string, string)
-                                                       // if possible.
-                                                       //
-                                                       if (b.method == TypeManager.string_concat_string_string ||
-                                                            b.method == TypeManager.string_concat_string_string_string){
-                                                               int count = b.Arguments.Count;
-                                                               
-                                                               if (count == 2){
-                                                                       ArrayList bargs = new ArrayList (3);
-                                                                       bargs.AddRange (b.Arguments);
-                                                                       bargs.Add (new Argument (right, Argument.AType.Expression));
-                                                                       return new BinaryMethod (
-                                                                               TypeManager.string_type,
-                                                                               TypeManager.string_concat_string_string_string, bargs);
-                                                               } else if (count == 3){
-                                                                       ArrayList bargs = new ArrayList (4);
-                                                                       bargs.AddRange (b.Arguments);
-                                                                       bargs.Add (new Argument (right, Argument.AType.Expression));
-                                                                       return new BinaryMethod (
-                                                                               TypeManager.string_type,
-                                                                               TypeManager.string_concat_string_string_string_string, bargs);
-                                                               }
-                                                       }
-                                               }
-
-                                               // string + string
-                                               method = TypeManager.string_concat_string_string;
-                                       } else {
-                                               // string + object
-                                               method = TypeManager.string_concat_object_object;
-                                               right = Convert.ImplicitConversion (
-                                                       ec, right, TypeManager.object_type, loc);
-                                               if (right == null){
-                                                       Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
-                                                       return null;
-                                               }
-                                       }
-
-                                       //
-                                       // Cascading concats will hold up to 2 arguments, any extras will be
-                                       // reallocated above.
-                                       //
-                                       ArrayList args = new ArrayList (2);
-                                       args.Add (new Argument (left, Argument.AType.Expression));
-                                       args.Add (new Argument (right, Argument.AType.Expression));
+                               // Simple constant folding
+                               if (left is StringConstant && right is StringConstant)
+                                       return new StringConstant (((StringConstant) left).Value + ((StringConstant) right).Value);
 
-                                       return new BinaryMethod (TypeManager.string_type, method, args);
-                               } else if (r == TypeManager.string_type){
-                                       // object + string
+                               if (l == TypeManager.string_type || r == TypeManager.string_type) {
 
-                                       if (l == TypeManager.void_type) {
+                                       if (r == TypeManager.void_type || l == TypeManager.void_type) {
                                                Error_OperatorCannotBeApplied ();
                                                return null;
                                        }
                                        
-                                       left = Convert.ImplicitConversion (ec, left, TypeManager.object_type, loc);
-                                       if (left == null){
-                                               Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
-                                               return null;
+                                       // try to fold it in on the left
+                                       if (left is StringConcat) {
+
+                                               //
+                                               // We have to test here for not-null, since we can be doubly-resolved
+                                               // take care of not appending twice
+                                               //
+                                               if (type == null){
+                                                       type = TypeManager.string_type;
+                                                       ((StringConcat) left).Append (ec, right);
+                                                       return left.Resolve (ec);
+                                               } else {
+                                                       return left;
+                                               }
                                        }
-                                       ArrayList args = new ArrayList (2);
-                                       args.Add (new Argument (left, Argument.AType.Expression));
-                                       args.Add (new Argument (right, Argument.AType.Expression));
 
-                                       return new BinaryMethod (TypeManager.string_type, TypeManager.string_concat_object_object, args);
+                                       // Otherwise, start a new concat expression
+                                       return new StringConcat (ec, loc, left, right).Resolve (ec);
                                }
 
                                //
@@ -2502,7 +2481,7 @@ namespace Mono.CSharp {
                        // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
                        //
                        if (oper == Operator.Addition || oper == Operator.Subtraction) {
-                               if (l.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)
@@ -2511,7 +2490,7 @@ namespace Mono.CSharp {
                                                r = right.Type;
                                        }
                                
-                                       if (r.IsSubclassOf (TypeManager.delegate_type)){
+                                       if (TypeManager.IsDelegateType (r)){
                                        MethodInfo method;
                                        ArrayList args = new ArrayList (2);
                                        
@@ -2810,32 +2789,25 @@ 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 || left is IntConstant && ((IntConstant) left).Value == 0) {
-                                       right.Emit (ec);
-                                       if (my_on_true)
-                                               ig.Emit (OpCodes.Brtrue, target);
-                                       else
-                                               ig.Emit (OpCodes.Brfalse, target);
+                               //
+                               // put the constant on the rhs, for simplicity
+                               //
+                               if (left is Constant) {
+                                       Expression swap = right;
+                                       right = left;
+                                       left = swap;
+                               }
                                        
-                                       return;
-                               } else if (right is NullLiteral || right is IntConstant && ((IntConstant) right).Value == 0){
+                               if (((Constant) right).IsZeroInteger) {
                                        left.Emit (ec);
                                        if (my_on_true)
                                                ig.Emit (OpCodes.Brtrue, target);
                                        else
                                                ig.Emit (OpCodes.Brfalse, target);
                                        
-                                       return;
-                               } 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;
                                } else if (right is BoolConstant){
                                        left.Emit (ec);
@@ -2887,7 +2859,7 @@ namespace Mono.CSharp {
                        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:
@@ -2931,9 +2903,6 @@ namespace Mono.CSharp {
                                break;
 
                        case Operator.LessThanOrEqual:
-                               if (t == TypeManager.double_type || t == TypeManager.float_type)
-                                       isUnsigned = true;
-
                                if (onTrue)
                                        if (isUnsigned)
                                                ig.Emit (OpCodes.Ble_Un, target);
@@ -2948,8 +2917,6 @@ namespace Mono.CSharp {
 
 
                        case Operator.GreaterThanOrEqual:
-                               if (t == TypeManager.double_type || t == TypeManager.float_type)
-                                       isUnsigned = true;
                                if (onTrue)
                                        if (isUnsigned)
                                                ig.Emit (OpCodes.Bge_Un, target);
@@ -3177,6 +3144,137 @@ namespace Mono.CSharp {
                }
        }
 
+       //
+       // Represents the operation a + b [+ c [+ d [+ ...]]], where a is a string
+       // b, c, d... may be strings or objects.
+       //
+       public class StringConcat : Expression {
+               ArrayList operands;
+               bool invalid = false;
+               
+               
+               public StringConcat (EmitContext ec, Location loc, Expression left, Expression right)
+               {
+                       this.loc = loc;
+                       type = TypeManager.string_type;
+                       eclass = ExprClass.Value;
+               
+                       operands = new ArrayList (2);
+                       Append (ec, left);
+                       Append (ec, right);
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (invalid)
+                               return null;
+                       
+                       return this;
+               }
+               
+               public void Append (EmitContext ec, Expression operand)
+               {
+                       //
+                       // Constant folding
+                       //
+                       if (operand is StringConstant && operands.Count != 0) {
+                               StringConstant last_operand = operands [operands.Count - 1] as StringConstant;
+                               if (last_operand != null) {
+                                       operands [operands.Count - 1] = new StringConstant (last_operand.Value + ((StringConstant) operand).Value);
+                                       return;
+                               }
+                       }
+                       
+                       //
+                       // Conversion to object
+                       //
+                       if (operand.Type != TypeManager.string_type) {
+                               Expression no = Convert.ImplicitConversion (ec, operand, TypeManager.object_type, loc);
+                               
+                               if (no == null) {
+                                       Binary.Error_OperatorCannotBeApplied (loc, "+", TypeManager.string_type, operand.Type);
+                                       invalid = true;
+                               }
+                               operand = no;
+                       }
+                       
+                       operands.Add (operand);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       MethodInfo concat_method = null;
+                       
+                       //
+                       // Are we also concating objects?
+                       //
+                       bool is_strings_only = true;
+                       
+                       //
+                       // Do conversion to arguments; check for strings only
+                       //
+                       for (int i = 0; i < operands.Count; i ++) {
+                               Expression e = (Expression) operands [i];
+                               is_strings_only &= e.Type == TypeManager.string_type;
+                       }
+                       
+                       for (int i = 0; i < operands.Count; i ++) {
+                               Expression e = (Expression) operands [i];
+                               
+                               if (! is_strings_only && e.Type == TypeManager.string_type) {
+                                       // need to make sure this is an object, because the EmitParams
+                                       // method might look at the type of this expression, see it is a
+                                       // string and emit a string [] when we want an object [];
+                                       
+                                       e = Convert.ImplicitConversion (ec, e, TypeManager.object_type, loc);
+                               }
+                               operands [i] = new Argument (e, Argument.AType.Expression);
+                       }
+                       
+                       //
+                       // Find the right method
+                       //
+                       switch (operands.Count) {
+                       case 1:
+                               //
+                               // This should not be possible, because simple constant folding
+                               // is taken care of in the Binary code.
+                               //
+                               throw new Exception ("how did you get here?");
+                       
+                       case 2:
+                               concat_method = is_strings_only ? 
+                                       TypeManager.string_concat_string_string :
+                                       TypeManager.string_concat_object_object ;
+                               break;
+                       case 3:
+                               concat_method = is_strings_only ? 
+                                       TypeManager.string_concat_string_string_string :
+                                       TypeManager.string_concat_object_object_object ;
+                               break;
+                       case 4:
+                               //
+                               // There is not a 4 param overlaod for object (the one that there is
+                               // is actually a varargs methods, and is only in corlib because it was
+                               // introduced there before.).
+                               //
+                               if (!is_strings_only)
+                                       goto default;
+                               
+                               concat_method = TypeManager.string_concat_string_string_string_string;
+                               break;
+                       default:
+                               concat_method = is_strings_only ? 
+                                       TypeManager.string_concat_string_dot_dot_dot :
+                                       TypeManager.string_concat_object_dot_dot_dot ;
+                               break;
+                       }
+                       
+                       Invocation.EmitArguments (ec, concat_method, operands);
+                       ec.ig.Emit (OpCodes.Call, concat_method);
+               }
+       }
+
        //
        // Object created with +/= on delegates
        //
@@ -3264,7 +3362,9 @@ namespace Mono.CSharp {
                        ArrayList arguments = new ArrayList ();
                        arguments.Add (new Argument (left, Argument.AType.Expression));
                        arguments.Add (new Argument (right, Argument.AType.Expression));
-                       method = Invocation.OverloadResolve (ec, (MethodGroupExpr) operator_group, arguments, loc) as MethodInfo;
+                       method = Invocation.OverloadResolve (
+                               ec, (MethodGroupExpr) operator_group, arguments, false, loc)
+                               as MethodInfo;
                        if ((method == null) || (method.ReturnType != type)) {
                                Error19 ();
                                return null;
@@ -3904,6 +4004,10 @@ namespace Mono.CSharp {
 
                public bool ResolveMethodGroup (EmitContext ec, Location loc)
                {
+                       ConstructedType ctype = Expr as ConstructedType;
+                       if (ctype != null)
+                               Expr = ctype.GetMemberAccess (ec);
+
                        // FIXME: csc doesn't report any error if you try to use `ref' or
                        //        `out' in a delegate creation expression.
                        Expr = Expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
@@ -3931,6 +4035,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){
                                //
@@ -3976,8 +4098,9 @@ namespace Mono.CSharp {
                                                
                                                pr.AddressOf (ec, mode);
                                        }
-                               } else
+                               } else {
                                        ((IMemoryLocation)Expr).AddressOf (ec, mode);
+                               }
                        } else
                                Expr.Emit (ec);
                }
@@ -4061,8 +4184,7 @@ namespace Mono.CSharp {
                                                      " does not resolve its type");
 
                        //
-                       // This is a special case since csc behaves this way. I can't find
-                       // it anywhere in the spec but oh well ...
+                       // This is a special case since csc behaves this way.
                        //
                        if (argument_expr is NullLiteral &&
                             p == TypeManager.string_type &&
@@ -4073,6 +4195,25 @@ namespace Mono.CSharp {
                                  q == TypeManager.string_type)
                                return 0;
                        
+                        //
+                        // csc behaves this way so we emulate it. Basically, if the argument
+                        // is null and one of the types to compare is 'object' and the other
+                        // is a reference type, we prefer the other.
+                        //
+                        // I can't find this anywhere in the spec but we can interpret this
+                        // to mean that null can be of any type you wish in such a context
+                        //
+                        if (p != null && q != null) {
+                                if (argument_expr is NullLiteral &&
+                                    !p.IsValueType &&
+                                    q == TypeManager.object_type)
+                                        return 1;
+                                else if (argument_expr is NullLiteral &&
+                                         !q.IsValueType &&
+                                         p == TypeManager.object_type)
+                                        return 0;
+                        }
+                                
                        if (p == q)
                                return 0;
                        
@@ -4229,7 +4370,6 @@ namespace Mono.CSharp {
                        // best method, we cant tell. This happens
                        // if we have:
                        // 
-                       //
                        //      interface IFoo {
                        //              void DoIt ();
                        //      }
@@ -4244,6 +4384,7 @@ namespace Mono.CSharp {
                        //
                        // However, we have to consider that
                        // Trim (); is better than Trim (params char[] chars);
+                        //
                        if (cand_count == 0 && argument_count == 0)
                                return best == null || best_params ? 1 : 0;
 
@@ -4329,6 +4470,9 @@ namespace Mono.CSharp {
                {
                        string ret_type = "";
 
+                        if (mb == null)
+                                return "";
+
                        if (mb is MethodInfo)
                                ret_type = TypeManager.CSharpName (((MethodInfo) mb).ReturnType);
                        
@@ -4400,6 +4544,16 @@ namespace Mono.CSharp {
                        return union;
                }
 
+               static bool IsParamsMethodApplicable (EmitContext ec, MethodGroupExpr me,
+                                                     ArrayList arguments, ref MethodBase candidate)
+               {
+                       if (!me.HasTypeArguments &&
+                           !InferParamsTypeArguments (ec, arguments, ref candidate))
+                               return false;
+
+                       return IsParamsMethodApplicable (ec, arguments, candidate);
+               }
+
                /// <summary>
                ///   Determines if the candidate method, if a params method, is applicable
                ///   in its expanded form to the given set of arguments
@@ -4477,6 +4631,16 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               static bool IsApplicable (EmitContext ec, MethodGroupExpr me,
+                                         ArrayList arguments, ref MethodBase candidate)
+               {
+                       if (!me.HasTypeArguments &&
+                           !InferTypeArguments (ec, arguments, ref candidate))
+                               return false;
+
+                       return IsApplicable (ec, arguments, candidate);
+               }
+
                /// <summary>
                ///   Determines if the candidate method is applicable (section 14.4.2.1)
                ///   to the given set of arguments
@@ -4532,8 +4696,6 @@ namespace Mono.CSharp {
                        return true;
                }
                
-               
-
                /// <summary>
                ///   Find the Applicable Function Members (7.4.2.1)
                ///
@@ -4551,7 +4713,8 @@ namespace Mono.CSharp {
                ///
                /// </summary>
                public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
-                                                         ArrayList Arguments, Location loc)
+                                                         ArrayList Arguments, bool may_fail,
+                                                         Location loc)
                {
                        MethodBase method = null;
                        Type applicable_type = null;
@@ -4563,6 +4726,8 @@ namespace Mono.CSharp {
                         // and whether it is being considered in its
                         // normal or expanded form
                         //
+                        // false is normal form, true is expanded form
+                        //
                         Hashtable candidate_to_form = new PtrHashtable ();
 
 
@@ -4581,8 +4746,10 @@ namespace Mono.CSharp {
 
                         bool found_applicable = false;
 
-                       foreach (MethodBase candidate in me.Methods){
-                                Type decl_type = candidate.DeclaringType;
+                       MethodBase[] methods = me.Methods;
+
+                       for (int i = 0; i < methods.Length; i++) {
+                                Type decl_type = methods [i].DeclaringType;
 
                                 //
                                 // If we have already found an applicable method
@@ -4594,25 +4761,29 @@ namespace Mono.CSharp {
                                     found_applicable)
                                        continue;
 
-
                                // Check if candidate is applicable (section 14.4.2.1)
-                               if (IsApplicable (ec, Arguments, candidate)) {
+                               if (IsApplicable (ec, me, Arguments, ref methods [i])) {
                                        // Candidate is applicable in normal form
+                                       MethodBase candidate = methods [i];
                                        candidates.Add (candidate);
                                        applicable_type = candidate.DeclaringType;
                                        found_applicable = true;
                                        candidate_to_form [candidate] = false;
-                               } else {
-                                        if (IsParamsMethodApplicable (ec, Arguments, candidate)) {
-                                                // Candidate is applicable in expanded form
-                                                candidates.Add (candidate);
-                                                applicable_type = candidate.DeclaringType;
-                                                found_applicable = true; 
-                                                candidate_to_form [candidate] = true;
-                                        }
+                               } else if (IsParamsMethodApplicable (ec, me, Arguments, ref methods [i])) {
+                                       // Candidate is applicable in expanded form
+                                       MethodBase candidate = methods [i];
+                                       candidates.Add (candidate);
+                                       applicable_type = candidate.DeclaringType;
+                                       found_applicable = true; 
+                                       candidate_to_form [candidate] = true;
                                }
                        }
 
+                       if (Arguments == null)
+                               argument_count = 0;
+                       else
+                               argument_count = Arguments.Count;
+
                         //
                         // Now we actually find the best method
                         //
@@ -4636,37 +4807,61 @@ namespace Mono.CSharp {
                                 method = candidate;
                         }
 
-                       if (Arguments == null)
-                               argument_count = 0;
-                       else
-                               argument_count = Arguments.Count;
-                       
-
                        if (method == null) {
+                               int errors = Report.Errors;
+
                                //
                                // Okay so we have failed to find anything so we
                                // return by providing info about the closest match
                                //
-                               for (int i = 0; i < me.Methods.Length; ++i) {
+                               for (int i = 0; i < methods.Length; ++i) {
 
-                                       MethodBase c = (MethodBase) me.Methods [i];
-                                       ParameterData pd = GetParameterData (c);
+                                       MethodBase c = methods [i];
+                                       if (c == null)
+                                               continue;
 
+                                       ParameterData pd = GetParameterData (c);
                                        if (pd.Count != argument_count)
                                                continue;
 
-                                       VerifyArgumentsCompat (ec, Arguments, argument_count, c, false,
-                                                              null, loc);
+                                       if (!InferTypeArguments (ec, Arguments, ref c))
+                                               continue;
+
+                                       VerifyArgumentsCompat (ec, Arguments, argument_count,
+                                                              c, false, null, loc);
                                         break;
                                }
 
-                                if (!Location.IsNull (loc)) {
-                                        string report_name = me.Name;
-                                        if (report_name == ".ctor")
-                                                report_name = me.DeclaringType.ToString ();
+                               if (Report.Errors > errors)
+                                       return null;
+
+                               string report_name = me.Name;
+                               if (report_name == ".ctor")
+                                       report_name = me.DeclaringType.ToString ();
                                         
-                                        Error_WrongNumArguments (loc, report_name, argument_count);
-                                }
+                               for (int i = 0; i < methods.Length; ++i) {
+
+                                       MethodBase c = methods [i];
+                                       if (c == null)
+                                               continue;
+
+                                       ParameterData pd = GetParameterData (c);
+                                       if (pd.Count != argument_count)
+                                               continue;
+
+                                       if (InferTypeArguments (ec, Arguments, ref c))
+                                               continue;
+
+                                       Report.Error (411, loc, "The type arguments for " +
+                                                     "method `{0}' cannot be infered from " +
+                                                     "the usage. Try specifying the type " +
+                                                     "arguments explicitly.", report_name);
+                                        break;
+                               }
+
+                                if (!may_fail && (errors == Report.Errors))
+                                        Error_WrongNumArguments (loc, report_name,
+                                                                argument_count);
                                 
                                return null;
                        }
@@ -4691,9 +4886,9 @@ namespace Mono.CSharp {
                                // applicable so we debar the params
                                // method.
                                //
-                                if ((IsParamsMethodApplicable (ec, Arguments, candidate) &&
-                                     IsApplicable (ec, Arguments, method)))
-                                        continue;
+                                // if ((IsParamsMethodApplicable (ec, Arguments, candidate) &&
+//                                      IsApplicable (ec, Arguments, method)))
+//                                         continue;
                                 
                                 bool cand_params = (bool) candidate_to_form [candidate];
                                int x = BetterFunction (ec, Arguments,
@@ -4839,6 +5034,238 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               static bool InferType (Type pt, Type at, ref Type[] infered)
+               {
+                       if (pt.IsGenericParameter) {
+                               int pos = pt.GenericParameterPosition;
+
+                               if (infered [pos] == null) {
+                                       Type check = at;
+                                       while (check.IsArray)
+                                               check = check.GetElementType ();
+
+                                       if (pt.Equals (check))
+                                               return false;
+
+                                       infered [pos] = at;
+                                       return true;
+                               }
+
+                               if (infered [pos] != at)
+                                       return false;
+
+                               return true;
+                       }
+
+                       if (!pt.ContainsGenericParameters)
+                               return true;
+
+                       if (at.IsArray) {
+                               if (!pt.IsArray ||
+                                   (at.GetArrayRank () != pt.GetArrayRank ()))
+                                       return false;
+
+                               return InferType (pt.GetElementType (), at.GetElementType (),
+                                                 ref infered);
+                       }
+
+                       if (pt.IsArray) {
+                               if (!at.IsArray ||
+                                   (pt.GetArrayRank () != at.GetArrayRank ()))
+                                       return false;
+
+                               return InferType (pt.GetElementType (), at.GetElementType (),
+                                                 ref infered);
+                       }
+
+                       if (!at.IsGenericInstance)
+                               return false;
+
+                       Type[] at_args = at.GetGenericArguments ();
+                       Type[] pt_args = pt.GetGenericArguments ();
+
+                       if (at_args.Length != pt_args.Length)
+                               return false;
+
+                       Type[] infered_types = new Type [at_args.Length];
+
+                       for (int i = 0; i < at_args.Length; i++)
+                               if (!InferType (pt_args [i], at_args [i], ref infered_types))
+                                       return false;
+
+                       for (int i = 0; i < infered_types.Length; i++)
+                               if (infered_types [i] == null)
+                                       return false;
+
+                       for (int i = 0; i < infered_types.Length; i++) {
+                               if (infered [i] == null) {
+                                       infered [i] = infered_types [i];
+                                       continue;
+                               }
+
+                               if (infered [i] != infered_types [i])
+                                       return false;
+                       }
+
+                       return true;
+               }
+
+               static bool InferParamsTypeArguments (EmitContext ec, ArrayList arguments,
+                                                     ref MethodBase method)
+               {
+                       if ((arguments == null) || !TypeManager.IsGenericMethod (method))
+                               return true;
+
+                       int arg_count;
+                       
+                       if (arguments == null)
+                               arg_count = 0;
+                       else
+                               arg_count = arguments.Count;
+                       
+                       ParameterData pd = GetParameterData (method);
+
+                       int pd_count = pd.Count;
+
+                       if (pd_count == 0)
+                               return false;
+                       
+                       if (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS)
+                               return false;
+                       
+                       if (pd_count - 1 > arg_count)
+                               return false;
+                       
+                       if (pd_count == 1 && arg_count == 0)
+                               return true;
+
+                       Type[] method_args = method.GetGenericArguments ();
+                       Type[] infered_types = new Type [method_args.Length];
+
+                       //
+                       // If we have come this far, the case which
+                       // remains is when the number of parameters is
+                       // less than or equal to the argument count.
+                       //
+                       for (int i = 0; i < pd_count - 1; ++i) {
+                               Argument a = (Argument) arguments [i];
+
+                               if ((a.Expr is NullLiteral) || (a.Expr is MethodGroupExpr))
+                                       continue;
+
+                               Type pt = pd.ParameterType (i);
+                               Type at = a.Type;
+
+                               if (!InferType (pt, at, ref infered_types))
+                                       return false;
+                       }
+
+                       Type element_type = TypeManager.GetElementType (pd.ParameterType (pd_count - 1));
+
+                       for (int i = pd_count - 1; i < arg_count; i++) {
+                               Argument a = (Argument) arguments [i];
+
+                               if ((a.Expr is NullLiteral) || (a.Expr is MethodGroupExpr))
+                                       continue;
+
+                               if (!InferType (element_type, a.Type, ref infered_types))
+                                       return false;
+                       }
+
+                       for (int i = 0; i < infered_types.Length; i++)
+                               if (infered_types [i] == null)
+                                       return false;
+
+                       method = method.BindGenericParameters (infered_types);
+                       return true;
+               }
+
+               public static bool InferTypeArguments (Type[] param_types, Type[] arg_types,
+                                                      ref Type[] infered_types)
+               {
+                       for (int i = 0; i < arg_types.Length; i++) {
+                               if (arg_types [i] == null)
+                                       continue;
+
+                               if (!InferType (param_types [i], arg_types [i],
+                                               ref infered_types))
+                                       return false;
+                       }
+
+                       for (int i = 0; i < infered_types.Length; i++)
+                               if (infered_types [i] == null)
+                                       return false;
+
+                       return true;
+               }
+
+               static bool InferTypeArguments (EmitContext ec, ArrayList arguments,
+                                               ref MethodBase method)
+               {
+                       if (!TypeManager.IsGenericMethod (method))
+                               return true;
+
+                       int arg_count;
+                       if (arguments != null)
+                               arg_count = arguments.Count;
+                       else
+                               arg_count = 0;
+
+                       ParameterData pd = GetParameterData (method);
+                       if (arg_count != pd.Count)
+                               return false;
+
+                       Type[] method_args = method.GetGenericArguments ();
+                       Type[] infered_types = new Type [method_args.Length];
+
+                       Type[] param_types = new Type [pd.Count];
+                       Type[] arg_types = new Type [pd.Count];
+
+                       for (int i = 0; i < arg_count; i++) {
+                               param_types [i] = pd.ParameterType (i);
+
+                               Argument a = (Argument) arguments [i];
+                               if ((a.Expr is NullLiteral) || (a.Expr is MethodGroupExpr))
+                                       continue;
+
+                               arg_types [i] = a.Type;
+                       }
+
+                       if (!InferTypeArguments (param_types, arg_types, ref infered_types))
+                               return false;
+
+                       method = method.BindGenericParameters (infered_types);
+                       return true;
+               }
+
+               public static bool InferTypeArguments (EmitContext ec, ParameterData apd,
+                                                      ref MethodBase method)
+               {
+                       if (!TypeManager.IsGenericMethod (method))
+                               return true;
+
+                       ParameterData pd = GetParameterData (method);
+                       if (apd.Count != pd.Count)
+                               return false;
+
+                       Type[] method_args = method.GetGenericArguments ();
+                       Type[] infered_types = new Type [method_args.Length];
+
+                       Type[] param_types = new Type [pd.Count];
+                       Type[] arg_types = new Type [pd.Count];
+
+                       for (int i = 0; i < apd.Count; i++) {
+                               param_types [i] = pd.ParameterType (i);
+                               arg_types [i] = apd.ParameterType (i);
+                       }
+
+                       if (!InferTypeArguments (param_types, arg_types, ref infered_types))
+                               return false;
+
+                       method = method.BindGenericParameters (infered_types);
+                       return true;
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        //
@@ -4882,13 +5309,10 @@ namespace Mono.CSharp {
                        }
 
                        MethodGroupExpr mg = (MethodGroupExpr) expr;
-                       method = OverloadResolve (ec, mg, Arguments, loc);
+                       method = OverloadResolve (ec, mg, Arguments, false, loc);
 
-                       if (method == null){
-                               Error (-6,
-                                      "Could not find any applicable function for this argument list");
+                       if (method == null)
                                return null;
-                       }
 
                        MethodInfo mi = method as MethodInfo;
                        if (mi != null) {
@@ -4931,19 +5355,15 @@ namespace Mono.CSharp {
                        int count = arguments.Count - idx;
                        Argument a = (Argument) arguments [idx];
                        Type t = a.Expr.Type;
-                       string array_type = t.FullName + "[]";
-                       LocalBuilder array;
 
-                       array = ig.DeclareLocal (TypeManager.LookupType (array_type));
                        IntConstant.EmitInt (ig, count);
                        ig.Emit (OpCodes.Newarr, TypeManager.TypeToCoreType (t));
-                       ig.Emit (OpCodes.Stloc, array);
 
                        int top = arguments.Count;
                        for (int j = idx; j < top; j++){
                                a = (Argument) arguments [j];
                                
-                               ig.Emit (OpCodes.Ldloc, array);
+                               ig.Emit (OpCodes.Dup);
                                IntConstant.EmitInt (ig, j - idx);
 
                                bool is_stobj, has_type_arg;
@@ -4958,7 +5378,6 @@ namespace Mono.CSharp {
                                else
                                        ig.Emit (op);
                        }
-                       ig.Emit (OpCodes.Ldloc, array);
                }
                
                /// <summary>
@@ -5088,18 +5507,17 @@ namespace Mono.CSharp {
                                        this_call = true;
                                        ig.Emit (OpCodes.Ldarg_0);
                                } else {
+                                       Type itype = instance_expr.Type;
+
                                        //
                                        // Push the instance expression
                                        //
-                                       if (TypeManager.IsValueType (instance_expr.Type)){
+                                       if (TypeManager.IsValueType (itype)){
                                                //
                                                // Special case: calls to a function declared in a 
                                                // reference-type with a value-type argument need
                                                // to have their value boxed.  
-
-                                               if (!instance_expr.Type.IsGenericParameter)
-                                                       struct_call = true;
-                                               if (TypeManager.IsValueType (decl_type)){
+                                               if (decl_type.IsValueType || itype.IsGenericParameter){
                                                        //
                                                        // If the expression implements IMemoryLocation, then
                                                        // we can optimize and use AddressOf on the
@@ -5112,16 +5530,18 @@ namespace Mono.CSharp {
                                                                        AddressOf (ec, AddressOp.LoadStore);
                                                        }
                                                        else {
-                                                               Type t = instance_expr.Type;
-                                                               
                                                                instance_expr.Emit (ec);
-                                                               LocalBuilder temp = ig.DeclareLocal (t);
+                                                               LocalBuilder temp = ig.DeclareLocal (itype);
                                                                ig.Emit (OpCodes.Stloc, temp);
                                                                ig.Emit (OpCodes.Ldloca, temp);
                                                        }
+                                                       if (itype.IsGenericParameter)
+                                                               ig.Emit (OpCodes.Constrained, itype);
+                                                       else
+                                                               struct_call = true;
                                                } else {
                                                        instance_expr.Emit (ec);
-                                                       ig.Emit (OpCodes.Box, instance_expr.Type);
+                                                       ig.Emit (OpCodes.Box, itype);
                                                } 
                                        } else
                                                instance_expr.Emit (ec);
@@ -5307,6 +5727,7 @@ namespace Mono.CSharp {
                //
                Expression value_target;
                bool value_target_set = false;
+               bool is_type_parameter = false;
                
                public New (Expression requested_type, ArrayList arguments, Location l)
                {
@@ -5384,7 +5805,28 @@ namespace Mono.CSharp {
                                return RequestedType;
                        }
 
-                       if (type.IsInterface || type.IsAbstract){
+                       if (type.IsGenericParameter) {
+                               if (!TypeManager.HasConstructorConstraint (type)) {
+                                       Error (304, String.Format (
+                                                      "Cannot create an instance of the " +
+                                                      "variable type '{0}' because it " +
+                                                      "doesn't have the new() constraint",
+                                                      type));
+                                       return null;
+                               }
+
+                               if ((Arguments != null) && (Arguments.Count != 0)) {
+                                       Error (417, String.Format (
+                                                      "`{0}': cannot provide arguments " +
+                                                      "when creating an instance of a " +
+                                                      "variable type.", type));
+                                       return null;
+                               }
+
+                               is_type_parameter = true;
+                               eclass = ExprClass.Value;
+                               return this;
+                       } else if (type.IsInterface || type.IsAbstract){
                                Error (144, "It is not possible to create instances of interfaces or abstract classes");
                                return null;
                        }
@@ -5400,7 +5842,7 @@ namespace Mono.CSharp {
                                return this;
                        
                        Expression ml;
-                       ml = MemberLookupFinal (ec, null, type, ".ctor", 0,
+                       ml = MemberLookupFinal (ec, null, type, ".ctor",
                                                MemberTypes.Constructor,
                                                AllBindingFlags | BindingFlags.DeclaredOnly, loc);
 
@@ -5422,7 +5864,8 @@ namespace Mono.CSharp {
                                        }
                                }
 
-                               method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, Arguments, loc);
+                               method = Invocation.OverloadResolve (
+                                       ec, (MethodGroupExpr) ml, Arguments, false, loc);
                                
                        }
 
@@ -5438,6 +5881,18 @@ namespace Mono.CSharp {
                        return this;
                }
 
+               bool DoEmitTypeParameter (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       ig.Emit (OpCodes.Ldtoken, type);
+                       ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
+                       ig.Emit (OpCodes.Call, TypeManager.activator_create_instance);
+                       ig.Emit (OpCodes.Unbox_Any, type);
+
+                       return true;
+               }
+
                //
                // This DoEmit can be invoked in two contexts:
                //    * As a mechanism that will leave a value on the stack (new object)
@@ -5501,17 +5956,26 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       DoEmit (ec, true);
+                       if (is_type_parameter)
+                               DoEmitTypeParameter (ec);
+                       else
+                               DoEmit (ec, true);
                }
                
                public override void EmitStatement (EmitContext ec)
                {
+                       if (is_type_parameter)
+                               throw new InvalidOperationException ();
+
                        if (DoEmit (ec, false))
                                ec.ig.Emit (OpCodes.Pop);
                }
 
                public void AddressOf (EmitContext ec, AddressOp Mode)
                {
+                       if (is_type_parameter)
+                               throw new InvalidOperationException ();
+
                        if (!type.IsValueType){
                                //
                                // We throw an exception.  So far, I believe we only need to support
@@ -5925,7 +6389,8 @@ namespace Mono.CSharp {
                                        return null;
                                }
                                
-                               new_method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, arguments, loc);
+                               new_method = Invocation.OverloadResolve (
+                                       ec, (MethodGroupExpr) ml, arguments, false, loc);
 
                                if (new_method == null) {
                                        Error (-6, "New invocation: Can not find a constructor for " +
@@ -6143,9 +6608,6 @@ namespace Mono.CSharp {
                        int dims = bounds.Count;
                        int [] current_pos = new int [dims];
                        int top = array_data.Count;
-                       LocalBuilder temp = ig.DeclareLocal (type);
-
-                       ig.Emit (OpCodes.Stloc, temp);
 
                        MethodInfo set = null;
 
@@ -6187,7 +6649,8 @@ namespace Mono.CSharp {
                                            num_automatic_initializers <= max_automatic_initializers) {
                                                Type etype = e.Type;
                                                
-                                               ig.Emit (OpCodes.Ldloc, temp);
+                                               if (is_expression || i != top - 1)
+                                                       ig.Emit (OpCodes.Dup);
 
                                                for (int idx = 0; idx < dims; idx++) 
                                                        IntConstant.EmitInt (ig, current_pos [idx]);
@@ -6233,9 +6696,6 @@ namespace Mono.CSharp {
                                        current_pos [j] = 0;
                                }
                        }
-
-                       if (is_expression)
-                               ig.Emit (OpCodes.Ldloc, temp);
                }
 
                void EmitArrayArguments (EmitContext ec)
@@ -6424,8 +6884,8 @@ namespace Mono.CSharp {
                public override void Emit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
-                       
-                       ig.Emit (OpCodes.Ldarg_0);
+
+                       ec.EmitThis ();
                        if (ec.TypeContainer is Struct)
                                ig.Emit (OpCodes.Ldobj, type);
                }
@@ -6435,7 +6895,7 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
                        
                        if (ec.TypeContainer is Struct){
-                               ig.Emit (OpCodes.Ldarg_0);
+                               ec.EmitThis ();
                                source.Emit (ec);
                                ig.Emit (OpCodes.Stobj, type);
                        } else {
@@ -6446,7 +6906,7 @@ namespace Mono.CSharp {
 
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
-                       ec.ig.Emit (OpCodes.Ldarg_0);
+                       ec.EmitThis ();
 
                        // FIMXE
                        // FIGURE OUT WHY LDARG_S does not work
@@ -6599,9 +7059,9 @@ namespace Mono.CSharp {
        ///   Implements the member access expression
        /// </summary>
        public class MemberAccess : Expression {
-               public readonly string Identifier;
-               public readonly int NumTypeArguments;
+               public string Identifier;
                protected Expression expr;
+               protected TypeArguments args;
                
                public MemberAccess (Expression expr, string id, Location l)
                {
@@ -6610,11 +7070,11 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               protected MemberAccess (Expression expr, string id, int num_type_args,
-                                       Location l)
+               public MemberAccess (Expression expr, string id, TypeArguments args,
+                                    Location l)
                        : this (expr, id, l)
                {
-                       NumTypeArguments = num_type_args;
+                       this.args = args;
                }
 
                public Expression Expr {
@@ -6641,7 +7101,7 @@ namespace Mono.CSharp {
 
                        SimpleName sn = (SimpleName) left_original;
 
-                       Type t = RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc);
+                       TypeExpr t = RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc);
                        if (t != null)
                                return true;
 
@@ -6677,10 +7137,10 @@ namespace Mono.CSharp {
                                        Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
                                        
                                        if (c != null) {
-                                               object o = c.LookupConstantValue ();
-                                               if (o == null)
+                                               object o;
+                                               if (!c.LookupConstantValue (out o))
                                                        return null;
-                                               
+
                                                object real_value = ((Constant) c.Expr).GetValue ();
 
                                                return Constantify (real_value, fi.FieldType);
@@ -6897,15 +7357,21 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       int real_num_type_args = NumTypeArguments +
-                               TypeManager.GetNumberOfTypeArguments (expr_type);
-                       
+                       int errors = Report.Errors;
+
                        Expression member_lookup;
-                       member_lookup = MemberLookupFinal (ec, expr_type, expr_type,
-                                                          Identifier, real_num_type_args,
-                                                          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)) {
@@ -6916,11 +7382,84 @@ namespace Mono.CSharp {
 
                                return member_lookup;
                        }
+
+                       if (args != null) {
+                               string full_name = expr_type + "." + Identifier;
+
+                               if (member_lookup is FieldExpr) {
+                                       Report.Error (307, loc, "The field `{0}' cannot " +
+                                                     "be used with type arguments", full_name);
+                                       return null;
+                               } else if (member_lookup is EventExpr) {
+                                       Report.Error (307, loc, "The event `{0}' cannot " +
+                                                     "be used with type arguments", full_name);
+                                       return null;
+                               } else if (member_lookup is PropertyExpr) {
+                                       Report.Error (307, loc, "The property `{0}' cannot " +
+                                                     "be used with type arguments", full_name);
+                                       return null;
+                               }
+                       }
                        
                        member_lookup = ResolveMemberAccess (ec, member_lookup, expr, loc, original);
                        if (member_lookup == null)
                                return null;
 
+                       if (args != null) {
+                               MethodGroupExpr mg = member_lookup as MethodGroupExpr;
+                               if (mg == null)
+                                       throw new InternalErrorException ();
+
+                               if (args.Resolve (ec) == false)
+                                       return null;
+
+                               Type[] atypes = args.Arguments;
+
+                               int first_count = 0;
+                               MethodInfo first = null;
+
+                               ArrayList list = new ArrayList ();
+                               foreach (MethodBase mb in mg.Methods) {
+                                       MethodInfo mi = mb as MethodInfo;
+                                       if ((mi == null) || !mi.HasGenericParameters)
+                                               continue;
+
+                                       Type[] gen_params = mi.GetGenericArguments ();
+
+                                       if (first == null) {
+                                               first = mi;
+                                               first_count = gen_params.Length;
+                                       }
+
+                                       if (gen_params.Length != atypes.Length)
+                                               continue;
+
+                                       list.Add (mi.BindGenericParameters (atypes));
+                               }
+
+                               if (list.Count > 0) {
+                                       MethodGroupExpr new_mg = new MethodGroupExpr (
+                                               list, mg.Location);
+                                       new_mg.InstanceExpression = mg.InstanceExpression;
+                                       new_mg.HasTypeArguments = true;
+                                       return new_mg;
+                               }
+
+                               string name = expr_type + "." + Identifier;
+
+                               if (first != null)
+                                       Report.Error (
+                                               305, loc, "Using the generic method `{0}' " +
+                                               "requires {1} type arguments", name,
+                                               first_count);
+                               else
+                                       Report.Error (
+                                               308, loc, "The non-generic method `{0}' " +
+                                               "cannot be used with type arguments", name);
+
+                               return null;
+                       }
+
                        // The following DoResolve/DoResolveLValue will do the definite assignment
                        // check.
 
@@ -6956,7 +7495,7 @@ namespace Mono.CSharp {
 
                                if (full_expr.Expr is SimpleName) {
                                        string full_name = String.Concat (((SimpleName) full_expr.Expr).Name, ".", fname);
-                                       Type fully_qualified = ec.DeclSpace.FindType (loc, full_name, 0);
+                                       Type fully_qualified = ec.DeclSpace.FindType (loc, full_name);
                                        if (fully_qualified != null)
                                                return new TypeExpression (fully_qualified, loc);
                                }
@@ -6985,22 +7524,44 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       int real_num_type_args = NumTypeArguments +
-                               TypeManager.GetNumberOfTypeArguments (expr_type);
-                       
                        Expression member_lookup;
-                       member_lookup = MemberLookupFinal (ec, expr_type, expr_type,
-                                                          Identifier, real_num_type_args,
-                                                          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)
@@ -7010,7 +7571,10 @@ namespace Mono.CSharp {
 
                public override string ToString ()
                {
-                       return expr + "." + Identifier;
+                       if (args != null)
+                               return expr + "." + Identifier + "!" + args.Count;
+                       else
+                               return expr + "." + Identifier;
                }
        }
 
@@ -7318,7 +7882,9 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Ldelem_R8);
                        else if (type == TypeManager.intptr_type)
                                ig.Emit (OpCodes.Ldelem_I);
-                       else if (type.IsValueType){
+                       else if (TypeManager.IsEnumType (type)){
+                               EmitLoadOpcode (ig, TypeManager.EnumToUnderlying (type));
+                       } else if (type.IsValueType){
                                ig.Emit (OpCodes.Ldelema, type);
                                ig.Emit (OpCodes.Ldobj, type);
                        } else if (type.IsGenericParameter)
@@ -7608,7 +8174,7 @@ namespace Mono.CSharp {
                        string p_name = TypeManager.IndexerPropertyName (lookup_type);
 
                        MemberInfo [] mi = TypeManager.MemberLookup (
-                               caller_type, caller_type, lookup_type, 0, MemberTypes.Property,
+                               caller_type, caller_type, lookup_type, MemberTypes.Property,
                                BindingFlags.Public | BindingFlags.Instance |
                                BindingFlags.DeclaredOnly, p_name);
 
@@ -7729,7 +8295,8 @@ namespace Mono.CSharp {
                        if (AllGetters.Count > 0) {
                                found_any_getters = true;
                                get = (MethodInfo) Invocation.OverloadResolve (
-                                       ec, new MethodGroupExpr (AllGetters, loc), arguments, loc);
+                                       ec, new MethodGroupExpr (AllGetters, loc),
+                                       arguments, false, loc);
                        }
 
                        if (!found_any) {
@@ -7793,7 +8360,7 @@ namespace Mono.CSharp {
                                set_arguments.Add (new Argument (right_side, Argument.AType.Expression));
                                set = (MethodInfo) Invocation.OverloadResolve (
                                        ec, new MethodGroupExpr (AllSetters, loc),
-                                       set_arguments, loc);
+                                       set_arguments, false, loc);
                        }
 
                        if (!found_any) {
@@ -7908,13 +8475,18 @@ namespace Mono.CSharp {
                                Error (1511, "Keyword base is not allowed in static method");
                                return null;
                        }
+
+                       if (ec.IsFieldInitializer){
+                               Error (1512, "Keyword base is not available in the current context");
+                               return null;
+                       }
                        
                        member_lookup = MemberLookup (ec, ec.ContainerType, null, base_type,
-                                                     member, 0, AllMemberTypes,
-                                                     AllBindingFlags, loc);
+                                                     member, AllMemberTypes, AllBindingFlags,
+                                                     loc);
                        if (member_lookup == null) {
-                               MemberLookupFailed (ec, base_type, base_type, member,
-                                                   0, null, loc);
+                               MemberLookupFailed (
+                                       ec, base_type, base_type, member, null, loc);
                                return null;
                        }
 
@@ -8077,6 +8649,7 @@ namespace Mono.CSharp {
                        int pos = 0;
                        while ((pos < dim.Length) && (dim [pos] == '[')) {
                                pos++;
+
                                if (dim [pos] == ']') {
                                        ltype = ltype.MakeArrayType ();
                                        pos++;
@@ -8090,8 +8663,9 @@ namespace Mono.CSharp {
                                }
 
                                int rank = 0;
-                               while (dim [pos++] == ',')
-                                       rank++;
+                               while (dim [pos] == ',') {
+                                       pos++; rank++;
+                               }
 
                                if ((dim [pos] != ']') || (pos != dim.Length-1))
                                        return null;
@@ -8105,7 +8679,8 @@ namespace Mono.CSharp {
                        // ltype.Fullname is already fully qualified, so we can skip
                        // a lot of probes, and go directly to TypeManager.LookupType
                        //
-                       string cname = ltype.FullName + dim;
+                       string fname = ltype.FullName != null ? ltype.FullName : ltype.Name;
+                       string cname = fname + dim;
                        type = TypeManager.LookupTypeDirect (cname);
                        if (type == null){
                                //
@@ -8114,9 +8689,13 @@ namespace Mono.CSharp {
                                //
                                // For now, fall back to the full lookup in that case.
                                //
-                               type = RootContext.LookupType (
+                               TypeExpr texpr = RootContext.LookupType (
                                        ec.DeclSpace, cname, false, loc);
 
+                               if (texpr == null)
+                                       return null;
+
+                               type = texpr.ResolveType (ec);
                                if (type == null)
                                        return null;
                        }