2005-09-05 Miguel de Icaza <miguel@novell.com>
[mono.git] / mcs / bmcs / expression.cs
index afe8249f0c657cc058a0453c5a1d1c9ed16481cb..d8562f5155e6527a8d43bf1bdd13b2e67e33cd9d 100644 (file)
@@ -15,6 +15,7 @@ namespace Mono.CSharp {
        using System.Reflection;
        using System.Reflection.Emit;
        using System.Text;
+       using Microsoft.VisualBasic;
 
        /// <summary>
        ///   This is just a helper class, it is generated by Unary, UnaryMutator
@@ -431,13 +432,15 @@ namespace Mono.CSharp {
                                }
 
                                IVariable variable = Expr as IVariable;
-                               if (!ec.InFixedInitializer && ((variable == null) || !variable.VerifyFixed (false))) {
+                               bool is_fixed = variable != null && variable.VerifyFixed (false);
+
+                               if (!ec.InFixedInitializer && !is_fixed) {
                                        Error (212, "You can only take the address of an unfixed expression inside " +
                                               "of a fixed statement initializer");
                                        return null;
                                }
 
-                               if (ec.InFixedInitializer && ((variable != null) && variable.VerifyFixed (false))) {
+                               if (ec.InFixedInitializer && is_fixed) {
                                        Error (213, "You can not fix an already fixed expression");
                                        return null;
                                }
@@ -581,6 +584,9 @@ namespace Mono.CSharp {
                        if (Expr == null)
                                return null;
 
+                       if (TypeManager.IsNullableType (Expr.Type))
+                               return new Nullable.LiftedUnaryOperator (Oper, Expr, loc).Resolve (ec);
+
                        eclass = ExprClass.Value;
                        return ResolveOperator (ec);
                }
@@ -658,7 +664,7 @@ namespace Mono.CSharp {
        // after semantic analysis (this is so we can take the address
        // of an indirection).
        //
-       public class Indirection : Expression, IMemoryLocation, IAssignMethod {
+       public class Indirection : Expression, IMemoryLocation, IAssignMethod, IVariable {
                Expression expr;
                LocalTemporary temporary;
                bool prepared;
@@ -732,6 +738,21 @@ namespace Mono.CSharp {
                {
                        return "*(" + expr + ")";
                }
+
+               #region IVariable Members
+
+               public VariableInfo VariableInfo {
+                       get {
+                               return null;
+                       }
+               }
+
+               public bool VerifyFixed (bool is_expression)
+               {
+                       return true;
+               }
+
+               #endregion
        }
        
        /// <summary>
@@ -893,6 +914,10 @@ namespace Mono.CSharp {
                                return null;
 
                        eclass = ExprClass.Value;
+
+                       if (TypeManager.IsNullableType (expr.Type))
+                               return new Nullable.LiftedUnaryMutator (mode, expr, loc).Resolve (ec);
+
                        return ResolveOperator (ec);
                }
 
@@ -988,7 +1013,6 @@ namespace Mono.CSharp {
                        this.is_expr = is_expr;
                        ((IAssignMethod) expr).EmitAssign (ec, this, is_expr && (mode == Mode.PreIncrement || mode == Mode.PreDecrement), true);
                }
-               
 
                public override void Emit (EmitContext ec)
                {
@@ -1831,21 +1855,23 @@ namespace Mono.CSharp {
        /// </summary>
        public class Binary : Expression {
                public enum Operator : byte {
-                       Multiply, Division, Modulus,
+                       Exponentiation,
+                       Multiply, Division, 
+                       IntegerDivision, 
+                       Modulus,
                        Addition, Subtraction,
+                       Concatenation,
                        LeftShift, RightShift,
-                       LessThan, GreaterThan, LessThanOrEqual, GreaterThanOrEqual
-                       Equality, Inequality,
-                       BitwiseAnd,
+                               Equality, Inequality, LessThan, GreaterThan, LessThanOrEqual, GreaterThanOrEqual, Like, Is
+                       BitwiseAnd, LogicalAndAlso,
+                       BitwiseOr, LogicalOrElse,
                        ExclusiveOr,
-                       BitwiseOr,
-                       LogicalAnd,
-                       LogicalOr,
                        TOP
                }
 
                Operator oper;
                Expression left, right;
+               Expression intermediate;
 
                // This must be kept in sync with Operator!!!
                public static readonly string [] oper_names;
@@ -1870,8 +1896,8 @@ namespace Mono.CSharp {
                        oper_names [(int) Operator.BitwiseAnd] = "op_BitwiseAnd";
                        oper_names [(int) Operator.BitwiseOr] = "op_BitwiseOr";
                        oper_names [(int) Operator.ExclusiveOr] = "op_ExclusiveOr";
-                       oper_names [(int) Operator.LogicalOr] = "op_LogicalOr";
-                       oper_names [(int) Operator.LogicalAnd] = "op_LogicalAnd";
+                       oper_names [(int) Operator.LogicalOrElse] = "op_LogicalOr";
+                       oper_names [(int) Operator.LogicalAndAlso] = "op_LogicalAnd";
                }
 
                public Binary (Operator oper, Expression left, Expression right, Location loc)
@@ -1916,12 +1942,16 @@ namespace Mono.CSharp {
                static string OperName (Operator oper)
                {
                        switch (oper){
+                       case Operator.Exponentiation:
+                               return "^";
                        case Operator.Multiply:
                                return "*";
                        case Operator.Division:
                                return "/";
+                       case Operator.IntegerDivision:
+                               return "\\";
                        case Operator.Modulus:
-                               return "%";
+                               return "Mod";
                        case Operator.Addition:
                                return "+";
                        case Operator.Subtraction:
@@ -1939,19 +1969,21 @@ namespace Mono.CSharp {
                        case Operator.GreaterThanOrEqual:
                                return ">=";
                        case Operator.Equality:
-                               return "==";
+                               return "=";
                        case Operator.Inequality:
-                               return "!=";
+                               return "<>";
+                       case Operator.Like:
+                               return "Like";
                        case Operator.BitwiseAnd:
-                               return "&";
+                               return "And";
                        case Operator.BitwiseOr:
-                               return "|";
+                               return "Or";
                        case Operator.ExclusiveOr:
-                               return "^";
-                       case Operator.LogicalOr:
-                               return "||";
-                       case Operator.LogicalAnd:
-                               return "&&";
+                               return "Xor";
+                       case Operator.LogicalOrElse:
+                               return "OrElse";
+                       case Operator.LogicalAndAlso:
+                               return "AndAlso";
                        }
 
                        return oper.ToString ();
@@ -2170,6 +2202,13 @@ namespace Mono.CSharp {
                        return (left != null) && (right != null);
                }
 
+               public void Error_OperatorCannotBeAppliedToObjectOperands ()
+               {
+                       Report.Error (30038, loc,
+                              "Operator " + OperName (oper) + " cannot be applied to operands of type `" +
+                              TypeManager.CSharpName (TypeManager.object_type) + "'");
+               }
+               
                static public void Error_OperatorCannotBeApplied (Location loc, string name, Type l, Type r)
                {
                        Report.Error (19, loc,
@@ -2220,38 +2259,89 @@ namespace Mono.CSharp {
                        return null;
                }
                                        
-               Expression CheckShiftArguments (EmitContext ec)
+               void CheckShiftArguments (EmitContext ec)
                {
                        Expression e;
+                       Type assumed_target_type = right.Type;
 
-                       e = ForceConversion (ec, right, TypeManager.int32_type);
+                       e = Convert.ImplicitVBConversion (ec, right, TypeManager.int32_type, Location);
                        if (e == null){
                                Error_OperatorCannotBeApplied ();
-                               return null;
+                               return;
                        }
                        right = e;
 
-                       if (((e = Convert.WideningConversion (ec, left, TypeManager.int32_type, loc)) != null) ||
-                           ((e = Convert.WideningConversion (ec, left, TypeManager.uint32_type, loc)) != null) ||
-                           ((e = Convert.WideningConversion (ec, left, TypeManager.int64_type, loc)) != null) ||
-                           ((e = Convert.WideningConversion (ec, left, TypeManager.uint64_type, loc)) != null)){
-                               left = e;
-                               type = e.Type;
+                       if ( !IsOperatorDefinedForType (left.Type)) {
+                               Expression target_left_expr = ConvertOperandToDefinedType(ec, left);
 
-                               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);
+                               if (target_left_expr == null) {
+                                       Error_OperatorCannotBeApplied();
+                                       return;
                                }
 
-                               return this;
-                       }
-                       Error_OperatorCannotBeApplied ();
-                       return null;
+                               left = target_left_expr;
+                       } else if (left.Type == TypeManager.null_type)
+                               left  = Convert.ImplicitVBConversion (ec, left, assumed_target_type, Location);
+
+                       type = left.Type;
+
+                       int mask = 0x1f;                                
+
+                       if (type == TypeManager.byte_type)
+                               mask = 0x7;
+                       else if (type == TypeManager.short_type)
+                               mask = 0xf;
+                       else if (type == TypeManager.int32_type)
+                               mask = 0x1f;
+                       else if (type == TypeManager.int64_type)
+                               mask = 0x3f;
+                       else
+                               throw new Exception ("This should not happen");
+                        
+                       right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (mask), loc);
+                       right = right.DoResolve (ec);
                }
 
+               void CheckIsArguments (EmitContext ec)
+               {
+                               Type l = left.Type;
+                               Type r = right.Type;
+                               Type = TypeManager.bool_type;
+                               
+                               bool left_is_null = left is NullLiteral;
+                               bool right_is_null = right is NullLiteral;
+
+                               if (left_is_null || right_is_null)
+                                       return;
+
+                               if (l.IsValueType || r.IsValueType) {
+                                       Error_OperatorCannotBeApplied ();
+                                       return;
+                               }
+
+                               
+                               if (l == r)
+                                       return; 
+                                       
+                               if (l.IsSubclassOf (r) || r.IsSubclassOf (l))
+                                       return; 
+
+                               if (!(Convert.WideningStandardConversionExists (ec, left, right.Type) ||
+                                     Convert.WideningStandardConversionExists (ec, right, left.Type))){
+                                       Error_OperatorCannotBeApplied ();
+                                       return;
+                               }
+
+                               if (left.Type != TypeManager.object_type)
+                                       left = new EmptyCast (left, TypeManager.object_type);
+                               if (right.Type != TypeManager.object_type)
+                                       right = new EmptyCast (right, TypeManager.object_type);
+
+                               return;
+               }
+
+               
+#if false
                Expression ResolveOperator (EmitContext ec)
                {
                        Type l = left.Type;
@@ -2399,6 +2489,15 @@ namespace Mono.CSharp {
                                        return this;
                                }
 
+                               bool left_is_null = left is NullLiteral;
+                               bool right_is_null = right is NullLiteral;
+                               if (left_is_null || right_is_null) {
+                                       if (oper == Operator.Equality)
+                                               return new BoolLiteral (left_is_null == right_is_null);
+                                       else
+                                               return new BoolLiteral (left_is_null != right_is_null);
+                               }
+
                                //
                                // operator != (object a, object b)
                                // operator == (object a, object b)
@@ -2458,33 +2557,33 @@ namespace Mono.CSharp {
                                             (r == TypeManager.anonymous_method_type))){
                                                if ((RootContext.Version != LanguageVersion.ISO_1)){
                                                Expression tmp = Convert.WideningConversionRequired (ec, right, l, loc);
-                                               if (tmp == null)
-                                                       return null;
-                                               right = tmp;
-                                               r = right.Type;
-                                       }
+                                                       if (tmp == null)
+                                                               return null;
+                                                       right = tmp;
+                                                       r = right.Type;
+                                               }
                                        }
                                
                                        if (TypeManager.IsDelegateType (r)){
-                                       MethodInfo method;
-                                       ArrayList args = new ArrayList (2);
+                                               MethodInfo method;
+                                               ArrayList args = new ArrayList (2);
                                        
-                                       args = new ArrayList (2);
-                                       args.Add (new Argument (left, Argument.AType.Expression));
-                                       args.Add (new Argument (right, Argument.AType.Expression));
+                                               args = new ArrayList (2);
+                                               args.Add (new Argument (left, Argument.AType.Expression));
+                                               args.Add (new Argument (right, Argument.AType.Expression));
                                        
-                                       if (oper == Operator.Addition)
-                                               method = TypeManager.delegate_combine_delegate_delegate;
-                                       else
-                                               method = TypeManager.delegate_remove_delegate_delegate;
+                                               if (oper == Operator.Addition)
+                                                       method = TypeManager.delegate_combine_delegate_delegate;
+                                               else
+                                                       method = TypeManager.delegate_remove_delegate_delegate;
 
-                                       if (l != r) {
-                                               Error_OperatorCannotBeApplied ();
-                                               return null;
-                                       }
+                                               if (!TypeManager.IsEqual (l, r)) {
+                                                       Error_OperatorCannotBeApplied ();
+                                                       return null;
+                                               }
 
-                                       return new BinaryDelegate (l, method, args);
-                               }
+                                               return new BinaryDelegate (l, method, args);
+                                       }
                                }
 
                                //
@@ -2616,7 +2715,7 @@ namespace Mono.CSharp {
                        if (oper == Operator.LeftShift || oper == Operator.RightShift)
                                return CheckShiftArguments (ec);
 
-                       if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){
+                       if (oper == Operator.LogicalOrElse || oper == Operator.LogicalAndAlso){
                                if (l == TypeManager.bool_type && r == TypeManager.bool_type) {
                                        type = TypeManager.bool_type;
                                        return this;
@@ -2628,7 +2727,7 @@ namespace Mono.CSharp {
                                }
 
                                Expression e = new ConditionalLogicalOperator (
-                                       oper == Operator.LogicalAnd, left, right, l, loc);
+                                       oper == Operator.LogicalAndAlso, left, right, l, loc);
                                return e.Resolve (ec);
                        } 
 
@@ -2706,6 +2805,7 @@ namespace Mono.CSharp {
 
                        return this;
                }
+#endif         
 
                public override Expression DoResolve (EmitContext ec)
                {
@@ -2727,8 +2827,8 @@ namespace Mono.CSharp {
 
                        Constant lc = left as Constant;
                        if (lc != null && lc.Type == TypeManager.bool_type && 
-                               ((oper == Operator.LogicalAnd && (bool)lc.GetValue () == false) ||
-                                (oper == Operator.LogicalOr && (bool)lc.GetValue () == true))) {
+                               ((oper == Operator.LogicalAndAlso && (bool)lc.GetValue () == false) ||
+                                (oper == Operator.LogicalOrElse && (bool)lc.GetValue () == true))) {
 
                                // TODO: make a sense to resolve unreachable expression as we do for statement
                                Report.Warning (429, 4, loc, "Unreachable expression code detected");
@@ -2749,7 +2849,10 @@ namespace Mono.CSharp {
                                                return e;
                        }
 
-                       return ResolveOperator (ec);
+                       if (TypeManager.IsNullableType (left.Type) || TypeManager.IsNullableType (right.Type))
+                               return new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec);
+
+                       return ResolveVisualBasicOperator (ec);
                }
 
                /// <remarks>
@@ -2800,7 +2903,7 @@ namespace Mono.CSharp {
                                        return;
                                }
 
-                       } else if (oper == Operator.LogicalAnd) {
+                       } else if (oper == Operator.LogicalAndAlso) {
 
                                if (onTrue) {
                                                Label tests_end = ig.DefineLabel ();
@@ -2815,7 +2918,7 @@ namespace Mono.CSharp {
 
                                return;
                                                                
-                       } else if (oper == Operator.LogicalOr){
+                       } else if (oper == Operator.LogicalOrElse){
                                if (onTrue) {
                                        left.EmitBranchable (ec, target, true);
                                        right.EmitBranchable (ec, target, true);
@@ -2920,12 +3023,13 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
                        Type l = left.Type;
                        OpCode opcode;
+                       OpCode opcode1 = OpCodes.Nop;
 
                        //
                        // Handle short-circuit operators differently
                        // than the rest
                        //
-                       if (oper == Operator.LogicalAnd) {
+                       if (oper == Operator.LogicalAndAlso) {
                                Label load_zero = ig.DefineLabel ();
                                Label end = ig.DefineLabel ();
 
@@ -2937,7 +3041,7 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Ldc_I4_0);
                                ig.MarkLabel (end);
                                return;
-                       } else if (oper == Operator.LogicalOr) {
+                       } else if (oper == Operator.LogicalOrElse) {
                                Label load_one = ig.DefineLabel ();
                                Label end = ig.DefineLabel ();
                                
@@ -2951,18 +3055,22 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       left.Emit (ec);
-                       right.Emit (ec);
+                       if (intermediate != null) {
+                               intermediate.Emit (ec);
+                               ig.Emit (OpCodes.Ldc_I4_0);
+                       }
+                       else {
+                               left.Emit (ec);
+                               right.Emit (ec);
+                       }
 
-                       bool isUnsigned = is_unsigned (left.Type);
+                       bool is_int32_or_int64_type = (Type == TypeManager.int32_type) || (Type == TypeManager.int64_type);
                        
                        switch (oper){
                        case Operator.Multiply:
                                if (ec.CheckState){
-                                       if (l == TypeManager.int32_type || l == TypeManager.int64_type)
+                                       if (is_int32_or_int64_type)
                                                opcode = OpCodes.Mul_Ovf;
-                                       else if (isUnsigned)
-                                               opcode = OpCodes.Mul_Ovf_Un;
                                        else
                                                opcode = OpCodes.Mul;
                                } else
@@ -2971,25 +3079,18 @@ namespace Mono.CSharp {
                                break;
 
                        case Operator.Division:
-                               if (isUnsigned)
-                                       opcode = OpCodes.Div_Un;
-                               else
-                                       opcode = OpCodes.Div;
+                       case Operator.IntegerDivision:
+                               opcode = OpCodes.Div;
                                break;
 
                        case Operator.Modulus:
-                               if (isUnsigned)
-                                       opcode = OpCodes.Rem_Un;
-                               else
-                                       opcode = OpCodes.Rem;
+                               opcode = OpCodes.Rem;
                                break;
 
                        case Operator.Addition:
                                if (ec.CheckState){
-                                       if (l == TypeManager.int32_type || l == TypeManager.int64_type)
+                                       if (is_int32_or_int64_type)
                                                opcode = OpCodes.Add_Ovf;
-                                       else if (isUnsigned)
-                                               opcode = OpCodes.Add_Ovf_Un;
                                        else
                                                opcode = OpCodes.Add;
                                } else
@@ -2998,10 +3099,8 @@ namespace Mono.CSharp {
 
                        case Operator.Subtraction:
                                if (ec.CheckState){
-                                       if (l == TypeManager.int32_type || l == TypeManager.int64_type)
+                                       if (is_int32_or_int64_type)
                                                opcode = OpCodes.Sub_Ovf;
-                                       else if (isUnsigned)
-                                               opcode = OpCodes.Sub_Ovf_Un;
                                        else
                                                opcode = OpCodes.Sub;
                                } else
@@ -3009,16 +3108,14 @@ namespace Mono.CSharp {
                                break;
 
                        case Operator.RightShift:
-                               if (isUnsigned)
-                                       opcode = OpCodes.Shr_Un;
-                               else
-                                       opcode = OpCodes.Shr;
+                               opcode = OpCodes.Shr;
                                break;
                                
                        case Operator.LeftShift:
                                opcode = OpCodes.Shl;
                                break;
 
+                       case Operator.Is:
                        case Operator.Equality:
                                opcode = OpCodes.Ceq;
                                break;
@@ -3031,39 +3128,22 @@ namespace Mono.CSharp {
                                break;
 
                        case Operator.LessThan:
-                               if (isUnsigned)
-                                       opcode = OpCodes.Clt_Un;
-                               else
-                                       opcode = OpCodes.Clt;
+                               opcode = OpCodes.Clt;
                                break;
 
                        case Operator.GreaterThan:
-                               if (isUnsigned)
-                                       opcode = OpCodes.Cgt_Un;
-                               else
-                                       opcode = OpCodes.Cgt;
+                               opcode = OpCodes.Cgt;
                                break;
 
                        case Operator.LessThanOrEqual:
-                               Type lt = left.Type;
-                               
-                               if (isUnsigned || (lt == TypeManager.double_type || lt == TypeManager.float_type))
-                                       ig.Emit (OpCodes.Cgt_Un);
-                               else
-                                       ig.Emit (OpCodes.Cgt);
+                               ig.Emit (OpCodes.Cgt);
                                ig.Emit (OpCodes.Ldc_I4_0);
                                
                                opcode = OpCodes.Ceq;
                                break;
 
                        case Operator.GreaterThanOrEqual:
-                               Type le = left.Type;
-                               
-                               if (isUnsigned || (le == TypeManager.double_type || le == TypeManager.float_type))
-                                       ig.Emit (OpCodes.Clt_Un);
-                               else
-                                       ig.Emit (OpCodes.Clt);
-                               
+                               ig.Emit (OpCodes.Clt);
                                ig.Emit (OpCodes.Ldc_I4_0);
                                
                                opcode = OpCodes.Ceq;
@@ -3087,6 +3167,671 @@ namespace Mono.CSharp {
                        }
 
                        ig.Emit (opcode);
+
+                       if (!IsArithmeticExpression && !IsShiftExpression)
+                               return;
+
+                       if (type == TypeManager.byte_type)
+                               ig.Emit (ec.CheckState && ! IsShiftExpression ? OpCodes.Conv_Ovf_U1 : OpCodes.Conv_U1);
+
+                       if (type == TypeManager.short_type)
+                               ig.Emit (ec.CheckState &&  ! IsShiftExpression ? OpCodes.Conv_Ovf_I2 : OpCodes.Conv_I2);                
+               }
+
+               Expression ResolveVisualBasicOperator (EmitContext ec)
+               {
+                       int errors;
+                       Expression ret_expr;
+
+                       Type l = left.Type;
+                       Type r = right.Type;
+
+                       //Console.WriteLine (OperName (oper) +"< "+  l + ", " + r + ">");
+
+                       errors = Report.Errors;
+                       ret_expr = HandleObjectOperands (ec);
+                       if (Report.Errors > errors)
+                               return null;
+                       if (ret_expr != null)
+                               return ret_expr;
+
+                       errors = Report.Errors;
+                       CheckArguments (ec);
+                       if (Report.Errors > errors)
+                               return null;
+
+                       if (oper == Operator.Exponentiation)
+                               return new HelperMethodInvocation (ec, Location, TypeManager.double_type,
+                                                                  TypeManager.math_pow_double_double, left, right);
+                       
+                       if (type == TypeManager.decimal_type) {
+                               MethodInfo helper_method = null;
+                               switch (oper) {
+                               case Operator.Addition:
+                                       helper_method = TypeManager.decimal_add_decimal_decimal;
+                                       break;
+                               case Operator.Subtraction:
+                                       helper_method = TypeManager.decimal_subtract_decimal_decimal;
+                                       break;
+                               case Operator.Multiply:
+                                       helper_method = TypeManager.decimal_multiply_decimal_decimal;
+                                       break;
+                               case Operator.Division:
+                                       helper_method = TypeManager.decimal_divide_decimal_decimal;
+                                       break;
+                               case Operator.Modulus:
+                                       helper_method = TypeManager.decimal_remainder_decimal_decimal;
+                                       break;
+                                               
+                               }
+                               return new HelperMethodInvocation (ec, Location, TypeManager.decimal_type, 
+                                                                  helper_method,  left, right);
+                       }
+
+                       if (IsRelationalExpression) {
+                               Type = TypeManager.bool_type;
+                               if (left.Type == TypeManager.string_type) {
+                                       Expression is_text_mode;
+
+                                       is_text_mode = new BoolConstant (RootContext.StringComparisonMode == CompareMethod.Text); 
+                                       intermediate = new HelperMethodInvocation (ec, Location, TypeManager.int32_type, 
+                                                                                  TypeManager.msvbcs_stringtype_strcmp_string_string_boolean,  
+                                                                                  left, right, is_text_mode);
+                                       return this;
+                               }
+                               if (left.Type == TypeManager.decimal_type) {
+                                       intermediate = new HelperMethodInvocation (ec, Location, TypeManager.int32_type, 
+                                                                                  TypeManager.decimal_compare_decimal_decimal,  left, right);
+                                       return this;
+                               }
+                               if (left.Type == TypeManager.date_type) {
+                                       intermediate = new HelperMethodInvocation (ec, Location, TypeManager.int32_type, 
+                                                                                  TypeManager.datetime_compare_datetime_datetime,  left, right);
+                                       return this;
+                               }
+                       }
+
+                       if (IsShiftExpression)
+                               return this;
+
+                       if (IsShortCircuitedLogicalExpression)
+                               return this;
+
+                       if (oper == Operator.Like) {
+                               Type = TypeManager.bool_type;
+                               Expression compare_mode = new EnumConstant (new IntConstant ((int) RootContext.StringComparisonMode), 
+                                                                     typeof (Microsoft.VisualBasic.CompareMethod));                                    
+                               return new HelperMethodInvocation (ec, Location, TypeManager.bool_type, TypeManager.msvbcs_stringtype_strlike_string_string_comparemethod, left, right, compare_mode);
+                       }
+
+
+                       //
+                       // Step 0: String concatenation (because overloading will get this wrong)
+                       //
+                       if (oper == Operator.Addition || oper == Operator.Concatenation){
+
+                               //
+                               // If any of the arguments is a string, cast to string
+                               //
+                               
+                               // Simple constant folding
+                               if (left is StringConstant && right is StringConstant)
+                                       return new StringConstant (((StringConstant) left).Value + ((StringConstant) right).Value);
+
+                               if (Type == TypeManager.string_type) {
+
+                                       // 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;
+                                               }
+                                       }
+
+                                       // Otherwise, start a new concat expression
+                                       return new StringConcat (ec, loc, left, right).Resolve (ec);
+                               }
+
+                               //
+                               // Transform a + ( - b) into a - b
+                               //
+                               if (right is Unary){
+                                       Unary right_unary = (Unary) right;
+
+                                       if (right_unary.Oper == Unary.Operator.UnaryNegation){
+                                               oper = Operator.Subtraction;
+                                               right = right_unary.Expr;
+                                               r = right.Type;
+                                       }
+                               }
+                       }
+
+                       return this;
+               }
+
+               Expression HandleObjectOperands (EmitContext ec)
+               {
+                       Type l = left.Type;
+                       Type r = right.Type;
+
+                       Expression target_left_expr = left;
+                       Expression target_right_expr = right;
+
+                       if (IsShortCircuitedLogicalExpression || IsExpression)
+                               return null;
+
+                       if (l != TypeManager.object_type && r != TypeManager.object_type)
+                               return null;
+
+                       if (RootContext.StricterTypeChecking)
+                               if (oper != Operator.Equality &&
+                                       oper != Operator.Inequality && oper != Operator.Is) {
+                                       Error_OperatorCannotBeAppliedToObjectOperands ();
+                                       return null;
+                               }
+
+                       if (l != TypeManager.object_type && ! IsOperatorDefinedForType (l) && ConvertOperandToDefinedType(ec, target_left_expr) == null) {
+                               Error_OperatorCannotBeApplied ();
+                               return null;
+                       }
+                       if (!IsShiftExpression && r != TypeManager.object_type && ! IsOperatorDefinedForType (r) && ConvertOperandToDefinedType(ec, target_right_expr) == null) {
+                               Error_OperatorCannotBeApplied ();
+                               return null;
+                       }
+
+                       if (l != TypeManager.object_type)
+                               left = Convert.ImplicitVBConversionRequired (ec, left, TypeManager.object_type, Location);
+
+                       if (IsShiftExpression) {
+                               if (r != TypeManager.int32_type) {
+                                       target_right_expr = Convert.ImplicitVBConversionRequired (ec, right, TypeManager.int32_type, Location);
+                                       if (target_right_expr == null) {
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+                                       right = target_right_expr;
+                               }
+
+                       } else if (r != TypeManager.object_type) {
+                               right = Convert.ImplicitVBConversionRequired (ec, right, TypeManager.object_type, Location);
+                       }
+
+                               
+                       Type = TypeManager.object_type;
+                       if (IsRelationalExpression) {
+                               Type = TypeManager.bool_type;
+                               Expression is_text_mode = new BoolConstant (RootContext.StringComparisonMode == CompareMethod.Text); 
+                               intermediate = new HelperMethodInvocation (ec, Location, TypeManager.int32_type, HelperMethod,  left, right, is_text_mode);
+                               return this;
+                       }
+
+                       if (oper == Operator.Like) {
+                               Type = TypeManager.bool_type;
+                               Expression compare_mode = new EnumConstant (new IntConstant ((int) RootContext.StringComparisonMode), 
+                                                                     typeof (Microsoft.VisualBasic.CompareMethod));                                    
+                               return new HelperMethodInvocation (ec, Location, TypeManager.bool_type, HelperMethod, left, right, compare_mode);
+                       }
+
+                       if (IsShiftExpression)
+                               return new HelperMethodInvocation (ec, Location, TypeManager.object_type, HelperMethod, left, right);
+
+                       return new HelperMethodInvocation (ec, Location, TypeManager.object_type, HelperMethod,  left, right);
+               }
+
+               void CheckArguments (EmitContext ec)
+               {
+                       int step = 0;
+                       
+                       Type l = left.Type;
+                       Type r = right.Type;
+
+                       Expression target_left_expr = left;
+                       Expression target_right_expr = right;
+
+                       Type target_left_expr_type = target_left_expr.Type;
+                       Type target_right_expr_type = target_right_expr.Type;
+
+
+                       if (IsShiftExpression) {
+                               CheckShiftArguments (ec);
+                               return;
+                       }
+
+                       if (IsExpression) {
+                               CheckIsArguments (ec);
+                               return;
+                       }
+
+                       while (true) {
+                               ++step;
+
+                               if (step > 10)
+                                       throw new Exception ("FIXME: An Infinite loop when resolving <" + l + "> " + OperName (oper) + " <" + r + ">");
+                               
+                               //Console.WriteLine ("          STEP " + step + ":");
+                               //Console.WriteLine ("          " + "<" + target_left_expr_type + ", " + target_right_expr_type + ">");
+                               
+                               if ((target_left_expr_type == target_right_expr_type) && 
+                                   IsOperatorDefinedForType (target_left_expr_type)) {
+
+                                       if (target_left_expr_type == TypeManager.null_type) {
+                                               target_left_expr = target_right_expr = new IntConstant (0);
+                                               Type = TypeManager.int32_type;
+                                               return;
+                                       } else {
+                                               left = target_left_expr;
+                                               right = target_right_expr;
+                                               type = target_left_expr_type;
+                                               return;
+                                       }
+                               }
+
+                               if ( !IsOperatorDefinedForType (target_left_expr_type)) {
+                                       target_left_expr = ConvertOperandToDefinedType(ec, target_left_expr);
+
+                                       if (target_left_expr == null) {
+                                               Error_OperatorCannotBeApplied();
+                                               return;
+                                       }
+
+                                       target_left_expr_type = target_left_expr.Type;
+                                       continue;
+                               }
+
+                               if ( !IsOperatorDefinedForType(target_right_expr_type)) {
+                                       target_right_expr = ConvertOperandToDefinedType(ec, target_right_expr);
+
+                                       if(target_right_expr == null) {
+                                               Error_OperatorCannotBeApplied();
+                                               return;
+                                       }                                               
+                                       
+                                       target_right_expr_type = target_right_expr.Type;
+                                       continue;
+                               }
+
+                               if (target_left_expr_type == TypeManager.null_type ||
+                                       target_right_expr_type == TypeManager.null_type)
+                                       break;
+
+                               if (target_left_expr_type == TypeManager.string_type) {
+                                       Type target_type;
+                                       if (target_right_expr_type == TypeManager.date_type)
+                                               target_type = TypeManager.date_type;
+                                       else if (target_right_expr_type == TypeManager.bool_type)
+                                               target_type = TypeManager.bool_type;
+                                       else
+                                               target_type = TypeManager.double_type;
+
+                                       if (l == target_type)
+                                               target_left_expr = left;
+                                       else
+                                               target_left_expr = Convert.ImplicitVBConversionRequired (ec, left, target_type, Location);
+
+                                       if (target_left_expr == null) {
+                                               Error_OperatorCannotBeApplied();
+                                               return;
+                                       }
+
+                                       target_left_expr_type = target_left_expr.Type;
+                                       continue;
+                               }
+
+                               if (target_right_expr_type == TypeManager.string_type) {
+                                       Type target_type;
+                                       if (target_left_expr_type == TypeManager.date_type)
+                                               target_type = TypeManager.date_type;
+                                       else if (target_left_expr_type == TypeManager.bool_type)
+                                               target_type = TypeManager.bool_type;
+                                       else
+                                               target_type = TypeManager.double_type;
+
+                                       if (r == target_type)
+                                               target_right_expr = right;
+                                       else
+                                               target_right_expr = Convert.ImplicitVBConversionRequired (ec, right, target_type, Location);
+
+                                       if (target_right_expr == null) {
+                                               Error_OperatorCannotBeApplied();
+                                               return;
+                                       }
+
+                                       target_right_expr_type = target_right_expr.Type;
+                                       continue;
+                               }
+
+                               break;
+                       }
+
+                       if ( !DoOperandPromotions(ec, target_left_expr, target_right_expr))
+                               Error_OperatorCannotBeApplied();
+
+                       return;
+               }       
+
+               bool IsOperatorDefinedForType (Type t)
+               {
+                       if (t == TypeManager.null_type)
+                               return true;
+               
+                       switch (oper) {
+
+                       case Operator.Exponentiation:
+                               if (t == TypeManager.double_type)
+                                       return true;
+                               break;
+
+                       case Operator.Concatenation:
+                       case Operator.Like:     
+                               if (t == TypeManager.string_type)
+                                       return true;
+
+                               break;
+
+                       case Operator.BitwiseAnd:
+                       case Operator.BitwiseOr:
+                       case Operator.ExclusiveOr:
+                               if (t == TypeManager.bool_type ||
+                                   TypeManager.IsFixedNumericType (t))
+                                       return true;
+
+                               break;
+
+                       case Operator.LogicalAndAlso:
+                       case Operator.LogicalOrElse:
+                               if (t == TypeManager.bool_type)
+                                       return true;
+                               break;
+
+                       case Operator.RightShift:
+                       case Operator.LeftShift:
+
+                               if (TypeManager.IsFixedNumericType (t))
+                                       return true;
+
+                               break;
+
+                       case Operator.Equality:
+                       case Operator.Inequality:
+                       case Operator.LessThan:
+                       case Operator.LessThanOrEqual:
+                       case Operator.GreaterThan:
+                       case Operator.GreaterThanOrEqual:
+                               if (t == TypeManager.bool_type ||
+                                   t == TypeManager.date_type ||
+                                   t == TypeManager.char_type ||
+                                   t == TypeManager.string_type ||
+                                   TypeManager.IsNumericType (t))
+                                       return true;
+
+                               break;
+                               
+                       case Operator.Addition:
+                               if (t == TypeManager.string_type ||
+                                   TypeManager.IsNumericType (t))
+                                       return true;
+                               break;
+                               
+                       case Operator.Subtraction:
+                       case Operator.Multiply:
+                       case Operator.Division:
+                       case Operator.Modulus:                          
+                               if (TypeManager.IsNumericType (t))
+                                       return true;
+                               break;
+
+                       case Operator.IntegerDivision:
+                               if (TypeManager.IsFixedNumericType (t))
+                                       return true;
+                               
+                               break;
+                       }
+
+                       return false;
+               }
+
+
+               Expression ConvertOperandToDefinedType (EmitContext ec, Expression expr)
+               {
+                       Type target_type = null;
+                       Type operand_type = expr.Type;
+                       
+                       if (IsOperatorDefinedForType (operand_type))
+                               return expr;
+                               
+                       switch (oper) {
+                       case Operator.Addition:
+                       case Operator.Subtraction:
+                       case Operator.Multiply:
+                               if (operand_type == TypeManager.bool_type)
+                                       target_type = TypeManager.short_type;
+                                       
+                               if (operand_type == TypeManager.char_type)
+                                       target_type = TypeManager.string_type;
+
+                               if (operand_type == TypeManager.date_type)
+                                       target_type = TypeManager.string_type;
+                                       
+                               break;
+
+                       case Operator.Like:
+                       case Operator.Concatenation:
+                               return Convert.ExplicitVBConversion(ec, expr, TypeManager.string_type, expr.Location);
+                               break;
+
+                       case Operator.LogicalAndAlso:
+                       case Operator.LogicalOrElse:
+                               return Convert.ExplicitVBConversion(ec, expr, TypeManager.bool_type, expr.Location);
+                               break;
+
+                       case Operator.Exponentiation:
+                               return Convert.ExplicitVBConversion(ec, expr, TypeManager.double_type, expr.Location);
+                               break;
+
+                       }
+
+                       if (target_type != null)
+                               return Convert.ImplicitVBConversion(ec, expr, target_type, expr.Location);
+
+                       return null;
+               }
+
+               static Type GetWiderOfTypes (Type t1, Type t2)
+               {
+                       // char array and Nothing should be handled here ?
+
+               
+                       if (t1 == t2)
+                               return t1;
+
+                       if(t1 == TypeManager.null_type)
+                               return t2;
+
+                       if (t2 == TypeManager.null_type)
+                               return t1;
+
+                       if (t1 == TypeManager.date_type || t1 == TypeManager.char_type) {
+                               if (t2 == TypeManager.string_type)
+                                       return t2;
+                               else
+                                       return null;
+                       }
+                       
+                       if (t2 == TypeManager.date_type || t2 == TypeManager.char_type) {
+                               if (t1 == TypeManager.string_type)
+                                       return t1;
+                               else
+                                       return null;
+                       }
+
+                       object order1 = TypeManager.relative_type_order[t1];
+                       if (order1 == null)
+                               return null;
+                       
+                       object order2 = TypeManager.relative_type_order[t2];
+
+                       if (order2 == null)
+                               return null;
+                       
+                       if ((int) order1 > (int) order2)
+                               return t1;
+                       else
+                               return t2;
+
+               }
+
+               bool DoOperandPromotions (EmitContext ec, Expression target_left_expr, Expression target_right_expr)
+               {
+                       Type l = target_left_expr.Type;
+                       Type r = target_right_expr.Type;
+                       
+                       Type target_type = GetWiderOfTypes(l, r);
+
+                       //Console.WriteLine ("          DoingOperandPromotions");
+                       //Console.WriteLine ("         left => " + l + " right => " + r);
+                       //Console.WriteLine ("          target_type => " + target_type);
+
+                       if (target_type == null) {
+                               throw new Exception ("Types " + l + " " + r +" cannot be compared");
+                       }
+
+                       if (r != target_type) {
+                               target_right_expr = Convert.ImplicitVBConversion (ec, target_right_expr, target_type, Location);
+
+                               if (target_right_expr == null)
+                                       return false;
+
+                       }
+
+                       if (l != target_type) {
+                               target_left_expr = Convert.ImplicitVBConversion (ec, target_left_expr, target_type, Location);
+
+                               if (target_left_expr == null)
+                                       return false;
+                       }
+
+                       left = target_left_expr;
+                       right = target_right_expr;
+                       type = target_type;
+                       return true;
+               }
+
+               bool IsArithmeticExpression {
+                       get {
+                               if (oper == Operator.Addition|| oper == Operator.Subtraction||  
+                                       oper == Operator.Multiply|| oper == Operator.Division|| 
+                                       oper == Operator.IntegerDivision|| oper == Operator.Modulus)
+                                       return true;
+
+                               return false;
+                       }
+               }
+               
+               bool IsRelationalExpression {
+                       get {
+                               if (oper == Operator.Equality || oper == Operator.Inequality || 
+                                       oper == Operator.LessThan || oper == Operator.LessThanOrEqual ||        
+                                       oper == Operator.GreaterThan || oper == Operator.GreaterThanOrEqual)
+                                       return true;
+
+                               return false;
+                       }
+               }
+
+               bool IsShiftExpression {
+                       get {
+                               if (oper == Operator.LeftShift || oper == Operator.RightShift)
+                                       return true;
+
+                               return false;
+                       }
+               }
+
+               bool IsShortCircuitedLogicalExpression {
+                       get {
+                               if (oper == Operator.LogicalAndAlso|| oper == Operator.LogicalOrElse)
+                                       return true;
+
+                               return false;
+                       }
+               }
+
+               bool IsExpression {
+                       get {
+                               return (oper == Operator.Is);
+                       }
+               }
+
+               MethodInfo HelperMethod {
+                       get {
+                               MethodInfo helper_method = null;
+                               switch (oper) {
+                               case Operator.Multiply:
+                                       helper_method = TypeManager.msvbcs_objecttype_mulobj_object_object;
+                                       break;
+                               case Operator.Division:
+                                       helper_method = TypeManager.msvbcs_objecttype_divobj_object_object;
+                                       break;
+                               case Operator.IntegerDivision:
+                                       helper_method = TypeManager.msvbcs_objecttype_idivobj_object_object;
+                                       break;
+                               case Operator.Modulus:
+                                       helper_method = TypeManager.msvbcs_objecttype_modobj_object_object;
+                                       break;
+                               case Operator.Addition:
+                                       helper_method = TypeManager.msvbcs_objecttype_addobj_object_object;
+                                       break;
+                               case Operator.Subtraction:
+                                       helper_method = TypeManager.msvbcs_objecttype_subobj_object_object;
+                                       break;
+                               case Operator.LessThan:
+                               case Operator.GreaterThan:
+                               case Operator.LessThanOrEqual:
+                               case Operator.GreaterThanOrEqual:
+                               case Operator.Equality:
+                               case Operator.Inequality:
+                                       helper_method = TypeManager.msvbcs_objecttype_objtst_object_object_boolean;
+                                       break;
+                               case Operator.BitwiseAnd:
+                                       helper_method = TypeManager.msvbcs_objecttype_bitandobj_object_object;
+                                       break;
+                                case Operator.BitwiseOr:
+                                       helper_method = TypeManager.msvbcs_objecttype_bitorobj_object_object;
+                                       break;
+                                case Operator.ExclusiveOr:
+                                       helper_method = TypeManager.msvbcs_objecttype_bitxorobj_object_object;
+                                       break;
+
+                               case Operator.Like:
+                                       helper_method = TypeManager.msvbcs_objecttype_likeobj_object_object_comparemethod;
+                                       break;
+
+                               case Operator.Concatenation:
+                                       helper_method = TypeManager.msvbcs_objecttype_strcatobj_object_object;
+                                       break;
+
+                               case Operator.Exponentiation:
+                                       helper_method = TypeManager.msvbcs_objecttype_powobj_object_object;
+                                       break;  
+                               case Operator.LeftShift:
+                                       helper_method = TypeManager.msvbcs_objecttype_shiftleftobj_object_int32;
+                                       break;                  
+                               case Operator.RightShift:
+                                       helper_method = TypeManager.msvbcs_objecttype_shiftrightobj_object_int32;
+                                       break;                                          
+                                       
+                               }
+
+                               return helper_method;
+                       }
                }
        }
 
@@ -3446,17 +4191,26 @@ namespace Mono.CSharp {
                                //
                                left.Emit (ec);
                                ig.Emit (OpCodes.Conv_I);
-                               right.Emit (ec);
-                               if (size != 1){
-                                       if (size == 0)
-                                               ig.Emit (OpCodes.Sizeof, element);
-                                       else 
-                                               IntLiteral.EmitInt (ig, size);
-                                       if (rtype == TypeManager.int64_type)
-                                               ig.Emit (OpCodes.Conv_I8);
-                                       else if (rtype == TypeManager.uint64_type)
-                                               ig.Emit (OpCodes.Conv_U8);
-                                       ig.Emit (OpCodes.Mul);
+
+                               Constant right_const = right as Constant;
+                               if (right_const != null && size != 0) {
+                                       Expression ex = ConstantFold.BinaryFold (ec, Binary.Operator.Multiply, new IntConstant (size), right_const, loc);
+                                       if (ex == null)
+                                               return;
+                                       ex.Emit (ec);
+                               } else {
+                                       right.Emit (ec);
+                                       if (size != 1){
+                                               if (size == 0)
+                                                       ig.Emit (OpCodes.Sizeof, element);
+                                               else 
+                                                       IntLiteral.EmitInt (ig, size);
+                                               if (rtype == TypeManager.int64_type)
+                                                       ig.Emit (OpCodes.Conv_I8);
+                                               else if (rtype == TypeManager.uint64_type)
+                                                       ig.Emit (OpCodes.Conv_U8);
+                                               ig.Emit (OpCodes.Mul);
+                                       }
                                }
                                
                                if (rtype == TypeManager.int64_type || rtype == TypeManager.uint64_type)
@@ -3508,6 +4262,9 @@ namespace Mono.CSharp {
 
                        if (expr == null)
                                return null;
+
+                       if (TypeManager.IsNullableType (expr.Type))
+                               return new Nullable.LiftedConditional (expr, trueExpr, falseExpr, loc).Resolve (ec);
                        
                        if (expr.Type != TypeManager.bool_type){
                                expr = Expression.ResolveBoolean (
@@ -4273,7 +5030,7 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Invocation of methods or delegates.
        /// </summary>
-       public class Invocation : ExpressionStatement {
+       public class Invocation : ExpressionStatement  {
                public readonly ArrayList Arguments;
 
                public Expression expr;
@@ -6707,8 +7464,7 @@ namespace Mono.CSharp {
                                                // If we are dealing with a struct, get the
                                                // address of it, so we can store it.
                                                //
-                                               if ((dims == 1) && 
-                                                   etype.IsSubclassOf (TypeManager.value_type) &&
+                                               if ((dims == 1) && etype.IsValueType &&
                                                    (!TypeManager.IsBuiltinOrEnum (etype) ||
                                                     etype == TypeManager.decimal_type)) {
                                                        if (e is New){
@@ -7273,7 +8029,15 @@ namespace Mono.CSharp {
 
                                                object real_value = ((Constant) c.Expr).GetValue ();
 
-                                               return Constantify (real_value, t);
+                                               Expression exp = Constantify (real_value, t);
+
+                                               if (left_is_explicit && !left_is_type && !IdenticalNameAndTypeName (ec, left_original, left, loc)) {
+                                                       Report.SymbolRelatedToPreviousError (c);
+                                                       error176 (loc, c.GetSignatureForError ());
+                                                       return null;
+                                               }
+                                       
+                                               return exp;
                                        }
                                }
 
@@ -7596,6 +8360,11 @@ namespace Mono.CSharp {
                }
 
                public override FullNamedExpression ResolveAsTypeStep (EmitContext ec)
+               {
+                       return ResolveNamespaceOrType (ec, false);
+               }
+
+               public FullNamedExpression ResolveNamespaceOrType (EmitContext ec, bool silent)
                {
                        FullNamedExpression new_expr = expr.ResolveAsTypeStep (ec);
 
@@ -7609,7 +8378,7 @@ namespace Mono.CSharp {
                                FullNamedExpression retval = ns.Lookup (ec.DeclSpace, lookup_id, loc);
                                if ((retval != null) && (args != null))
                                        retval = new ConstructedType (retval, args, loc).ResolveAsTypeStep (ec);
-                               if (retval == null)
+                               if (!silent && retval == null)
                                        Report.Error (234, loc, "The type or namespace name `{0}' could not be found in namespace `{1}'", Identifier, ns.FullName);
                                return retval;
                        }
@@ -7628,7 +8397,7 @@ namespace Mono.CSharp {
 
                        Expression member_lookup;
                        member_lookup = MemberLookupFinal (ec, expr_type, expr_type, lookup_id, loc);
-                       if (member_lookup == null) {
+                       if (!silent && member_lookup == null) {
                                Report.Error (234, loc, "The type name `{0}' could not be found in type `{1}'", 
                                              Identifier, new_expr.FullName);
                                return null;
@@ -8812,6 +9581,13 @@ namespace Mono.CSharp {
                                return null;
                        }
 
+                       if ((dim.Length > 0) && (dim [0] == '?')) {
+                               TypeExpr nullable = new NullableType (left, loc);
+                               if (dim.Length > 1)
+                                       nullable = new ComposedCast (nullable, dim.Substring (1), loc);
+                               return nullable.ResolveAsTypeTerminal (ec);
+                       }
+
                        int pos = 0;
                        while ((pos < dim.Length) && (dim [pos] == '[')) {
                                pos++;
@@ -8841,25 +9617,29 @@ namespace Mono.CSharp {
                                return this;
                        }
 
-                       //
-                       // ltype.Fullname is already fully qualified, so we can skip
-                       // a lot of probes, and go directly to TypeManager.LookupType
-                       //
-                       string fname = ltype.FullName != null ? ltype.FullName : ltype.Name;
-                       string cname = fname + dim;
-                       type = TypeManager.LookupTypeDirect (cname);
-                       if (type == null){
-                               //
-                               // For arrays of enumerations we are having a problem
-                               // with the direct lookup.  Need to investigate.
+                       if (dim != "") {
                                //
-                               // For now, fall back to the full lookup in that case.
+                               // ltype.Fullname is already fully qualified, so we can skip
+                               // a lot of probes, and go directly to TypeManager.LookupType
                                //
-                               FullNamedExpression e = ec.DeclSpace.LookupType (cname, false, loc);
-                               if (e is TypeExpr)
-                                       type = ((TypeExpr) e).ResolveType (ec);
-                               if (type == null)
-                                       return null;
+                               string fname = ltype.FullName != null ? ltype.FullName : ltype.Name;
+                               string cname = fname + dim;
+                               type = TypeManager.LookupTypeDirect (cname);
+                               if (type == null){
+                                       //
+                                       // For arrays of enumerations we are having a problem
+                                       // with the direct lookup.  Need to investigate.
+                                       //
+                                       // For now, fall back to the full lookup in that case.
+                                       //
+                                       FullNamedExpression e = ec.DeclSpace.LookupType (cname, false, loc);
+                                       if (e is TypeExpr)
+                                               type = ((TypeExpr) e).ResolveType (ec);
+                                       if (type == null)
+                                               return null;
+                               }
+                       } else {
+                               type = ltype;
                        }
 
                        if (!ec.InUnsafe && type.IsPointer){