2006-11-29 Martin Baulig <martin@ximian.com>
authorMartin Baulig <martin@novell.com>
Wed, 29 Nov 2006 15:45:48 +0000 (15:45 -0000)
committerMartin Baulig <martin@novell.com>
Wed, 29 Nov 2006 15:45:48 +0000 (15:45 -0000)
Merged everything from SVN HEAD back.

svn path=/branches/martin/anonymous-methods2/mcs/; revision=68669

13 files changed:
mcs/mcs/ChangeLog
mcs/mcs/class.cs
mcs/mcs/codegen.cs
mcs/mcs/convert.cs [new file with mode: 0644]
mcs/mcs/cs-parser.jay [new file with mode: 0644]
mcs/mcs/cs-tokenizer.cs [new file with mode: 0644]
mcs/mcs/decl.cs [new file with mode: 0644]
mcs/mcs/delegate.cs [new file with mode: 0644]
mcs/mcs/driver.cs [new file with mode: 0644]
mcs/mcs/ecore.cs [new file with mode: 0644]
mcs/mcs/expression.cs
mcs/mcs/namespace.cs [new file with mode: 0644]
mcs/mcs/report.cs [new file with mode: 0644]

index 8d5763c6a2ad4ce43c65180d2905008acd73775a..f420a61284b62936d73d622751df9a0497dd99dd 100644 (file)
@@ -1,3 +1,7 @@
+2006-11-29  Martin Baulig  <martin@ximian.com>
+
+       Merged everything from SVN HEAD back.
+
 2006-11-28  Martin Baulig  <martin@ximian.com>
 
        Milestone II: We are ready to merge things back.
 
        **** The anonymous methods branch starts here ****
 
+2006-11-22  Marek Safar  <marek.safar@gmail.com>
+
+       A fix for bug #79987
+       * class.cs (VerifyClsCompliance): Move redundant CLS compliance attribute
+       check to a base class.
+       * decl.cs (VerifyClsCompliance): Warn that CLS compliance cannot be tested
+       only when assembly has missing attribute.
+       * report.cs: Update.
+
+2006-11-21  Marek Safar  <marek.safar@gmail.com>
+
+       * cs-tokenizer.cs: Merged with gmcs version.
+
+2006-11-20  Marek Safar  <marek.safar@gmail.com>
+
+       * cs-tokenizer.cs,
+       * cs-parser.jay: Better error message when partial keyword is misplaced.
+
+2006-11-19  Gert Driesen  <drieseng@users.sourceforge.net>
+
+       A fix for bug #79810
+       report.cs: CS1058 only applies to 2.0 profile (gmcs).
+       codegen.cs: on 2.0 profile, non-exception throwables are wrapped in
+       a RuntimeWrappedException by default.
+
+2006-11-18  Marek Safar  <marek.safar@gmail.com>
+
+       A fix for bug #79843
+       * delegate.cs (Delegate.VerifyMethod): Fixed covariance and contravariance
+       implementation.
+       (DelegateCreation.Error_NoMatchingMethodForDelegate): Ditto.
+
+2006-11-18  Marek Safar  <marek.safar@gmail.com>
+
+       * driver.cs, namespace.cs: Uses faster IndexOf version.
+
+2006-11-17  Marek Safar  <marek.safar@gmail.com>
+
+       A fix for bug #79941
+       * class.cs (MemberCore.IsDuplicateImplementation): Add more tricks for
+       operators.
+       (Operator.Define): Implicit/Explicit operator of same type is duplicate
+       even if internal name is different.
+       * convert.cs (GetConversionOperator): Replaced EmitContext with parentType.
+       (UserDefinedConversion): Simplified as the operators cannot be internal.
+       * ecore.cs (Error_ValueCannotBeConverted): Take account of user
+       conversions.
+       (MethodLookup): Replaced EmitContext with parentType.
+       * expression.cs: Updated.
+
 2006-11-09  Raja R Harinath  <rharinath@novell.com>
 
        * driver.cs (BadAssembly): Handle all the ugliness of
index 06e75900a195ec5d50ce5ce15c736325a5f4b6a1..f41b2fb8a3e92a1197e96d2c9b378262b6a63b7a 100644 (file)
@@ -2549,11 +2549,6 @@ namespace Mono.CSharp {
                        if (base_type != null && !AttributeTester.IsClsCompliant (base_type)) {
                                Report.Error (3009, Location, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (base_type));
                        }
-
-                       if (!Parent.IsClsComplianceRequired ()) {
-                               Report.Error (3018, Location, "`{0}' cannot be marked as CLS-compliant because it is a member of non CLS-compliant type `{1}'", 
-                                       GetSignatureForError (), Parent.GetSignatureForError ());
-                       }
                        return true;
                }
 
@@ -3654,11 +3649,29 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               // TODO: create a special method for operators only to make code better
                protected bool IsDuplicateImplementation (MethodCore method)
                {
-                       if (method == this || !(method.MemberName.Equals (MemberName)))
+                       if (method == this)
                                return false;
 
+                       Operator op2 = null;
+                       Operator op1 = null;
+
+                       if (!(method.MemberName.Equals (MemberName)))
+                       {
+                               op1 = this as Operator;
+                               if (op1 == null || !(op1.OperatorType == Operator.OpType.Explicit || op1.OperatorType == Operator.OpType.Implicit))
+                                       return false;
+
+                               op2 = method as Operator;
+                               if (op2 == null || !(op2.OperatorType == Operator.OpType.Explicit || op2.OperatorType == Operator.OpType.Implicit))
+                                       return false;
+                       } else {
+                               op1 = this as Operator;
+                               op2 = method as Operator;
+                       }
+
                        Type[] param_types = method.ParameterTypes;
                        // This never happen. Rewrite this as Equal
                        if (param_types == null && ParameterTypes == null)
@@ -3683,7 +3696,7 @@ namespace Mono.CSharp {
                                equal = false;
 
                        // TODO: make operator compatible with MethodCore to avoid this
-                       if (this is Operator && method is Operator) {
+                       if (op1 != null && op2 != null) {
                                if (MemberType != method.MemberType)
                                        equal = false;
                        }
@@ -7661,7 +7674,7 @@ namespace Mono.CSharp {
                                 int mod_flags, Parameters parameters,
                                 ToplevelBlock block, Attributes attrs, Location loc)
                        : base (parent, null, ret_type, mod_flags, AllowedModifiers, false,
-                               new MemberName ("op_" + type, loc), attrs, parameters)
+                               new MemberName ("op_" + type.ToString(), loc), attrs, parameters)
                {
                        OperatorType = type;
                        Block = block;
@@ -7712,6 +7725,10 @@ namespace Mono.CSharp {
                                return false;
                        }
 
+                       // imlicit and explicit operator of same types are not allowed
+                       if (OperatorType == OpType.Explicit || OperatorType == OpType.Implicit)
+                               MarkForDuplicationCheck ();
+
                        if (!base.Define ())
                                return false;
 
index 7f95441bc020d33c5cf7108c698c8babace64b7d..94d7a949eab33cf4889ac7e123de7a79bd7f07c4 100644 (file)
@@ -1005,7 +1005,9 @@ namespace Mono.CSharp {
 
                public AssemblyClass (): base ()
                {
+#if GMCS_SOURCE
                        wrap_non_exception_throws = true;
+#endif
                }
 
                public bool IsClsCompliant {
diff --git a/mcs/mcs/convert.cs b/mcs/mcs/convert.cs
new file mode 100644 (file)
index 0000000..a35cc84
--- /dev/null
@@ -0,0 +1,2116 @@
+//
+// conversion.cs: various routines for implementing conversions.
+//
+// Authors:
+//   Miguel de Icaza (miguel@ximian.com)
+//   Ravi Pratap (ravi@ximian.com)
+//
+// (C) 2001, 2002, 2003 Ximian, Inc.
+//
+
+namespace Mono.CSharp {
+       using System;
+       using System.Collections;
+       using System.Diagnostics;
+       using System.Reflection;
+       using System.Reflection.Emit;
+
+       //
+       // A container class for all the conversion operations
+       //
+       public class Convert {
+#if GMCS_SOURCE
+               static bool TypeParameter_to_Null (Type target_type)
+               {
+                       GenericConstraints gc = TypeManager.GetTypeParameterConstraints (target_type);
+                       if (gc == null)
+                               return false;
+
+                       if (gc.HasReferenceTypeConstraint)
+                               return true;
+                       if (gc.HasClassConstraint && !TypeManager.IsValueType (gc.ClassConstraint))
+                               return true;
+
+                       return false;
+               }
+
+               static Type TypeParam_EffectiveBaseType (GenericConstraints gc)
+               {
+                       ArrayList list = new ArrayList ();
+                       list.Add (gc.EffectiveBaseClass);
+                       foreach (Type t in gc.InterfaceConstraints) {
+                               if (!TypeManager.IsGenericParameter (t))
+                                       continue;
+
+                               GenericConstraints new_gc = TypeManager.GetTypeParameterConstraints (t);
+                               if (new_gc != null)
+                                       list.Add (TypeParam_EffectiveBaseType (new_gc));
+                       }
+                       return FindMostEncompassedType (list);
+               }
+#endif
+
+               //
+               // From a one-dimensional array-type S[] to System.Collections.IList<S> and base
+               // interfaces of this interface.
+               //
+               // From a one-dimensional array-type S[] to System.Collections.IList<T> and base
+               // interfaces of this interface, provided there is an implicit reference conversion
+               // from S to T.
+               //
+               static bool Array_To_IList (Type array, Type list)
+               {
+#if GMCS_SOURCE
+                       if (!array.IsArray || (array.GetArrayRank () != 1) || !list.IsGenericType)
+                               return false;
+
+                       Type gt = list.GetGenericTypeDefinition ();
+                       if ((gt != TypeManager.generic_ilist_type) &&
+                           (gt != TypeManager.generic_icollection_type) &&
+                           (gt != TypeManager.generic_ienumerable_type))
+                               return false;
+
+                       Type element_type = TypeManager.GetElementType (array);
+                       Type arg_type = TypeManager.GetTypeArguments (list) [0];
+
+                       if (element_type == arg_type)
+                               return true;
+
+                       if (MyEmptyExpr == null)
+                               MyEmptyExpr = new EmptyExpression ();
+                       MyEmptyExpr.SetType (TypeManager.GetElementType (array));
+
+                       return ImplicitReferenceConversionExists (MyEmptyExpr, arg_type);
+#else
+                       return false;
+#endif
+               }
+
+               static Expression ImplicitTypeParameterConversion (Expression expr,
+                                                                  Type target_type)
+               {
+#if GMCS_SOURCE
+                       Type expr_type = expr.Type;
+
+                       GenericConstraints gc = TypeManager.GetTypeParameterConstraints (expr_type);
+
+                       if (gc == null) {
+                               if (target_type == TypeManager.object_type)
+                                       return new BoxedCast (expr, target_type);
+
+                               return null;
+                       }
+
+                       // We're converting from a type parameter which is known to be a reference type.
+                       Type base_type = TypeParam_EffectiveBaseType (gc);
+
+                       if (TypeManager.IsSubclassOf (base_type, target_type))
+                               return new ClassCast (expr, target_type);
+
+                       if (target_type.IsInterface) {
+                               if (TypeManager.ImplementsInterface (base_type, target_type))
+                                       return new ClassCast (expr, target_type);
+
+                               foreach (Type t in gc.InterfaceConstraints) {
+                                       if (TypeManager.IsSubclassOf (t, target_type))
+                                               return new ClassCast (expr, target_type);
+                                       if (TypeManager.ImplementsInterface (t, target_type))
+                                               return new ClassCast (expr, target_type);
+                               }
+                       }
+
+                       foreach (Type t in gc.InterfaceConstraints) {
+                               if (!TypeManager.IsGenericParameter (t))
+                                       continue;
+                               if (TypeManager.IsSubclassOf (t, target_type))
+                                       return new ClassCast (expr, target_type);
+                               if (TypeManager.ImplementsInterface (t, target_type))
+                                       return new ClassCast (expr, target_type);
+                       }
+#endif
+                       return null;
+               }
+
+               static bool ExplicitTypeParameterConversionExists (Type source_type, Type target_type)
+               {
+#if GMCS_SOURCE
+                       if (target_type.IsInterface)
+                               return true;
+
+                       if (TypeManager.IsGenericParameter (target_type)) {
+                               GenericConstraints gc = TypeManager.GetTypeParameterConstraints (target_type);
+                               if (gc == null)
+                                       return false;
+
+                               foreach (Type iface in gc.InterfaceConstraints) {
+                                       if (!TypeManager.IsGenericParameter (iface))
+                                               continue;
+
+                                       if (TypeManager.IsSubclassOf (source_type, iface))
+                                               return true;
+                               }
+                       }
+#endif
+                       return false;
+               }
+
+               static Expression ExplicitTypeParameterConversion (Expression source, Type target_type)
+               {
+#if GMCS_SOURCE
+                       Type source_type = source.Type;
+
+                       if (target_type.IsInterface)
+                               return new ClassCast (source, target_type);
+
+                       if (TypeManager.IsGenericParameter (target_type)) {
+                               GenericConstraints gc = TypeManager.GetTypeParameterConstraints (target_type);
+                               if (gc == null)
+                                       return null;
+
+                               foreach (Type iface in gc.InterfaceConstraints) {
+                                       if (!TypeManager.IsGenericParameter (iface))
+                                               continue;
+
+                                       if (TypeManager.IsSubclassOf (source_type, iface))
+                                               return new ClassCast (source, target_type);
+                               }
+                       }
+#endif
+                       return null;
+               }
+
+               static EmptyExpression MyEmptyExpr;
+               static public Expression ImplicitReferenceConversion (Expression expr, Type target_type)
+               {
+                       Type expr_type = expr.Type;
+
+                       if (expr_type == null && expr.eclass == ExprClass.MethodGroup){
+                               // if we are a method group, emit a warning
+
+                               expr.Emit (null);
+                       }
+
+                       if (expr_type == TypeManager.void_type)
+                               return null;
+
+                       if (TypeManager.IsGenericParameter (expr_type))
+                               return ImplicitTypeParameterConversion (expr, target_type);
+
+                       //
+                       // notice that it is possible to write "ValueType v = 1", the ValueType here
+                       // is an abstract class, and not really a value type, so we apply the same rules.
+                       //
+                       if (target_type == TypeManager.object_type) {
+                               //
+                               // A pointer type cannot be converted to object
+                               //
+                               if (expr_type.IsPointer)
+                                       return null;
+
+                               if (TypeManager.IsValueType (expr_type))
+                                       return new BoxedCast (expr, target_type);
+                               if (expr_type.IsClass || expr_type.IsInterface || expr_type == TypeManager.enum_type){
+                                       if (expr_type == TypeManager.anonymous_method_type)
+                                               return null;
+                                       return new EmptyCast (expr, target_type);
+                               }
+
+                               return null;
+                       } else if (target_type == TypeManager.value_type) {
+                               if (TypeManager.IsValueType (expr_type))
+                                       return new BoxedCast (expr, target_type);
+                               if (expr_type == TypeManager.null_type)
+                                       return new EmptyConstantCast ((Constant)expr, target_type);
+
+                               return null;
+                       } else if (TypeManager.IsSubclassOf (expr_type, target_type)) {
+                               //
+                               // Special case: enumeration to System.Enum.
+                               // System.Enum is not a value type, it is a class, so we need
+                               // a boxing conversion
+                               //
+                               if (expr_type.IsEnum || TypeManager.IsGenericParameter (expr_type))
+                                       return new BoxedCast (expr, target_type);
+
+                               return new EmptyCast (expr, target_type);
+                       }
+
+                       // This code is kind of mirrored inside ImplicitStandardConversionExists
+                       // with the small distinction that we only probe there
+                       //
+                       // Always ensure that the code here and there is in sync
+
+                       // from the null type to any reference-type.
+                       if (expr_type == TypeManager.null_type) {
+                               NullConstant nc = (NullConstant)expr;
+                               return nc.ToType(target_type);
+                       }
+
+                       // from any class-type S to any interface-type T.
+                       if (target_type.IsInterface) {
+                               if (target_type != TypeManager.iconvertible_type &&
+                                   expr_type.IsValueType && (expr is Constant) &&
+                                   !(expr is IntLiteral || expr is BoolLiteral ||
+                                     expr is FloatLiteral || expr is DoubleLiteral ||
+                                     expr is LongLiteral || expr is CharLiteral ||
+                                     expr is StringLiteral || expr is DecimalLiteral ||
+                                     expr is UIntLiteral || expr is ULongLiteral)) {
+                                       return null;
+                               }
+
+                               if (TypeManager.ImplementsInterface (expr_type, target_type)){
+                                       if (TypeManager.IsGenericParameter (expr_type) || TypeManager.IsValueType (expr_type))
+                                               return new BoxedCast (expr, target_type);
+                                       else
+                                               return new EmptyCast (expr, target_type);
+                               }
+                       }
+
+                       // from any interface type S to interface-type T.
+                       if (expr_type.IsInterface && target_type.IsInterface) {
+                               if (TypeManager.ImplementsInterface (expr_type, target_type))
+                                       return new EmptyCast (expr, target_type);
+                               else
+                                       return null;
+                       }
+
+                       // from an array-type S to an array-type of type T
+                       if (expr_type.IsArray && target_type.IsArray) {
+                               if (expr_type.GetArrayRank () == target_type.GetArrayRank ()) {
+
+                                       Type expr_element_type = TypeManager.GetElementType (expr_type);
+
+                                       if (MyEmptyExpr == null)
+                                               MyEmptyExpr = new EmptyExpression ();
+
+                                       MyEmptyExpr.SetType (expr_element_type);
+                                       Type target_element_type = TypeManager.GetElementType (target_type);
+
+                                       if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
+                                               if (ImplicitStandardConversionExists (MyEmptyExpr,
+                                                                                     target_element_type))
+                                                       return new EmptyCast (expr, target_type);
+                               }
+                       }
+
+                       // from an array-type to System.Array
+                       if (expr_type.IsArray && target_type == TypeManager.array_type)
+                               return new EmptyCast (expr, target_type);
+
+                       // from an array-type of type T to IList<T>
+                       if (expr_type.IsArray && Array_To_IList (expr_type, target_type))
+                               return new EmptyCast (expr, target_type);
+
+                       // from any delegate type to System.Delegate
+                       if ((expr_type == TypeManager.delegate_type || TypeManager.IsDelegateType (expr_type)) &&
+                           target_type == TypeManager.delegate_type)
+                               return new EmptyCast (expr, target_type);
+
+                       // from any array-type or delegate type into System.ICloneable.
+                       if (expr_type.IsArray ||
+                           expr_type == TypeManager.delegate_type || TypeManager.IsDelegateType (expr_type))
+                               if (target_type == TypeManager.icloneable_type)
+                                       return new EmptyCast (expr, target_type);
+
+                       // from a generic type definition to a generic instance.
+                       if (TypeManager.IsEqual (expr_type, target_type))
+                               return new EmptyCast (expr, target_type);
+
+                       return null;
+               }
+
+               //
+               // Tests whether an implicit reference conversion exists between expr_type
+               // and target_type
+               //
+               public static bool ImplicitReferenceConversionExists (Expression expr, Type target_type)
+               {
+                       if (target_type.IsValueType)
+                               return false;
+
+                       Type expr_type = expr.Type;
+
+                       if (TypeManager.IsGenericParameter (expr_type))
+                               return ImplicitTypeParameterConversion (expr, target_type) != null;
+
+                       //
+                       // This is the boxed case.
+                       //
+                       if (target_type == TypeManager.object_type) {
+                               if (expr_type.IsClass || TypeManager.IsValueType (expr_type) ||
+                                   expr_type.IsInterface || expr_type == TypeManager.enum_type)
+                                       if (target_type != TypeManager.anonymous_method_type)
+                                       return true;
+
+                               return false;
+                       } else if (TypeManager.IsSubclassOf (expr_type, target_type))
+                               return true;
+
+                       // Please remember that all code below actually comes
+                       // from ImplicitReferenceConversion so make sure code remains in sync
+
+                       // from any class-type S to any interface-type T.
+                       if (target_type.IsInterface) {
+                               if (target_type != TypeManager.iconvertible_type &&
+                                   expr_type.IsValueType && (expr is Constant) &&
+                                   !(expr is IntLiteral || expr is BoolLiteral ||
+                                     expr is FloatLiteral || expr is DoubleLiteral ||
+                                     expr is LongLiteral || expr is CharLiteral ||
+                                     expr is StringLiteral || expr is DecimalLiteral ||
+                                     expr is UIntLiteral || expr is ULongLiteral)) {
+                                       return false;
+                               }
+
+                               if (TypeManager.ImplementsInterface (expr_type, target_type))
+                                       return true;
+                       }
+
+                       // from any interface type S to interface-type T.
+                       if (expr_type.IsInterface && target_type.IsInterface)
+                               if (TypeManager.ImplementsInterface (expr_type, target_type))
+                                       return true;
+
+                       // from an array-type S to an array-type of type T
+                       if (expr_type.IsArray && target_type.IsArray) {
+                               if (expr_type.GetArrayRank () == target_type.GetArrayRank ()) {
+
+                                       Type expr_element_type = expr_type.GetElementType ();
+
+                                       if (MyEmptyExpr == null)
+                                               MyEmptyExpr = new EmptyExpression ();
+
+                                       MyEmptyExpr.SetType (expr_element_type);
+                                       Type target_element_type = TypeManager.GetElementType (target_type);
+
+                                       if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
+                                               if (ImplicitStandardConversionExists (MyEmptyExpr,
+                                                                                     target_element_type))
+                                                       return true;
+                               }
+                       }
+
+                       // from an array-type to System.Array
+                       if (expr_type.IsArray && (target_type == TypeManager.array_type))
+                               return true;
+
+                       // from an array-type of type T to IList<T>
+                       if (expr_type.IsArray && Array_To_IList (expr_type, target_type))
+                               return true;
+
+                       // from any delegate type to System.Delegate
+                       if ((expr_type == TypeManager.delegate_type || TypeManager.IsDelegateType (expr_type)) &&
+                           target_type == TypeManager.delegate_type)
+                               if (target_type.IsAssignableFrom (expr_type))
+                                       return true;
+
+                       // from any array-type or delegate type into System.ICloneable.
+                       if (expr_type.IsArray ||
+                           expr_type == TypeManager.delegate_type || TypeManager.IsDelegateType (expr_type))
+                               if (target_type == TypeManager.icloneable_type)
+                                       return true;
+
+                       // from the null type to any reference-type.
+                       if (expr_type == TypeManager.null_type){
+                               if (target_type.IsPointer)
+                                       return true;
+
+                               if (!target_type.IsValueType)
+                                       return true;
+                       }
+
+                       // from a generic type definition to a generic instance.
+                       if (TypeManager.IsEqual (expr_type, target_type))
+                               return true;
+
+                       return false;
+               }
+
+               /// <summary>
+               ///   Implicit Numeric Conversions.
+               ///
+               ///   expr is the expression to convert, returns a new expression of type
+               ///   target_type or null if an implicit conversion is not possible.
+               /// </summary>
+               static public Expression ImplicitNumericConversion (Expression expr,
+                                                                   Type target_type)
+               {
+                       Type expr_type = expr.Type;
+
+                       //
+                       // Attempt to do the implicit constant expression conversions
+
+                       if (expr is Constant){
+                               if (expr is IntConstant){
+                                       Expression e;
+
+                                       e = TryImplicitIntConversion (target_type, (IntConstant) expr);
+
+                                       if (e != null)
+                                               return e;
+                               } else if (expr is LongConstant && target_type == TypeManager.uint64_type){
+                                       //
+                                       // Try the implicit constant expression conversion
+                                       // from long to ulong, instead of a nice routine,
+                                       // we just inline it
+                                       //
+                                       long v = ((LongConstant) expr).Value;
+                                       if (v >= 0)
+                                               return new ULongConstant ((ulong) v, expr.Location);
+                               }
+                       }
+
+                       Type real_target_type = target_type;
+
+                       if (expr_type == TypeManager.sbyte_type){
+                               //
+                               // From sbyte to short, int, long, float, double, decimal
+                               //
+                               if (real_target_type == TypeManager.int32_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                               if (real_target_type == TypeManager.short_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
+                               if (real_target_type == TypeManager.decimal_type)
+                                       return new CastToDecimal (expr);
+                       } else if (expr_type == TypeManager.byte_type){
+                               //
+                               // From byte to short, ushort, int, uint, long, ulong, float, double, decimal
+                               //
+                               if ((real_target_type == TypeManager.short_type) ||
+                                   (real_target_type == TypeManager.ushort_type) ||
+                                   (real_target_type == TypeManager.int32_type) ||
+                                   (real_target_type == TypeManager.uint32_type))
+                                       return new EmptyCast (expr, target_type);
+
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                               if (real_target_type == TypeManager.decimal_type)
+                                       return new CastToDecimal (expr);
+
+                       } else if (expr_type == TypeManager.short_type){
+                               //
+                               // From short to int, long, float, double, decimal
+                               //
+                               if (real_target_type == TypeManager.int32_type)
+                                       return new EmptyCast (expr, target_type);
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                               if (real_target_type == TypeManager.decimal_type)
+                                       return new CastToDecimal (expr);
+
+                       } else if (expr_type == TypeManager.ushort_type){
+                               //
+                               // From ushort to int, uint, long, ulong, float, double, decimal
+                               //
+                               if (real_target_type == TypeManager.uint32_type)
+                                       return new EmptyCast (expr, target_type);
+
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+                               if (real_target_type == TypeManager.int32_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                               if (real_target_type == TypeManager.decimal_type)
+                                       return new CastToDecimal (expr);
+                       } else if (expr_type == TypeManager.int32_type){
+                               //
+                               // From int to long, float, double, decimal
+                               //
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                               if (real_target_type == TypeManager.decimal_type)
+                                       return new CastToDecimal (expr);
+                       } else if (expr_type == TypeManager.uint32_type){
+                               //
+                               // From uint to long, ulong, float, double, decimal
+                               //
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
+                                                              OpCodes.Conv_R8);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
+                                                              OpCodes.Conv_R4);
+                               if (real_target_type == TypeManager.decimal_type)
+                                       return new CastToDecimal (expr);
+                       } else if (expr_type == TypeManager.int64_type){
+                               //
+                               // From long/ulong to float, double
+                               //
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                               if (real_target_type == TypeManager.decimal_type)
+                                       return new CastToDecimal (expr);
+                       } else if (expr_type == TypeManager.uint64_type){
+                               //
+                               // From ulong to float, double
+                               //
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
+                                                              OpCodes.Conv_R8);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
+                                                              OpCodes.Conv_R4);
+                               if (real_target_type == TypeManager.decimal_type)
+                                       return new CastToDecimal (expr);
+                       } else if (expr_type == TypeManager.char_type){
+                               //
+                               // From char to ushort, int, uint, long, ulong, float, double, decimal
+                               //
+                               if ((real_target_type == TypeManager.ushort_type) ||
+                                   (real_target_type == TypeManager.int32_type) ||
+                                   (real_target_type == TypeManager.uint32_type))
+                                       return new EmptyCast (expr, target_type);
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                               if (real_target_type == TypeManager.decimal_type)
+                                       return new CastToDecimal (expr);
+                       } else if (expr_type == TypeManager.float_type){
+                               //
+                               // float to double
+                               //
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                       }
+
+                       return null;
+               }
+
+               /// <summary>
+               ///  Same as ImplicitStandardConversionExists except that it also looks at
+               ///  implicit user defined conversions - needed for overload resolution
+               /// </summary>
+               public static bool ImplicitConversionExists (EmitContext ec, Expression expr, Type target_type)
+               {
+#if GMCS_SOURCE
+                       if (expr is NullLiteral) {
+                               if (TypeManager.IsGenericParameter (target_type))
+                                       return TypeParameter_to_Null (target_type);
+
+                               if (TypeManager.IsNullableType (target_type))
+                                       return true;
+                       }
+#endif
+                       if (ImplicitStandardConversionExists (expr, target_type))
+                               return true;
+
+                       return ImplicitUserConversion (ec, expr, target_type, Location.Null) != null;
+               }
+
+               public static bool ImplicitUserConversionExists (EmitContext ec, Type source, Type target)
+               {
+                       return ImplicitUserConversion (ec, new EmptyExpression (source), target, Location.Null) != null;
+               }
+
+               /// <summary>
+               ///  Determines if a standard implicit conversion exists from
+               ///  expr_type to target_type
+               ///
+               ///  ec should point to a real EmitContext if expr.Type is TypeManager.anonymous_method_type.
+               /// </summary>
+               public static bool ImplicitStandardConversionExists (Expression expr, Type target_type)
+               {
+                       Type expr_type = expr.Type;
+#if GMCS_SOURCE
+                       if (TypeManager.IsNullableType (target_type)) {
+                               // if implicit standard conversion S -> T exists, S -> T? and S? -> T? also exists
+                               target_type = TypeManager.GetTypeArguments (target_type) [0];
+
+                               // S? -> T?
+                               if (TypeManager.IsNullableType (expr_type)) {
+                                       EmptyExpression new_expr = EmptyExpression.Grab ();
+                                       new_expr.SetType (TypeManager.GetTypeArguments (expr_type) [0]);
+                                       bool retval = ImplicitStandardConversionExists (new_expr, target_type);
+                                       EmptyExpression.Release (new_expr);
+                                       return retval;
+                               }
+                       }
+#endif
+                       if (expr_type == TypeManager.void_type)
+                               return false;
+
+                       //Console.WriteLine ("Expr is {0}", expr);
+                       //Console.WriteLine ("{0} -> {1} ?", expr_type, target_type);
+                       if (expr_type.Equals (target_type))
+                               return true;
+
+
+                       // First numeric conversions
+
+                       if (expr_type == TypeManager.sbyte_type){
+                               //
+                               // From sbyte to short, int, long, float, double, decimal
+                               //
+                               if ((target_type == TypeManager.int32_type) ||
+                                   (target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.float_type)  ||
+                                   (target_type == TypeManager.short_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+
+                       } else if (expr_type == TypeManager.byte_type){
+                               //
+                               // From byte to short, ushort, int, uint, long, ulong, float, double, decimal
+                               //
+                               if ((target_type == TypeManager.short_type) ||
+                                   (target_type == TypeManager.ushort_type) ||
+                                   (target_type == TypeManager.int32_type) ||
+                                   (target_type == TypeManager.uint32_type) ||
+                                   (target_type == TypeManager.uint64_type) ||
+                                   (target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+
+                       } else if (expr_type == TypeManager.short_type){
+                               //
+                               // From short to int, long, double, float, decimal 
+                               //
+                               if ((target_type == TypeManager.int32_type) ||
+                                   (target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+
+                       } else if (expr_type == TypeManager.ushort_type){
+                               //
+                               // From ushort to int, uint, long, ulong, double, float, decimal
+                               //
+                               if ((target_type == TypeManager.uint32_type) ||
+                                   (target_type == TypeManager.uint64_type) ||
+                                   (target_type == TypeManager.int32_type) ||
+                                   (target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+
+                       } else if (expr_type == TypeManager.int32_type){
+                               //
+                               // From int to long, double, float, decimal
+                               //
+                               if ((target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+
+                       } else if (expr_type == TypeManager.uint32_type){
+                               //
+                               // From uint to long, ulong, double, float, decimal
+                               //
+                               if ((target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.uint64_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+
+                       } else if ((expr_type == TypeManager.uint64_type) ||
+                                  (expr_type == TypeManager.int64_type)) {
+                               //
+                               // From long/ulong to double, float, decimal
+                               //
+                               if ((target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+
+                       } else if (expr_type == TypeManager.char_type){
+                               //
+                               // From char to ushort, int, uint, ulong, long, float, double, decimal
+                               //
+                               if ((target_type == TypeManager.ushort_type) ||
+                                   (target_type == TypeManager.int32_type) ||
+                                   (target_type == TypeManager.uint32_type) ||
+                                   (target_type == TypeManager.uint64_type) ||
+                                   (target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+
+                       } else if (expr_type == TypeManager.float_type){
+                               //
+                               // float to double
+                               //
+                               if (target_type == TypeManager.double_type)
+                                       return true;
+                       }
+
+                       if (expr.eclass == ExprClass.MethodGroup){
+                               if (TypeManager.IsDelegateType (target_type) && RootContext.Version != LanguageVersion.ISO_1){
+                                       MethodGroupExpr mg = expr as MethodGroupExpr;
+                                       if (mg != null){
+                                               return DelegateCreation.ImplicitStandardConversionExists (mg, target_type) != null;
+                                       }
+                               }
+                       }
+
+                       if (ImplicitReferenceConversionExists (expr, target_type))
+                               return true;
+
+                       //
+                       // Implicit Constant Expression Conversions
+                       //
+                       if (expr is IntConstant){
+                               int value = ((IntConstant) expr).Value;
+
+                               if (target_type == TypeManager.sbyte_type){
+                                       if (value >= SByte.MinValue && value <= SByte.MaxValue)
+                                               return true;
+                               } else if (target_type == TypeManager.byte_type){
+                                       if (value >= 0 && value <= Byte.MaxValue)
+                                               return true;
+                               } else if (target_type == TypeManager.short_type){
+                                       if (value >= Int16.MinValue && value <= Int16.MaxValue)
+                                               return true;
+                               } else if (target_type == TypeManager.ushort_type){
+                                       if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
+                                               return true;
+                               } else if (target_type == TypeManager.uint32_type){
+                                       if (value >= 0)
+                                               return true;
+                               } else if (target_type == TypeManager.uint64_type){
+                                        //
+                                        // we can optimize this case: a positive int32
+                                        // always fits on a uint64.  But we need an opcode
+                                        // to do it.
+                                        //
+                                       if (value >= 0)
+                                               return true;
+                               }
+
+                               if (value == 0 && expr is IntLiteral && TypeManager.IsEnumType (target_type))
+                                       return true;
+                       }
+
+                       if (expr is LongConstant && target_type == TypeManager.uint64_type){
+                               //
+                               // Try the implicit constant expression conversion
+                               // from long to ulong, instead of a nice routine,
+                               // we just inline it
+                               //
+                               long v = ((LongConstant) expr).Value;
+                               if (v >= 0)
+                                       return true;
+                       }
+
+                       if ((target_type == TypeManager.enum_type ||
+                            target_type.IsSubclassOf (TypeManager.enum_type)) &&
+                            expr is IntLiteral){
+                               IntLiteral i = (IntLiteral) expr;
+
+                               if (i.Value == 0)
+                                       return true;
+                       }
+
+                       //
+                       // If `expr_type' implements `target_type' (which is an iface)
+                       // see TryImplicitIntConversion
+                       //
+                       if (target_type.IsInterface && target_type.IsAssignableFrom (expr_type))
+                               return true;
+
+                       if (target_type == TypeManager.void_ptr_type && expr_type.IsPointer)
+                               return true;
+
+                       if (expr_type == TypeManager.anonymous_method_type){
+                               if (!TypeManager.IsDelegateType (target_type))
+                                       return false;
+
+                               AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
+                               return ame.ImplicitStandardConversionExists (target_type);
+                       }
+
+                       return false;
+               }
+
+               /// <summary>
+               ///  Finds "most encompassed type" according to the spec (13.4.2)
+               ///  amongst the methods in the MethodGroupExpr
+               /// </summary>
+               static Type FindMostEncompassedType (ArrayList types)
+               {
+                       Type best = null;
+
+                       if (types.Count == 0)
+                               return null;
+
+                       if (types.Count == 1)
+                               return (Type) types [0];
+
+                       EmptyExpression expr = EmptyExpression.Grab ();
+
+                       foreach (Type t in types) {
+                               if (best == null) {
+                                       best = t;
+                                       continue;
+                               }
+
+                               expr.SetType (t);
+                               if (ImplicitStandardConversionExists (expr, best))
+                                       best = t;
+                       }
+
+                       expr.SetType (best);
+                       foreach (Type t in types) {
+                               if (best == t)
+                                       continue;
+                               if (!ImplicitStandardConversionExists (expr, t)) {
+                                       best = null;
+                                       break;
+                               }
+                       }
+
+                       EmptyExpression.Release (expr);
+
+                       return best;
+               }
+
+               /// <summary>
+               ///  Finds "most encompassing type" according to the spec (13.4.2)
+               ///  amongst the types in the given set
+               /// </summary>
+               static Type FindMostEncompassingType (ArrayList types)
+               {
+                       Type best = null;
+
+                       if (types.Count == 0)
+                               return null;
+
+                       if (types.Count == 1)
+                               return (Type) types [0];
+
+                       EmptyExpression expr = EmptyExpression.Grab ();
+
+                       foreach (Type t in types) {
+                               if (best == null) {
+                                       best = t;
+                                       continue;
+                               }
+
+                               expr.SetType (best);
+                               if (ImplicitStandardConversionExists (expr, t))
+                                       best = t;
+                       }
+
+                       foreach (Type t in types) {
+                               if (best == t)
+                                       continue;
+                               expr.SetType (t);
+                               if (!ImplicitStandardConversionExists (expr, best)) {
+                                       best = null;
+                                       break;
+                               }
+                       }
+
+                       EmptyExpression.Release (expr);
+
+                       return best;
+               }
+
+               /// <summary>
+               ///   Finds the most specific source Sx according to the rules of the spec (13.4.4)
+               ///   by making use of FindMostEncomp* methods. Applies the correct rules separately
+               ///   for explicit and implicit conversion operators.
+               /// </summary>
+               static public Type FindMostSpecificSource (IList list,
+                                                          Expression source, bool apply_explicit_conv_rules)
+               {
+                       ArrayList src_types_set = new ArrayList ();
+
+                       //
+                       // If any operator converts from S then Sx = S
+                       //
+                       Type source_type = source.Type;
+                       foreach (MethodBase mb in list){
+                               ParameterData pd = TypeManager.GetParameterData (mb);
+                               Type param_type = pd.ParameterType (0);
+
+                               if (param_type == source_type)
+                                       return param_type;
+
+                               src_types_set.Add (param_type);
+                       }
+
+                       //
+                       // Explicit Conv rules
+                       //
+                       if (apply_explicit_conv_rules) {
+                               ArrayList candidate_set = new ArrayList ();
+
+                               foreach (Type param_type in src_types_set){
+                                       if (ImplicitStandardConversionExists (source, param_type))
+                                               candidate_set.Add (param_type);
+                               }
+
+                               if (candidate_set.Count != 0)
+                                       return FindMostEncompassedType (candidate_set);
+                       }
+
+                       //
+                       // Final case
+                       //
+                       if (apply_explicit_conv_rules)
+                               return FindMostEncompassingType (src_types_set);
+                       else
+                               return FindMostEncompassedType (src_types_set);
+               }
+
+               /// <summary>
+               ///  Finds the most specific target Tx according to section 13.4.4
+               /// </summary>
+               static public Type FindMostSpecificTarget (IList list,
+                                                          Type target, bool apply_explicit_conv_rules)
+               {
+                       ArrayList tgt_types_set = new ArrayList ();
+
+                       //
+                       // If any operator converts to T then Tx = T
+                       //
+                       foreach (MethodInfo mi in list){
+                               Type ret_type = mi.ReturnType;
+                               if (ret_type == target)
+                                       return ret_type;
+
+                               tgt_types_set.Add (ret_type);
+                       }
+
+                       //
+                       // Explicit conv rules
+                       //
+                       if (apply_explicit_conv_rules) {
+                               ArrayList candidate_set = new ArrayList ();
+
+                               EmptyExpression expr = EmptyExpression.Grab ();
+
+                               foreach (Type ret_type in tgt_types_set){
+                                       expr.SetType (ret_type);
+
+                                       if (ImplicitStandardConversionExists (expr, target))
+                                               candidate_set.Add (ret_type);
+                               }
+
+                               EmptyExpression.Release (expr);
+
+                               if (candidate_set.Count != 0)
+                                       return FindMostEncompassingType (candidate_set);
+                       }
+
+                       //
+                       // Okay, final case !
+                       //
+                       if (apply_explicit_conv_rules)
+                               return FindMostEncompassedType (tgt_types_set);
+                       else
+                               return FindMostEncompassingType (tgt_types_set);
+               }
+
+               /// <summary>
+               ///  User-defined Implicit conversions
+               /// </summary>
+               static public Expression ImplicitUserConversion (EmitContext ec, Expression source,
+                                                                Type target, Location loc)
+               {
+                       return UserDefinedConversion (ec, source, target, loc, false);
+               }
+
+               /// <summary>
+               ///  User-defined Explicit conversions
+               /// </summary>
+               static public Expression ExplicitUserConversion (EmitContext ec, Expression source,
+                                                                Type target, Location loc)
+               {
+                       return UserDefinedConversion (ec, source, target, loc, true);
+               }
+
+               static void AddConversionOperators (ArrayList list,
+                                                   Expression source, Type target_type,
+                                                   bool look_for_explicit,
+                                                   MethodGroupExpr mg)
+               {
+                       if (mg == null)
+                               return;
+
+                       Type source_type = source.Type;
+                       EmptyExpression expr = EmptyExpression.Grab ();
+                       foreach (MethodInfo m in mg.Methods) {
+                               ParameterData pd = TypeManager.GetParameterData (m);
+                               Type return_type = m.ReturnType;
+                               Type arg_type = pd.ParameterType (0);
+
+                               if (source_type != arg_type) {
+                                       if (!ImplicitStandardConversionExists (source, arg_type)) {
+                                               if (!look_for_explicit)
+                                                       continue;
+                                               expr.SetType (arg_type);
+                                               if (!ImplicitStandardConversionExists (expr, source_type))
+                                                       continue;
+                                       }
+                               }
+
+                               if (target_type != return_type) {
+                                       expr.SetType (return_type);
+                                       if (!ImplicitStandardConversionExists (expr, target_type)) {
+                                               if (!look_for_explicit)
+                                                       continue;
+                                               expr.SetType (target_type);
+                                               if (!ImplicitStandardConversionExists (expr, return_type))
+                                                       continue;
+                                       }
+                               }
+
+                               list.Add (m);
+                       }
+
+                       EmptyExpression.Release (expr);
+               }
+
+               /// <summary>
+               ///   Compute the user-defined conversion operator from source_type to target_type.
+               ///   `look_for_explicit' controls whether we should also include the list of explicit operators
+               /// </summary>
+               static MethodInfo GetConversionOperator (Type container_type, Expression source, Type target_type, bool look_for_explicit)
+               {
+                       ArrayList ops = new ArrayList (4);
+
+                       Type source_type = source.Type;
+
+                       if (source_type != TypeManager.decimal_type) {
+                               AddConversionOperators (ops, source, target_type, look_for_explicit,
+                                       Expression.MethodLookup (container_type, source_type, "op_Implicit", Location.Null) as MethodGroupExpr);
+                               if (look_for_explicit) {
+                                       AddConversionOperators (ops, source, target_type, look_for_explicit,
+                                               Expression.MethodLookup (
+                                                       container_type, source_type, "op_Explicit", Location.Null) as MethodGroupExpr);
+                               }
+                       }
+
+                       if (target_type != TypeManager.decimal_type) {
+                               AddConversionOperators (ops, source, target_type, look_for_explicit,
+                                       Expression.MethodLookup (container_type, target_type, "op_Implicit", Location.Null) as MethodGroupExpr);
+                               if (look_for_explicit) {
+                                       AddConversionOperators (ops, source, target_type, look_for_explicit,
+                                               Expression.MethodLookup (
+                                                       container_type, target_type, "op_Explicit", Location.Null) as MethodGroupExpr);
+                               }
+                       }
+
+                       if (ops.Count == 0)
+                               return null;
+
+                       Type most_specific_source = FindMostSpecificSource (ops, source, look_for_explicit);
+                       if (most_specific_source == null)
+                               return null;
+
+                       Type most_specific_target = FindMostSpecificTarget (ops, target_type, look_for_explicit);
+                       if (most_specific_target == null)
+                               return null;
+
+                       MethodInfo method = null;
+
+                       foreach (MethodInfo m in ops) {
+                               if (m.ReturnType != most_specific_target)
+                                       continue;
+                               if (TypeManager.GetParameterData (m).ParameterType (0) != most_specific_source)
+                                       continue;
+                               // Ambiguous: more than one conversion operator satisfies the signature.
+                               if (method != null)
+                                       return null;
+                               method = m;
+                       }
+
+                       return method;
+               }
+
+               static DoubleHash explicit_conv = new DoubleHash (100);
+               static DoubleHash implicit_conv = new DoubleHash (100);
+
+               /// <summary>
+               ///   User-defined conversions
+               /// </summary>
+               static public Expression UserDefinedConversion (EmitContext ec, Expression source,
+                                                               Type target, Location loc,
+                                                               bool look_for_explicit)
+               {
+                       Type source_type = source.Type;
+                       MethodInfo method = null;
+
+                       object o;
+                       DoubleHash hash = look_for_explicit ? explicit_conv : implicit_conv;
+
+                       if (!(source is Constant) && hash.Lookup (source_type, target, out o)) {
+                               method = (MethodInfo) o;
+                       } else {
+                               method = GetConversionOperator (null, source, target, look_for_explicit);
+                               if (!(source is Constant))
+                                       hash.Insert (source_type, target, method);
+                       }
+
+                       if (method == null)
+                               return null;
+
+                       Type most_specific_source = TypeManager.GetParameterData (method).ParameterType (0);
+
+                       //
+                       // This will do the conversion to the best match that we
+                       // found.  Now we need to perform an implict standard conversion
+                       // if the best match was not the type that we were requested
+                       // by target.
+                       //
+                       if (look_for_explicit)
+                               source = ExplicitConversionStandard (ec, source, most_specific_source, loc);
+                       else
+                               source = ImplicitConversionStandard (ec, source, most_specific_source, loc);
+
+                       if (source == null)
+                               return null;
+
+                       Expression e;
+                       e =  new UserCast (method, source, loc);
+                       if (e.Type != target){
+                               if (!look_for_explicit)
+                                       e = ImplicitConversionStandard (ec, e, target, loc);
+                               else
+                                       e = ExplicitConversionStandard (ec, e, target, loc);
+                       }
+
+                       return e;
+               }
+
+               /// <summary>
+               ///   Converts implicitly the resolved expression `expr' into the
+               ///   `target_type'.  It returns a new expression that can be used
+               ///   in a context that expects a `target_type'.
+               /// </summary>
+               static public Expression ImplicitConversion (EmitContext ec, Expression expr,
+                                                            Type target_type, Location loc)
+               {
+                       Expression e;
+
+                       if (target_type == null)
+                               throw new Exception ("Target type is null");
+
+                       e = ImplicitConversionStandard (ec, expr, target_type, loc);
+                       if (e != null)
+                               return e;
+
+                       e = ImplicitUserConversion (ec, expr, target_type, loc);
+                       if (e != null)
+                               return e;
+
+                       return null;
+               }
+
+
+               /// <summary>
+               ///   Attempts to apply the `Standard Implicit
+               ///   Conversion' rules to the expression `expr' into
+               ///   the `target_type'.  It returns a new expression
+               ///   that can be used in a context that expects a
+               ///   `target_type'.
+               ///
+               ///   This is different from `ImplicitConversion' in that the
+               ///   user defined implicit conversions are excluded.
+               /// </summary>
+               static public Expression ImplicitConversionStandard (EmitContext ec, Expression expr,
+                                                                    Type target_type, Location loc)
+               {
+                       Type expr_type = expr.Type;
+                       Expression e;
+#if GMCS_SOURCE
+                       // TODO: refactor to be a part of constant infrastructure
+                       if (expr is NullLiteral) {
+                           if (TypeManager.IsNullableType (target_type))
+                               return new Nullable.NullableLiteral (target_type, loc);
+                       }
+
+                       if (TypeManager.IsNullableType (target_type)) {
+                               Type target = TypeManager.GetTypeArguments (target_type) [0];
+
+                               if (TypeManager.IsNullableType (expr.Type)) {
+                                       e = new Nullable.LiftedConversion (
+                                               expr, target_type, false, false, loc).Resolve (ec);
+                                       if (e != null)
+                                               return e;
+                               } else {
+                                       e = ImplicitConversion (ec, expr, target, loc);
+                                       if (e != null)
+                                               return Nullable.Wrap.Create (e, ec);
+                               }
+                       }
+#endif
+                       if (expr.eclass == ExprClass.MethodGroup){
+                               if (!TypeManager.IsDelegateType (target_type)){
+                                       return null;
+                               }
+
+                               //
+                               // Only allow anonymous method conversions on post ISO_1
+                               //
+                               if (RootContext.Version != LanguageVersion.ISO_1){
+                                       MethodGroupExpr mg = expr as MethodGroupExpr;
+                                       if (mg != null)
+                                               return ImplicitDelegateCreation.Create (
+                                                       ec, mg, target_type, loc);
+                               }
+                       }
+
+                       if (expr_type.Equals (target_type) && !TypeManager.IsNullType (expr_type))
+                               return expr;
+
+                       e = ImplicitNumericConversion (expr, target_type);
+                       if (e != null)
+                               return e;
+
+                       e = ImplicitReferenceConversion (expr, target_type);
+                       if (e != null)
+                               return e;
+
+                       if (TypeManager.IsEnumType (target_type) && expr is IntLiteral){
+                               IntLiteral i = (IntLiteral) expr;
+
+                               if (i.Value == 0)
+                                       return new EnumConstant ((Constant) expr, target_type);
+                       }
+
+                       if (ec.InUnsafe) {
+                               if (expr_type.IsPointer){
+                                       if (target_type == TypeManager.void_ptr_type)
+                                               return new EmptyCast (expr, target_type);
+
+                                       //
+                                       // yep, comparing pointer types cant be done with
+                                       // t1 == t2, we have to compare their element types.
+                                       //
+                                       if (target_type.IsPointer){
+                                               if (TypeManager.GetElementType(target_type) == TypeManager.GetElementType(expr_type))
+                                                       return expr;
+
+                                               //return null;
+                                       }
+                               }
+
+                               if (expr_type == TypeManager.null_type && target_type.IsPointer)
+                                       return new EmptyCast (NullPointer.Null, target_type);
+                       }
+
+                       if (expr_type == TypeManager.anonymous_method_type){
+                               AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
+
+                               int errors = Report.Errors;
+
+                               Expression conv = ame.Compatible (ec, target_type);
+                               if (conv != null)
+                                       return conv;
+                               
+                               //
+                               // We return something instead of null, to avoid
+                               // the duplicate error, since am.Compatible would have
+                               // reported that already
+                               //
+                               if (errors != Report.Errors)
+                                       return new EmptyCast (expr, target_type);
+                       }
+
+                       return null;
+               }
+
+               /// <summary>
+               ///   Attempts to perform an implicit constant conversion of the IntConstant
+               ///   into a different data type using casts (See Implicit Constant
+               ///   Expression Conversions)
+               /// </summary>
+               static public Expression TryImplicitIntConversion (Type target_type, IntConstant ic)
+               {
+                       int value = ic.Value;
+
+                       if (target_type == TypeManager.sbyte_type){
+                               if (value >= SByte.MinValue && value <= SByte.MaxValue)
+                                       return new SByteConstant ((sbyte) value, ic.Location);
+                       } else if (target_type == TypeManager.byte_type){
+                               if (value >= Byte.MinValue && value <= Byte.MaxValue)
+                                       return new ByteConstant ((byte) value, ic.Location);
+                       } else if (target_type == TypeManager.short_type){
+                               if (value >= Int16.MinValue && value <= Int16.MaxValue)
+                                       return new ShortConstant ((short) value, ic.Location);
+                       } else if (target_type == TypeManager.ushort_type){
+                               if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
+                                       return new UShortConstant ((ushort) value, ic.Location);
+                       } else if (target_type == TypeManager.uint32_type){
+                               if (value >= 0)
+                                       return new UIntConstant ((uint) value, ic.Location);
+                       } else if (target_type == TypeManager.uint64_type){
+                               //
+                               // we can optimize this case: a positive int32
+                               // always fits on a uint64.  But we need an opcode
+                               // to do it.
+                               //
+                               if (value >= 0)
+                                       return new ULongConstant ((ulong) value, ic.Location);
+                       } else if (target_type == TypeManager.double_type)
+                               return new DoubleConstant ((double) value, ic.Location);
+                       else if (target_type == TypeManager.float_type)
+                               return new FloatConstant ((float) value, ic.Location);
+
+                       if (value == 0 && ic is IntLiteral && TypeManager.IsEnumType (target_type)){
+                               Type underlying = TypeManager.EnumToUnderlying (target_type);
+                               Constant e = (Constant) ic;
+
+                               //
+                               // Possibly, we need to create a different 0 literal before passing
+                               // to EnumConstant
+                               //
+                               if (underlying == TypeManager.int64_type)
+                                       e = new LongLiteral (0, ic.Location);
+                               else if (underlying == TypeManager.uint64_type)
+                                       e = new ULongLiteral (0, ic.Location);
+
+                               return new EnumConstant (e, target_type);
+                       }
+
+                       //
+                       // If `target_type' is an interface and the type of `ic' implements the interface
+                       // e.g. target_type is IComparable, IConvertible, IFormattable
+                       //
+                       if (target_type.IsInterface && target_type.IsAssignableFrom (ic.Type))
+                               return new BoxedCast (ic, target_type);
+
+                       return null;
+               }
+
+               /// <summary>
+               ///   Attempts to implicitly convert `source' into `target_type', using
+               ///   ImplicitConversion.  If there is no implicit conversion, then
+               ///   an error is signaled
+               /// </summary>
+               static public Expression ImplicitConversionRequired (EmitContext ec, Expression source,
+                                                                    Type target_type, Location loc)
+               {
+                       Expression e = ImplicitConversion (ec, source, target_type, loc);
+                       if (e != null)
+                               return e;
+
+                       source.Error_ValueCannotBeConverted (loc, target_type, false);
+                       return null;
+               }
+
+               /// <summary>
+               ///   Performs the explicit numeric conversions
+               ///
+               /// There are a few conversions that are not part of the C# standard,
+               /// they were interim hacks in the C# compiler that were supposed to
+               /// become explicit operators in the UIntPtr class and IntPtr class,
+               /// but for historical reasons it did not happen, so the C# compiler
+               /// ended up with these special hacks.
+               ///
+               /// See bug 59800 for details.
+               ///
+               /// The conversion are:
+               ///   UIntPtr->SByte
+               ///   UIntPtr->Int16
+               ///   UIntPtr->Int32
+               ///   IntPtr->UInt64
+               ///   UInt64->IntPtr
+               ///   SByte->UIntPtr
+               ///   Int16->UIntPtr
+               ///
+               /// </summary>
+               public static Expression ExplicitNumericConversion (Expression expr, Type target_type)
+               {
+                       Type expr_type = expr.Type;
+                       Type real_target_type = target_type;
+
+                       if (expr_type == TypeManager.sbyte_type){
+                               //
+                               // From sbyte to byte, ushort, uint, ulong, char, uintptr
+                               //
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I1_U1);
+                               if (real_target_type == TypeManager.ushort_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I1_U2);
+                               if (real_target_type == TypeManager.uint32_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I1_U4);
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I1_U8);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I1_CH);
+
+                               // One of the built-in conversions that belonged in the class library
+                               if (real_target_type == TypeManager.uintptr_type){
+                                       Expression u8e = new ConvCast (expr, TypeManager.uint64_type, ConvCast.Mode.I1_U8);
+
+                                       return new OperatorCast (u8e, TypeManager.uintptr_type, true);
+                               }
+                       } else if (expr_type == TypeManager.byte_type){
+                               //
+                               // From byte to sbyte and char
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U1_I1);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U1_CH);
+                       } else if (expr_type == TypeManager.short_type){
+                               //
+                               // From short to sbyte, byte, ushort, uint, ulong, char, uintptr
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I2_I1);
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I2_U1);
+                               if (real_target_type == TypeManager.ushort_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I2_U2);
+                               if (real_target_type == TypeManager.uint32_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I2_U4);
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I2_U8);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I2_CH);
+
+                               // One of the built-in conversions that belonged in the class library
+                               if (real_target_type == TypeManager.uintptr_type){
+                                       Expression u8e = new ConvCast (expr, TypeManager.uint64_type, ConvCast.Mode.I2_U8);
+
+                                       return new OperatorCast (u8e, TypeManager.uintptr_type, true);
+                               }
+                       } else if (expr_type == TypeManager.ushort_type){
+                               //
+                               // From ushort to sbyte, byte, short, char
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U2_I1);
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U2_U1);
+                               if (real_target_type == TypeManager.short_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U2_I2);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U2_CH);
+                       } else if (expr_type == TypeManager.int32_type){
+                               //
+                               // From int to sbyte, byte, short, ushort, uint, ulong, char, uintptr
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I4_I1);
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I4_U1);
+                               if (real_target_type == TypeManager.short_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I4_I2);
+                               if (real_target_type == TypeManager.ushort_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I4_U2);
+                               if (real_target_type == TypeManager.uint32_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I4_U4);
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I4_U8);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I4_CH);
+
+                               // One of the built-in conversions that belonged in the class library
+                               if (real_target_type == TypeManager.uintptr_type){
+                                       Expression u8e = new ConvCast (expr, TypeManager.uint64_type, ConvCast.Mode.I2_U8);
+
+                                       return new OperatorCast (u8e, TypeManager.uintptr_type, true);
+                               }
+                       } else if (expr_type == TypeManager.uint32_type){
+                               //
+                               // From uint to sbyte, byte, short, ushort, int, char
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U4_I1);
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U4_U1);
+                               if (real_target_type == TypeManager.short_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U4_I2);
+                               if (real_target_type == TypeManager.ushort_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U4_U2);
+                               if (real_target_type == TypeManager.int32_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U4_I4);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U4_CH);
+                       } else if (expr_type == TypeManager.int64_type){
+                               //
+                               // From long to sbyte, byte, short, ushort, int, uint, ulong, char
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I8_I1);
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I8_U1);
+                               if (real_target_type == TypeManager.short_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I8_I2);
+                               if (real_target_type == TypeManager.ushort_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I8_U2);
+                               if (real_target_type == TypeManager.int32_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I8_I4);
+                               if (real_target_type == TypeManager.uint32_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I8_U4);
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I8_U8);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.I8_CH);
+                       } else if (expr_type == TypeManager.uint64_type){
+                               //
+                               // From ulong to sbyte, byte, short, ushort, int, uint, long, char
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U8_I1);
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U8_U1);
+                               if (real_target_type == TypeManager.short_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U8_I2);
+                               if (real_target_type == TypeManager.ushort_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U8_U2);
+                               if (real_target_type == TypeManager.int32_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U8_I4);
+                               if (real_target_type == TypeManager.uint32_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U8_U4);
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U8_I8);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.U8_CH);
+
+                               // One of the built-in conversions that belonged in the class library
+                               if (real_target_type == TypeManager.intptr_type){
+                                       return new OperatorCast (new EmptyCast (expr, TypeManager.int64_type),
+                                                                TypeManager.intptr_type, true);
+                               }
+                       } else if (expr_type == TypeManager.char_type){
+                               //
+                               // From char to sbyte, byte, short
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.CH_I1);
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.CH_U1);
+                               if (real_target_type == TypeManager.short_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.CH_I2);
+                       } else if (expr_type == TypeManager.float_type){
+                               //
+                               // From float to sbyte, byte, short,
+                               // ushort, int, uint, long, ulong, char
+                               // or decimal
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R4_I1);
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R4_U1);
+                               if (real_target_type == TypeManager.short_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R4_I2);
+                               if (real_target_type == TypeManager.ushort_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R4_U2);
+                               if (real_target_type == TypeManager.int32_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R4_I4);
+                               if (real_target_type == TypeManager.uint32_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R4_U4);
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R4_I8);
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R4_U8);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R4_CH);
+                               if (real_target_type == TypeManager.decimal_type)
+                                       return new CastToDecimal (expr, true);
+                       } else if (expr_type == TypeManager.double_type){
+                               //
+                               // From double to sbyte, byte, short,
+                               // ushort, int, uint, long, ulong,
+                               // char, float or decimal
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_I1);
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_U1);
+                               if (real_target_type == TypeManager.short_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_I2);
+                               if (real_target_type == TypeManager.ushort_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_U2);
+                               if (real_target_type == TypeManager.int32_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_I4);
+                               if (real_target_type == TypeManager.uint32_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_U4);
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_I8);
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_U8);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_CH);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_R4);
+                               if (real_target_type == TypeManager.decimal_type)
+                                       return new CastToDecimal (expr, true);
+                       } else if (expr_type == TypeManager.uintptr_type){
+                               //
+                               // Various built-in conversions that belonged in the class library
+                               //
+                               // from uintptr to sbyte, short, int32
+                               //
+                               if (real_target_type == TypeManager.sbyte_type){
+                                       Expression uint32e = new OperatorCast (expr, TypeManager.uint32_type, true);
+                                       return new ConvCast (uint32e, TypeManager.sbyte_type, ConvCast.Mode.U4_I1);
+                               }
+                               if (real_target_type == TypeManager.short_type){
+                                       Expression uint32e = new OperatorCast (expr, TypeManager.uint32_type, true);
+                                       return new ConvCast (uint32e, TypeManager.sbyte_type, ConvCast.Mode.U4_I2);
+                               }
+                               if (real_target_type == TypeManager.int32_type){
+                                       return new EmptyCast (new OperatorCast (expr, TypeManager.uint32_type, true),
+                                                             TypeManager.int32_type);
+                               }
+                       } else if (expr_type == TypeManager.intptr_type){
+                               if (real_target_type == TypeManager.uint64_type){
+                                       return new EmptyCast (new OperatorCast (expr, TypeManager.int64_type, true),
+                                                             TypeManager.uint64_type);
+                               }
+                       } else if (expr_type == TypeManager.decimal_type) {
+                               return new CastFromDecimal (expr, target_type).Resolve ();
+                       }
+                       return null;
+               }
+
+               /// <summary>
+               ///  Returns whether an explicit reference conversion can be performed
+               ///  from source_type to target_type
+               /// </summary>
+               public static bool ExplicitReferenceConversionExists (Type source_type, Type target_type)
+               {
+                       bool target_is_type_param = TypeManager.IsGenericParameter (target_type);
+                       bool target_is_value_type = target_type.IsValueType;
+
+                       if (source_type == target_type)
+                               return true;
+
+                       //
+                       // From generic parameter to any type
+                       //
+                       if (TypeManager.IsGenericParameter (source_type))
+                               return ExplicitTypeParameterConversionExists (source_type, target_type);
+
+                       //
+                       // From object to a generic parameter
+                       //
+                       if (source_type == TypeManager.object_type && target_is_type_param)
+                               return true;
+
+                       //
+                       // From object to any reference type
+                       //
+                       if (source_type == TypeManager.object_type && !target_is_value_type)
+                               return true;
+
+                       //
+                       // From any class S to any class-type T, provided S is a base class of T
+                       //
+                       if (TypeManager.IsSubclassOf (target_type, source_type))
+                               return true;
+
+                       //
+                       // From any interface type S to any interface T provided S is not derived from T
+                       //
+                       if (source_type.IsInterface && target_type.IsInterface){
+                               if (!TypeManager.IsSubclassOf (target_type, source_type))
+                                       return true;
+                       }
+
+                       //
+                       // From any class type S to any interface T, provided S is not sealed
+                       // and provided S does not implement T.
+                       //
+                       if (target_type.IsInterface && !source_type.IsSealed &&
+                           !TypeManager.ImplementsInterface (source_type, target_type))
+                               return true;
+
+                       //
+                       // From any interface-type S to to any class type T, provided T is not
+                       // sealed, or provided T implements S.
+                       //
+                       if (source_type.IsInterface &&
+                           (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type)))
+                               return true;
+
+
+                       // From an array type S with an element type Se to an array type T with an
+                       // element type Te provided all the following are true:
+                       //     * S and T differe only in element type, in other words, S and T
+                       //       have the same number of dimensions.
+                       //     * Both Se and Te are reference types
+                       //     * An explicit referenc conversions exist from Se to Te
+                       //
+                       if (source_type.IsArray && target_type.IsArray) {
+                               if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
+
+                                       Type source_element_type = TypeManager.GetElementType (source_type);
+                                       Type target_element_type = TypeManager.GetElementType (target_type);
+
+                                       if (TypeManager.IsGenericParameter (source_element_type) ||
+                                           (!source_element_type.IsValueType && !target_element_type.IsValueType))
+                                               if (ExplicitReferenceConversionExists (source_element_type,
+                                                                                      target_element_type))
+                                                       return true;
+                               }
+                       }
+
+
+                       // From System.Array to any array-type
+                       if (source_type == TypeManager.array_type &&
+                           target_type.IsArray){
+                               return true;
+                       }
+
+                       //
+                       // From System delegate to any delegate-type
+                       //
+                       if (source_type == TypeManager.delegate_type &&
+                           TypeManager.IsDelegateType (target_type))
+                               return true;
+
+                       //
+                       // From ICloneable to Array or Delegate types
+                       //
+                       if (source_type == TypeManager.icloneable_type &&
+                           (target_type == TypeManager.array_type ||
+                            target_type == TypeManager.delegate_type))
+                               return true;
+
+                       return false;
+               }
+
+               /// <summary>
+               ///   Implements Explicit Reference conversions
+               /// </summary>
+               static Expression ExplicitReferenceConversion (Expression source, Type target_type)
+               {
+                       Type source_type = source.Type;
+                       bool target_is_type_param = TypeManager.IsGenericParameter (target_type);
+                       bool target_is_value_type = target_type.IsValueType;
+
+                       //
+                       // From object to a generic parameter
+                       //
+                       if (source_type == TypeManager.object_type && target_is_type_param)
+                               return new UnboxCast (source, target_type);
+
+                       //
+                       // Explicit type parameter conversion.
+                       //
+
+                       if (TypeManager.IsGenericParameter (source_type))
+                               return ExplicitTypeParameterConversion (source, target_type);
+
+                       //
+                       // From object to any reference type
+                       //
+                       if (source_type == TypeManager.object_type && !target_is_value_type)
+                               return new ClassCast (source, target_type);
+
+                       //
+                       // Unboxing conversion.
+                       //
+                       if (((source_type == TypeManager.enum_type &&
+                               !(source is EmptyCast)) ||
+                               source_type == TypeManager.value_type) && target_is_value_type)
+                               return new UnboxCast (source, target_type);
+
+                       //
+                       // From any class S to any class-type T, provided S is a base class of T
+                       //
+                       if (TypeManager.IsSubclassOf (target_type, source_type))
+                               return new ClassCast (source, target_type);
+
+                       //
+                       // From any interface type S to any interface T provided S is not derived from T
+                       //
+                       if (source_type.IsInterface && target_type.IsInterface){
+                               if (TypeManager.ImplementsInterface (source_type, target_type))
+                                       return null;
+                               else
+                                       return new ClassCast (source, target_type);
+                       }
+
+                       //
+                       // From any class type S to any interface T, provides S is not sealed
+                       // and provided S does not implement T.
+                       //
+                       if (target_type.IsInterface && !source_type.IsSealed) {
+                               if (TypeManager.ImplementsInterface (source_type, target_type))
+                                       return null;
+                               else
+                                       return new ClassCast (source, target_type);
+
+                       }
+
+                       //
+                       // From any interface-type S to to any class type T, provided T is not
+                       // sealed, or provided T implements S.
+                       //
+                       if (source_type.IsInterface) {
+                               if (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type)) {
+                                       if (target_type.IsClass)
+                                               return new ClassCast (source, target_type);
+                                       else
+                                               return new UnboxCast (source, target_type);
+                               }
+
+                               return null;
+                       }
+
+                       // From an array type S with an element type Se to an array type T with an
+                       // element type Te provided all the following are true:
+                       //     * S and T differe only in element type, in other words, S and T
+                       //       have the same number of dimensions.
+                       //     * Both Se and Te are reference types
+                       //     * An explicit referenc conversions exist from Se to Te
+                       //
+                       if (source_type.IsArray && target_type.IsArray) {
+                               if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
+
+                                       Type source_element_type = TypeManager.GetElementType (source_type);
+                                       Type target_element_type = TypeManager.GetElementType (target_type);
+
+                                       if (!source_element_type.IsValueType && !target_element_type.IsValueType)
+                                               if (ExplicitReferenceConversionExists (source_element_type,
+                                                                                      target_element_type))
+                                                       return new ClassCast (source, target_type);
+                               }
+                       }
+
+
+                       // From System.Array to any array-type
+                       if (source_type == TypeManager.array_type &&
+                           target_type.IsArray) {
+                               return new ClassCast (source, target_type);
+                       }
+
+                       //
+                       // From System delegate to any delegate-type
+                       //
+                       if (source_type == TypeManager.delegate_type &&
+                           TypeManager.IsDelegateType (target_type))
+                               return new ClassCast (source, target_type);
+
+                       //
+                       // From ICloneable to Array or Delegate types
+                       //
+                       if (source_type == TypeManager.icloneable_type &&
+                           (target_type == TypeManager.array_type ||
+                            target_type == TypeManager.delegate_type))
+                               return new ClassCast (source, target_type);
+
+                       return null;
+               }
+
+               /// <summary>
+               ///   Performs an explicit conversion of the expression `expr' whose
+               ///   type is expr.Type to `target_type'.
+               /// </summary>
+               static public Expression ExplicitConversionCore (EmitContext ec, Expression expr,
+                                                                Type target_type, Location loc)
+               {
+                       Type expr_type = expr.Type;
+
+                       // Explicit conversion includes implicit conversion and it used for enum underlying types too
+                       Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc);
+                       if (ne != null)
+                               return ne;
+
+                       //
+                       // Unboxing conversions; only object types can be convertible to enum
+                       //
+                       if (expr_type == TypeManager.object_type && target_type.IsValueType)
+                               return new UnboxCast (expr, target_type);
+
+                       if (TypeManager.IsEnumType (expr_type)) {
+                               if (expr is EnumConstant)
+                                       return ExplicitConversionCore (ec, ((EnumConstant) expr).Child, target_type, loc);
+
+                               return ExplicitConversionCore (ec, new EmptyCast (expr, TypeManager.EnumToUnderlying (expr_type)), target_type, loc);
+                       }
+
+                       if (TypeManager.IsEnumType (target_type)){
+                               if (expr_type == TypeManager.enum_type)
+                                       return new UnboxCast (expr, target_type);
+
+                               Expression ce = ExplicitConversionCore (ec, expr, TypeManager.EnumToUnderlying (target_type), loc);
+                               if (ce != null)
+                                       return new EmptyCast (ce, target_type);
+                       }
+
+                       ne = ExplicitNumericConversion (expr, target_type);
+                       if (ne != null)
+                               return ne;
+
+                       //
+                       // Skip the ExplicitReferenceConversion because we can not convert
+                       // from Null to a ValueType, and ExplicitReference wont check against
+                       // null literal explicitly
+                       //
+                       if (expr_type != TypeManager.null_type){
+                               ne = ExplicitReferenceConversion (expr, target_type);
+                               if (ne != null)
+                                       return ne;
+                       }
+
+                       if (ec.InUnsafe){
+                               ne = ExplicitUnsafe (expr, target_type);
+                               if (ne != null)
+                                       return ne;
+                       }
+
+                       ne = ExplicitUserConversion (ec, expr, target_type, loc);
+                       if (ne != null)
+                               return ne;
+
+                       return null;
+               }
+
+               public static Expression ExplicitUnsafe (Expression expr, Type target_type)
+               {
+                       Type expr_type = expr.Type;
+
+                       if (target_type.IsPointer){
+                               if (expr_type.IsPointer)
+                                       return new EmptyCast (expr, target_type);
+
+                               if (expr_type == TypeManager.sbyte_type ||
+                                       expr_type == TypeManager.short_type ||
+                                       expr_type == TypeManager.int32_type ||
+                                       expr_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I);
+
+                               if (expr_type == TypeManager.ushort_type ||
+                                       expr_type == TypeManager.uint32_type ||
+                                       expr_type == TypeManager.uint64_type ||
+                                       expr_type == TypeManager.byte_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U);
+                       }
+
+                       if (expr_type.IsPointer){
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
+                               else if (target_type == TypeManager.byte_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
+                               else if (target_type == TypeManager.short_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
+                               else if (target_type == TypeManager.ushort_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
+                               else if (target_type == TypeManager.int32_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
+                               else if (target_type == TypeManager.uint32_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
+                               else if (target_type == TypeManager.uint64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+                               else if (target_type == TypeManager.int64_type){
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               }
+                       }
+                       return null;
+               }
+
+               /// <summary>
+               ///   Same as ExplicitConversion, only it doesn't include user defined conversions
+               /// </summary>
+               static public Expression ExplicitConversionStandard (EmitContext ec, Expression expr,
+                                                                    Type target_type, Location l)
+               {
+                       int errors = Report.Errors;
+                       Expression ne = ImplicitConversionStandard (ec, expr, target_type, l);
+                       if (Report.Errors > errors)
+                               return null;
+
+                       if (ne != null)
+                               return ne;
+
+                       ne = ExplicitNumericConversion (expr, target_type);
+                       if (ne != null)
+                               return ne;
+
+                       ne = ExplicitReferenceConversion (expr, target_type);
+                       if (ne != null)
+                               return ne;
+
+                       if (ec.InUnsafe && expr.Type == TypeManager.void_ptr_type && target_type.IsPointer)
+                               return new EmptyCast (expr, target_type);
+
+                       expr.Error_ValueCannotBeConverted (l, target_type, true);
+                       return null;
+               }
+
+               /// <summary>
+               ///   Performs an explicit conversion of the expression `expr' whose
+               ///   type is expr.Type to `target_type'.
+               /// </summary>
+               static public Expression ExplicitConversion (EmitContext ec, Expression expr,
+                       Type target_type, Location loc)
+               {
+                       Expression e;
+#if GMCS_SOURCE
+                       Type expr_type = expr.Type;
+                       if (TypeManager.IsNullableType (target_type)) {
+                               if (TypeManager.IsNullableType (expr_type)) {
+                                       e = new Nullable.LiftedConversion (
+                                               expr, target_type, false, true, loc).Resolve (ec);
+                                       if (e != null)
+                                               return e;
+                               } else if (expr_type == TypeManager.object_type) {
+                                       return new UnboxCast (expr, target_type);
+                               } else {
+                                       Type target = TypeManager.GetTypeArguments (target_type) [0];
+
+                                       e = ExplicitConversionCore (ec, expr, target, loc);
+                                       if (e != null)
+                                               return Nullable.Wrap.Create (e, ec);
+                               }
+                       } else if (TypeManager.IsNullableType (expr_type)) {
+                               Expression source = Nullable.Unwrap.Create (expr, ec);
+                               if (source != null) {
+                                       e = ExplicitConversionCore (ec, source, target_type, loc);
+                                       if (e != null)
+                                               return e;
+                               }
+                       }
+#endif
+                       e = ExplicitConversionCore (ec, expr, target_type, loc);
+                       if (e != null)
+                               return e;
+
+                       expr.Error_ValueCannotBeConverted (loc, target_type, true);
+                       return null;
+               }
+       }
+}
diff --git a/mcs/mcs/cs-parser.jay b/mcs/mcs/cs-parser.jay
new file mode 100644 (file)
index 0000000..92ab90e
--- /dev/null
@@ -0,0 +1,4973 @@
+%{
+//
+// cs-parser.jay: The Parser for the C# compiler
+//
+// Authors: Miguel de Icaza (miguel@gnu.org)
+//          Ravi Pratap     (ravi@ximian.com)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+// (C) 2004 Novell, Inc
+//
+// TODO:
+//   (1) Figure out why error productions dont work.  `type-declaration' is a
+//       great spot to put an `error' because you can reproduce it with this input:
+//      "public X { }"
+//
+// Possible optimization:
+//   Run memory profiler with parsing only, and consider dropping 
+//   arraylists where not needed.   Some pieces can use linked lists.
+//
+using System.Text;
+using System.IO;
+using System;
+
+namespace Mono.CSharp
+{
+       using System.Collections;
+
+       /// <summary>
+       ///    The C# Parser
+       /// </summary>
+       public class CSharpParser {
+               NamespaceEntry  current_namespace;
+               TypeContainer   current_container;
+               DeclSpace       current_class;
+       
+               IAnonymousHost anonymous_host;
+
+               /// <summary>
+               ///   Current block is used to add statements as we find
+               ///   them.  
+               /// </summary>
+               Block      current_block, top_current_block;
+
+               Delegate   current_delegate;
+
+               AnonymousMethodExpression current_anonymous_method;
+
+               /// <summary>
+               ///   This is used by the unary_expression code to resolve
+               ///   a name against a parameter.  
+               /// </summary>
+               Parameters current_local_parameters;
+
+               /// <summary>
+               ///   Using during property parsing to describe the implicit
+               ///   value parameter that is passed to the "set" and "get"accesor
+               ///   methods (properties and indexers).
+               /// </summary>
+               Expression implicit_value_parameter_type;
+               Parameters indexer_parameters;
+
+               /// <summary>
+               ///   Hack to help create non-typed array initializer
+               /// </summary>
+               public static Expression current_array_type;
+               Expression pushed_current_array_type;
+
+               /// <summary>
+               ///   Used to determine if we are parsing the get/set pair
+               ///   of an indexer or a property
+               /// </summmary>
+               bool parsing_indexer;
+
+               bool parsing_anonymous_method;
+
+               ///
+               /// An out-of-band stack.
+               ///
+               Stack oob_stack;
+
+               ///
+               /// Switch stack.
+               ///
+               Stack switch_stack;
+
+               static public int yacc_verbose_flag;
+
+               // Name of the file we are parsing
+               public string name;
+
+               ///
+               /// The current file.
+               ///
+               SourceFile file;
+
+               ///
+               /// Temporary Xml documentation cache.
+               /// For enum types, we need one more temporary store.
+               ///
+               string tmpComment;
+               string enumTypeComment;
+                       
+               /// Current attribute target
+               string current_attr_target;
+               
+               /// assembly and module attribute definitions are enabled
+               bool global_attrs_enabled = true;
+               bool has_get, has_set;
+
+%}
+
+%token EOF
+%token NONE   /* This token is never returned by our lexer */
+%token ERROR           // This is used not by the parser, but by the tokenizer.
+                       // do not remove.
+
+/*
+ *These are the C# keywords
+ */
+%token FIRST_KEYWORD
+%token ABSTRACT        
+%token AS
+%token ADD
+%token ASSEMBLY
+%token BASE    
+%token BOOL    
+%token BREAK   
+%token BYTE    
+%token CASE    
+%token CATCH   
+%token CHAR    
+%token CHECKED 
+%token CLASS   
+%token CONST   
+%token CONTINUE        
+%token DECIMAL 
+%token DEFAULT 
+%token DELEGATE        
+%token DO      
+%token DOUBLE  
+%token ELSE    
+%token ENUM    
+%token EVENT   
+%token EXPLICIT        
+%token EXTERN  
+%token FALSE   
+%token FINALLY 
+%token FIXED   
+%token FLOAT   
+%token FOR     
+%token FOREACH 
+%token GOTO    
+%token IF      
+%token IMPLICIT        
+%token IN      
+%token INT     
+%token INTERFACE
+%token INTERNAL        
+%token IS      
+%token LOCK    
+%token LONG    
+%token NAMESPACE
+%token NEW     
+%token NULL    
+%token OBJECT  
+%token OPERATOR        
+%token OUT     
+%token OVERRIDE        
+%token PARAMS  
+%token PRIVATE 
+%token PROTECTED
+%token PUBLIC  
+%token READONLY        
+%token REF     
+%token RETURN  
+%token REMOVE
+%token SBYTE   
+%token SEALED  
+%token SHORT   
+%token SIZEOF  
+%token STACKALLOC
+%token STATIC  
+%token STRING  
+%token STRUCT  
+%token SWITCH  
+%token THIS    
+%token THROW   
+%token TRUE    
+%token TRY     
+%token TYPEOF  
+%token UINT    
+%token ULONG   
+%token UNCHECKED
+%token UNSAFE  
+%token USHORT  
+%token USING   
+%token VIRTUAL 
+%token VOID    
+%token VOLATILE
+%token WHILE   
+%token ARGLIST
+%token PARTIAL
+
+/* C# keywords which are not really keywords */
+%token GET           "get"
+%token SET           "set"
+
+%left LAST_KEYWORD
+
+/* C# single character operators/punctuation. */
+%token OPEN_BRACE    "{"
+%token CLOSE_BRACE   "}"
+%token OPEN_BRACKET  "["
+%token CLOSE_BRACKET "]"
+%token OPEN_PARENS   "("
+%token CLOSE_PARENS  ")"
+%token DOT           "."
+%token COMMA         ","
+%token COLON         ":"
+%token SEMICOLON     ";"
+%token TILDE         "~"
+
+%token PLUS           "+"
+%token MINUS          "-"
+%token BANG           "!"
+%token ASSIGN         "="
+%token OP_LT          "<"
+%token OP_GT          ">"
+%token BITWISE_AND    "&"
+%token BITWISE_OR     "|"
+%token STAR           "*"
+%token PERCENT        "%"
+%token DIV            "/"
+%token CARRET         "^"
+%token INTERR         "?"
+
+/* C# multi-character operators. */
+%token DOUBLE_COLON          "::"
+%token OP_INC                 "++"
+%token OP_DEC                 "--"
+%token OP_SHIFT_LEFT          "<<"
+%token OP_SHIFT_RIGHT         ">>"
+%token OP_LE                  "<="
+%token OP_GE                  ">="
+%token OP_EQ                  "=="
+%token OP_NE                  "!="
+%token OP_AND                 "&&"
+%token OP_OR                  "||"
+%token OP_MULT_ASSIGN         "*="
+%token OP_DIV_ASSIGN          "/="
+%token OP_MOD_ASSIGN          "%="
+%token OP_ADD_ASSIGN          "+="
+%token OP_SUB_ASSIGN          "-="
+%token OP_SHIFT_LEFT_ASSIGN   "<<="
+%token OP_SHIFT_RIGHT_ASSIGN  ">>="
+%token OP_AND_ASSIGN          "&="
+%token OP_XOR_ASSIGN          "^="
+%token OP_OR_ASSIGN           "|="
+%token OP_PTR                 "->"
+
+/* Numbers */
+%token LITERAL_INTEGER           "int literal"
+%token LITERAL_FLOAT             "float literal"
+%token LITERAL_DOUBLE            "double literal"
+%token LITERAL_DECIMAL           "decimal literal"
+%token LITERAL_CHARACTER         "character literal"
+%token LITERAL_STRING            "string literal"
+
+%token IDENTIFIER
+%token CLOSE_PARENS_CAST
+%token CLOSE_PARENS_NO_CAST
+%token CLOSE_PARENS_OPEN_PARENS
+%token CLOSE_PARENS_MINUS
+
+/* Add precedence rules to solve dangling else s/r conflict */
+%nonassoc LOWPREC
+%nonassoc IF
+%nonassoc ELSE
+%right ASSIGN
+%left OP_OR
+%left OP_AND
+%left BITWISE_OR
+%left BITWISE_AND
+%left OP_SHIFT_LEFT OP_SHIFT_RIGHT
+%left PLUS MINUS
+%left STAR DIV PERCENT
+%right BANG CARRET UMINUS
+%nonassoc OP_INC OP_DEC
+%left OPEN_PARENS
+%left OPEN_BRACKET OPEN_BRACE
+%left DOT
+%nonassoc HIGHPREC
+
+%start compilation_unit
+%%
+
+compilation_unit
+        : outer_declarations opt_EOF
+        | outer_declarations global_attributes opt_EOF
+        | global_attributes opt_EOF
+       | opt_EOF /* allow empty files */
+        ;
+       
+opt_EOF
+       : /* empty */
+         {
+               Lexer.check_incorrect_doc_comment ();
+         }
+       | EOF
+         {
+               Lexer.check_incorrect_doc_comment ();
+         }
+       ;
+
+outer_declarations
+        : outer_declaration
+        | outer_declarations outer_declaration
+        ;
+outer_declaration
+       : extern_alias_directive
+        | using_directive 
+        | namespace_member_declaration
+        ;
+
+extern_alias_directives
+       : extern_alias_directive
+       | extern_alias_directives extern_alias_directive;
+
+extern_alias_directive
+       : EXTERN IDENTIFIER IDENTIFIER SEMICOLON
+         {
+               LocatedToken lt = (LocatedToken) $2;
+               string s = lt.Value;
+               if (s != "alias"){
+                       Report.Error (1003, lt.Location, "'alias' expected");
+               } else if (RootContext.Version == LanguageVersion.ISO_1) {
+                       Report.FeatureIsNotStandardized (lt.Location, "external alias");
+               } else {
+                       lt = (LocatedToken) $3; 
+                       current_namespace.UsingExternalAlias (lt.Value, lt.Location);
+               }
+         }
+       ;
+using_directives
+       : using_directive 
+       | using_directives using_directive
+       ;
+
+using_directive
+       : using_alias_directive
+         {
+               if (RootContext.Documentation != null)
+                       Lexer.doc_state = XmlCommentState.Allowed;
+         }
+       | using_namespace_directive
+         {
+               if (RootContext.Documentation != null)
+                       Lexer.doc_state = XmlCommentState.Allowed;
+         }
+       ;
+
+using_alias_directive
+       : USING IDENTIFIER ASSIGN 
+         namespace_or_type_name SEMICOLON
+         {
+               LocatedToken lt = (LocatedToken) $2;
+               current_namespace.UsingAlias (lt.Value, (MemberName) $4, (Location) $1);
+         }
+       | USING error {
+               CheckIdentifierToken (yyToken, GetLocation ($2));
+         }
+       ;
+
+using_namespace_directive
+       : USING namespace_name SEMICOLON 
+         {
+               current_namespace.Using ((MemberName) $2, (Location) $1);
+          }
+       ;
+
+//
+// Strictly speaking, namespaces don't have attributes but
+// we parse global attributes along with namespace declarations and then
+// detach them
+// 
+namespace_declaration
+       : opt_attributes NAMESPACE namespace_or_type_name
+         {
+               MemberName name = (MemberName) $3;
+
+               if ($1 != null) {
+                       Report.Error(1671, name.Location, "A namespace declaration cannot have modifiers or attributes");
+               }
+
+               current_namespace = new NamespaceEntry (
+                       current_namespace, file, name.GetName ());
+               current_class = current_namespace.SlaveDeclSpace;
+               current_container = current_class.PartialContainer;
+         } 
+         namespace_body opt_semicolon
+         { 
+               current_namespace = current_namespace.Parent;
+               current_class = current_namespace.SlaveDeclSpace;
+               current_container = current_class.PartialContainer;
+         }
+       ;
+
+opt_semicolon
+       : /* empty */
+       | SEMICOLON
+       ;
+
+opt_comma
+       : /* empty */
+       | COMMA
+       ;
+
+namespace_name
+       : namespace_or_type_name
+       ;
+
+namespace_body
+       : OPEN_BRACE
+         {
+               if (RootContext.Documentation != null)
+                       Lexer.doc_state = XmlCommentState.Allowed;
+         }
+         opt_extern_alias_directives
+         opt_using_directives
+         opt_namespace_member_declarations
+         CLOSE_BRACE
+       ;
+
+opt_using_directives
+       : /* empty */
+       | using_directives
+       ;
+
+opt_extern_alias_directives
+       : /* empty */
+       | extern_alias_directives
+       ;
+
+opt_namespace_member_declarations
+       : /* empty */
+       | namespace_member_declarations
+       ;
+
+namespace_member_declarations
+       : namespace_member_declaration
+       | namespace_member_declarations namespace_member_declaration
+       ;
+
+namespace_member_declaration
+       : type_declaration
+         {
+               if ($1 != null) {
+                       DeclSpace ds = (DeclSpace)$1;
+
+                       if ((ds.ModFlags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
+                               Report.Error (1527, ds.Location, 
+                               "Namespace elements cannot be explicitly declared as private, protected or protected internal");
+                       }
+               }
+               current_namespace.DeclarationFound = true;
+         }
+       | namespace_declaration {
+               current_namespace.DeclarationFound = true;
+         }
+
+       | field_declaration {
+               Report.Error (116, ((MemberCore) $1).Location, "A namespace can only contain types and namespace declarations");
+         }
+       | method_declaration {
+               Report.Error (116, ((MemberCore) $1).Location, "A namespace can only contain types and namespace declarations");
+         }
+       ;
+
+type_declaration
+       : class_declaration             
+       | struct_declaration            
+       | interface_declaration         
+       | enum_declaration              
+       | delegate_declaration
+//
+// Enable this when we have handled all errors, because this acts as a generic fallback
+//
+//     | error {
+//             Console.WriteLine ("Token=" + yyToken);
+//             Report.Error (1518, GetLocation ($1), "Expected class, struct, interface, enum or delegate");
+//       }
+       ;
+
+//
+// Attributes 17.2
+//
+
+global_attributes
+       : attribute_sections
+{
+       if ($1 != null)
+               CodeGen.Assembly.AddAttributes (((Attributes)$1).Attrs);
+
+       $$ = $1;
+}
+
+opt_attributes
+       : /* empty */ 
+         {
+               global_attrs_enabled = false;
+               $$ = null;
+      }
+       | attribute_sections
+         { 
+               global_attrs_enabled = false;
+               $$ = $1;
+         }
+    ;
+
+attribute_sections
+       : attribute_section
+         {
+               ArrayList sect = (ArrayList) $1;
+
+               if (global_attrs_enabled) {
+                       if (current_attr_target == "module") {
+                               CodeGen.Module.AddAttributes (sect);
+                               $$ = null;
+                       } else if (current_attr_target != null && current_attr_target.Length > 0) {
+                               CodeGen.Assembly.AddAttributes (sect);
+                               $$ = null;
+                       } else {
+                               $$ = new Attributes (sect);
+                       }
+                       if ($$ == null) {
+                               if (RootContext.Documentation != null) {
+                                       Lexer.check_incorrect_doc_comment ();
+                                       Lexer.doc_state =
+                                               XmlCommentState.Allowed;
+                               }
+                       }
+               } else {
+                       $$ = new Attributes (sect);
+               }               
+               current_attr_target = null;
+         }
+       | attribute_sections attribute_section
+         {
+               Attributes attrs = $1 as Attributes;
+               ArrayList sect = (ArrayList) $2;
+
+               if (global_attrs_enabled) {
+                       if (current_attr_target == "module") {
+                               CodeGen.Module.AddAttributes (sect);
+                               $$ = null;
+                       } else if (current_attr_target == "assembly") {
+                               CodeGen.Assembly.AddAttributes (sect);
+                               $$ = null;
+                       } else {
+                               if (attrs == null)
+                                       attrs = new Attributes (sect);
+                               else
+                                       attrs.AddAttributes (sect);                     
+                       }
+               } else {
+                       if (attrs == null)
+                               attrs = new Attributes (sect);
+                       else
+                               attrs.AddAttributes (sect);
+               }               
+               $$ = attrs;
+               current_attr_target = null;
+         }
+       ;
+
+attribute_section
+       : OPEN_BRACKET attribute_target_specifier attribute_list opt_comma CLOSE_BRACKET
+         {
+               $$ = $3;
+         }
+        | OPEN_BRACKET attribute_list opt_comma CLOSE_BRACKET
+         {
+               $$ = $2;
+         }
+       ;
+attribute_target_specifier
+       : attribute_target COLON
+         {
+               current_attr_target = (string)$1;
+               $$ = $1;
+         }
+       ;
+
+attribute_target
+       : IDENTIFIER
+         {
+               LocatedToken lt = (LocatedToken) $1;
+               CheckAttributeTarget (lt.Value, lt.Location);
+               $$ = lt.Value; // Location won't be required anymore.
+         }
+        | EVENT  { $$ = "event"; }       
+        | RETURN { $$ = "return"; }
+       ;
+
+attribute_list
+       : attribute
+         {
+               ArrayList attrs = new ArrayList (4);
+               attrs.Add ($1);
+
+               $$ = attrs;
+              
+         }
+       | attribute_list COMMA attribute
+         {
+               ArrayList attrs = (ArrayList) $1;
+               attrs.Add ($3);
+
+               $$ = attrs;
+         }
+       ;
+
+attribute
+       : attribute_name opt_attribute_arguments
+         {
+               MemberName mname = (MemberName) $1;
+               object[] arguments = (object[]) $2;
+               MemberName left = mname.Left;
+               string identifier = mname.Name;
+
+               Expression left_expr = left == null ? null : left.GetTypeExpression ();
+
+               if (current_attr_target == "assembly" || current_attr_target == "module")
+                       // FIXME: supply "nameEscaped" parameter here.
+                       $$ = new GlobalAttribute (current_namespace, current_attr_target,
+                                                 left_expr, identifier, arguments, mname.Location, lexer.IsEscapedIdentifier (mname.Location));
+               else
+                       $$ = new Attribute (current_attr_target, left_expr, identifier, arguments, mname.Location, lexer.IsEscapedIdentifier (mname.Location));
+         }
+       ;
+
+attribute_name
+       : namespace_or_type_name  { /* reserved attribute name or identifier: 17.4 */ }
+       ;
+
+opt_attribute_arguments
+       : /* empty */   { $$ = null; }
+       | OPEN_PARENS attribute_arguments CLOSE_PARENS
+         {
+               $$ = $2;
+         }
+       ;
+
+
+attribute_arguments
+       : opt_positional_argument_list
+         {
+               if ($1 == null)
+                       $$ = null;
+               else {
+                       $$ = new object [] { $1, null };
+               }
+         }
+    | positional_argument_list COMMA named_argument_list
+         {
+               $$ = new object[] { $1, $3 };
+         }
+    | named_argument_list
+         {
+               $$ = new object [] { null, $1 };
+         }
+    ;
+
+
+opt_positional_argument_list
+       : /* empty */           { $$ = null; } 
+       | positional_argument_list
+       ;
+
+positional_argument_list
+       : expression
+         {
+               ArrayList args = new ArrayList (4);
+               args.Add (new Argument ((Expression) $1, Argument.AType.Expression));
+
+               $$ = args;
+         }
+        | positional_argument_list COMMA expression
+        {
+               ArrayList args = (ArrayList) $1;
+               args.Add (new Argument ((Expression) $3, Argument.AType.Expression));
+
+               $$ = args;
+        }
+        ;
+
+named_argument_list
+       : named_argument
+         {
+               ArrayList args = new ArrayList (4);
+               args.Add ($1);
+
+               $$ = args;
+         }
+        | named_argument_list COMMA named_argument
+         {       
+               ArrayList args = (ArrayList) $1;
+               args.Add ($3);
+
+               $$ = args;
+         }
+         | named_argument_list COMMA expression
+           {
+                 Report.Error (1016, ((Expression) $3).Location, "Named attribute argument expected");
+                 $$ = null;
+               }
+        ;
+
+named_argument
+       : IDENTIFIER ASSIGN expression
+         {
+               // FIXME: keep location
+               $$ = new DictionaryEntry (
+                       ((LocatedToken) $1).Value, 
+                       new Argument ((Expression) $3, Argument.AType.Expression));
+         }
+       ;
+
+                 
+class_body
+       :  OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
+       ;
+
+opt_class_member_declarations
+       : /* empty */
+       | class_member_declarations
+       ;
+
+class_member_declarations
+       : class_member_declaration
+       | class_member_declarations 
+         class_member_declaration
+       ;
+
+class_member_declaration
+       : constant_declaration                  // done
+       | field_declaration                     // done
+       | method_declaration                    // done
+       | property_declaration                  // done
+       | event_declaration                     // done
+       | indexer_declaration                   // done
+       | operator_declaration                  // done
+       | constructor_declaration               // done
+       | destructor_declaration                // done
+       | type_declaration
+       ;
+
+struct_declaration
+       : opt_attributes
+         opt_modifiers
+         opt_partial
+         STRUCT member_name
+         { 
+               MemberName name = MakeName ((MemberName) $5);
+               push_current_class (new Struct (
+                       current_namespace, current_class, name, (int) $2,
+                       (Attributes) $1), false, $3);
+
+         }
+         opt_class_base
+         {
+               if ($7 != null)
+                       current_container.AddBasesForPart (current_class, (ArrayList) $7);
+
+               if (RootContext.Documentation != null)
+                       current_container.DocComment = Lexer.consume_doc_comment ();
+         }
+         struct_body
+         {
+               if (RootContext.Documentation != null)
+                       Lexer.doc_state = XmlCommentState.Allowed;
+         }
+         opt_semicolon
+         {
+               $$ = pop_current_class ();
+         }
+       | opt_attributes opt_modifiers opt_partial STRUCT error {
+               CheckIdentifierToken (yyToken, GetLocation ($5));
+         }
+       ;
+
+struct_body
+       : OPEN_BRACE
+         {
+               if (RootContext.Documentation != null)
+                       Lexer.doc_state = XmlCommentState.Allowed;
+         }
+         opt_struct_member_declarations CLOSE_BRACE
+       ;
+
+opt_struct_member_declarations
+       : /* empty */
+       | struct_member_declarations
+       ;
+
+struct_member_declarations
+       : struct_member_declaration
+       | struct_member_declarations struct_member_declaration
+       ;
+
+struct_member_declaration
+       : constant_declaration
+       | field_declaration
+       | method_declaration
+       | property_declaration
+       | event_declaration
+       | indexer_declaration
+       | operator_declaration
+       | constructor_declaration
+       | type_declaration
+
+       /*
+        * This is only included so we can flag error 575: 
+        * destructors only allowed on class types
+        */
+       | destructor_declaration 
+       ;
+
+constant_declaration
+       : opt_attributes 
+         opt_modifiers
+         CONST
+         type
+         constant_declarators
+         SEMICOLON
+         {
+               int modflags = (int) $2;
+               foreach (VariableDeclaration constant in (ArrayList) $5){
+                       Location l = constant.Location;
+                       if ((modflags & Modifiers.STATIC) != 0) {
+                               Report.Error (504, l, "The constant `{0}' cannot be marked static", current_container.GetSignatureForError () + '.' + (string) constant.identifier);
+                               continue;
+                       }
+
+                       Const c = new Const (
+                               current_class, (Expression) $4, (string) constant.identifier, 
+                               (Expression) constant.expression_or_array_initializer, modflags, 
+                               (Attributes) $1, l);
+
+                       if (RootContext.Documentation != null) {
+                               c.DocComment = Lexer.consume_doc_comment ();
+                               Lexer.doc_state = XmlCommentState.Allowed;
+                       }
+                       current_container.AddConstant (c);
+               }
+         }
+       ;
+
+constant_declarators
+       : constant_declarator 
+         {
+               ArrayList constants = new ArrayList (4);
+               if ($1 != null)
+                       constants.Add ($1);
+               $$ = constants;
+         }
+       | constant_declarators COMMA constant_declarator
+         {
+               if ($3 != null) {
+                       ArrayList constants = (ArrayList) $1;
+                       constants.Add ($3);
+               }
+         }
+       ;
+
+constant_declarator
+       : IDENTIFIER ASSIGN constant_expression
+         {
+               $$ = new VariableDeclaration ((LocatedToken) $1, $3);
+         }
+       | IDENTIFIER
+         {
+               // A const field requires a value to be provided
+               Report.Error (145, ((LocatedToken) $1).Location, "A const field requires a value to be provided");
+               $$ = null;
+         }
+       ;
+
+field_declaration
+       : opt_attributes
+         opt_modifiers
+         type 
+         variable_declarators
+         SEMICOLON
+         { 
+               Expression type = (Expression) $3;
+               int mod = (int) $2;
+
+               current_array_type = null;
+
+               foreach (VariableDeclaration var in (ArrayList) $4){
+                       Field field = new Field (current_class, type, mod, var.identifier, 
+                                                (Attributes) $1, var.Location);
+
+                       field.Initializer = var.expression_or_array_initializer;
+
+                       if (RootContext.Documentation != null) {
+                               field.DocComment = Lexer.consume_doc_comment ();
+                               Lexer.doc_state = XmlCommentState.Allowed;
+                       }
+                       current_container.AddField (field);
+                       $$ = field; // FIXME: might be better if it points to the top item
+               }
+         }
+       | opt_attributes
+         opt_modifiers
+         FIXED
+         type 
+         fixed_variable_declarators
+         SEMICOLON
+         { 
+                       Expression type = (Expression) $4;
+                       int mod = (int) $2;
+
+                       current_array_type = null;
+
+                       foreach (VariableDeclaration var in (ArrayList) $5) {
+                               FixedField field = new FixedField (current_class, type, mod, var.identifier,
+                                       (Expression)var.expression_or_array_initializer, (Attributes) $1, var.Location);
+
+                               if (RootContext.Documentation != null) {
+                                       field.DocComment = Lexer.consume_doc_comment ();
+                                       Lexer.doc_state = XmlCommentState.Allowed;
+                               }
+                               current_container.AddField (field);
+                               $$ = field; // FIXME: might be better if it points to the top item
+                       }
+         }
+       | opt_attributes
+         opt_modifiers
+         VOID  
+         variable_declarators
+         SEMICOLON {
+               current_array_type = null;
+               Report.Error (670, (Location) $3, "Fields cannot have void type");
+         }
+       ;
+
+fixed_variable_declarators
+       : fixed_variable_declarator
+         {
+               ArrayList decl = new ArrayList (2);
+               decl.Add ($1);
+               $$ = decl;
+         }
+       | fixed_variable_declarators COMMA fixed_variable_declarator
+         {
+               ArrayList decls = (ArrayList) $1;
+               decls.Add ($3);
+               $$ = $1;
+         }
+       ;
+
+fixed_variable_declarator
+       : IDENTIFIER OPEN_BRACKET expression CLOSE_BRACKET
+         {
+               $$ = new VariableDeclaration ((LocatedToken) $1, $3);
+         }
+       | IDENTIFIER OPEN_BRACKET CLOSE_BRACKET
+         {
+               Report.Error (443, lexer.Location, "Value or constant expected");
+               $$ = new VariableDeclaration ((LocatedToken) $1, null);
+         }
+       ;
+
+variable_declarators
+       : variable_declarator 
+         {
+               ArrayList decl = new ArrayList (4);
+               if ($1 != null)
+                       decl.Add ($1);
+               $$ = decl;
+         }
+       | variable_declarators COMMA variable_declarator
+         {
+               ArrayList decls = (ArrayList) $1;
+               decls.Add ($3);
+               $$ = $1;
+         }
+       ;
+
+variable_declarator
+       : IDENTIFIER ASSIGN variable_initializer
+         {
+               $$ = new VariableDeclaration ((LocatedToken) $1, $3);
+         }
+       | IDENTIFIER
+         {
+               $$ = new VariableDeclaration ((LocatedToken) $1, null);
+         }
+       | IDENTIFIER OPEN_BRACKET opt_expression CLOSE_BRACKET
+         {
+               Report.Error (650, ((LocatedToken) $1).Location, "Syntax error, bad array declarator. To declare a managed array the rank specifier precedes the variable's identifier. " +
+                       "To declare a fixed size buffer field, use the fixed keyword before the field type");
+               $$ = null;
+         }
+       ;
+
+variable_initializer
+       : expression
+         {
+               $$ = $1;
+         }
+       | array_initializer
+         {
+               $$ = $1;
+         }
+       | STACKALLOC type OPEN_BRACKET expression CLOSE_BRACKET
+         {
+               $$ = new StackAlloc ((Expression) $2, (Expression) $4, (Location) $1);
+         }
+       | ARGLIST
+         {
+               $$ = new ArglistAccess ((Location) $1);
+         }
+       | STACKALLOC type
+         {
+               Report.Error (1575, (Location) $1, "A stackalloc expression requires [] after type");
+                $$ = null;
+         }
+       ;
+
+method_declaration
+       : method_header {
+               anonymous_host = (IAnonymousHost) $1;
+               if (RootContext.Documentation != null)
+                       Lexer.doc_state = XmlCommentState.NotAllowed;
+         }
+         method_body
+         {
+               Method method = (Method) $1;
+               method.Block = (ToplevelBlock) $3;
+               current_container.AddMethod (method);
+
+               anonymous_host = null;
+               current_local_parameters = null;
+
+               if (RootContext.Documentation != null)
+                       Lexer.doc_state = XmlCommentState.Allowed;
+         }
+       ;
+
+opt_error_modifier
+       : /* empty */
+       | modifiers 
+         {
+               int m = (int) $1;
+               int i = 1;
+
+               while (m != 0){
+                       if ((i & m) != 0){
+                               Report.Error (1585, lexer.Location,
+                                       "Member modifier `{0}' must precede the member type and name",
+                                       Modifiers.Name (i));
+                       }
+                       m &= ~i;
+                       i = i << 1;
+               }
+         }
+       ;
+
+method_header
+       : opt_attributes
+         opt_modifiers
+         type namespace_or_type_name
+         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
+         {
+               MemberName name = (MemberName) $4;
+
+               Method method = new Method (current_class, null, (Expression) $3, (int) $2,
+                                           false, name,  (Parameters) $6, (Attributes) $1);
+
+               anonymous_host = method;
+               current_local_parameters = (Parameters) $6;
+
+               if (RootContext.Documentation != null)
+                       method.DocComment = Lexer.consume_doc_comment ();
+
+               $$ = method;
+         }
+       | opt_attributes
+         opt_modifiers
+         VOID namespace_or_type_name
+         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
+         {
+               MemberName name = (MemberName) $4;
+
+               Method method = new Method (current_class, null, TypeManager.system_void_expr,
+                                           (int) $2, false, name, (Parameters) $6,
+                                           (Attributes) $1);
+
+               anonymous_host = method;
+               current_local_parameters = (Parameters) $6;
+
+               if (RootContext.Documentation != null)
+                       method.DocComment = Lexer.consume_doc_comment ();
+
+               $$ = method;
+         }
+       | opt_attributes
+         opt_modifiers
+         type 
+         modifiers namespace_or_type_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
+         {
+               MemberName name = (MemberName) $5;
+               Report.Error (1585, name.Location, 
+                       "Member modifier `{0}' must precede the member type and name", Modifiers.Name ((int) $4));
+
+               Method method = new Method (current_class, null, TypeManager.system_void_expr,
+                                           0, false, name, (Parameters) $7, (Attributes) $1);
+
+               current_local_parameters = (Parameters) $7;
+
+               if (RootContext.Documentation != null)
+                       method.DocComment = Lexer.consume_doc_comment ();
+
+               $$ = null;
+         }
+       ;
+
+method_body
+       : block
+       | SEMICOLON             { $$ = null; }
+       ;
+
+opt_formal_parameter_list
+       : /* empty */                   { $$ = Parameters.EmptyReadOnlyParameters; }
+       | formal_parameter_list
+       ;
+
+formal_parameter_list
+       : fixed_parameters              
+         { 
+               ArrayList pars_list = (ArrayList) $1;
+
+               Parameter [] pars = new Parameter [pars_list.Count];
+               pars_list.CopyTo (pars);
+
+               $$ = new Parameters (pars); 
+         } 
+       | fixed_parameters COMMA parameter_array
+         {
+               ArrayList pars_list = (ArrayList) $1;
+               pars_list.Add ($3);
+
+               Parameter [] pars = new Parameter [pars_list.Count];
+               pars_list.CopyTo (pars);
+
+               $$ = new Parameters (pars); 
+         }
+       | fixed_parameters COMMA ARGLIST
+         {
+               ArrayList pars_list = (ArrayList) $1;
+               //pars_list.Add (new ArglistParameter (GetLocation ($3)));
+
+               Parameter [] pars = new Parameter [pars_list.Count];
+               pars_list.CopyTo (pars);
+
+               $$ = new Parameters (pars, true);
+         }
+       | parameter_array COMMA error
+         {
+               if ($1 != null)
+                       Report.Error (231, ((Parameter) $1).Location, "A params parameter must be the last parameter in a formal parameter list");
+               $$ = null;
+         }
+       | fixed_parameters COMMA parameter_array COMMA error
+         {
+               if ($3 != null)
+                       Report.Error (231, ((Parameter) $3).Location, "A params parameter must be the last parameter in a formal parameter list");
+               $$ = null;
+         }
+       | ARGLIST COMMA error
+         {
+               Report.Error (257, (Location) $1, "An __arglist parameter must be the last parameter in a formal parameter list");
+               $$ = null;
+         }
+       | fixed_parameters COMMA ARGLIST COMMA error 
+         {
+               Report.Error (257, (Location) $3, "An __arglist parameter must be the last parameter in a formal parameter list");
+               $$ = null;
+         }
+       | parameter_array 
+         {
+               $$ = new Parameters (new Parameter[] { (Parameter) $1 } );
+         }
+       | ARGLIST
+         {
+               $$ = new Parameters (new Parameter[0], true);
+         }
+       ;
+
+fixed_parameters
+       : fixed_parameter       
+         {
+               ArrayList pars = new ArrayList (4);
+
+               pars.Add ($1);
+               $$ = pars;
+         }
+       | fixed_parameters COMMA fixed_parameter
+         {
+               ArrayList pars = (ArrayList) $1;
+
+               pars.Add ($3);
+               $$ = $1;
+         }
+       ;
+
+fixed_parameter
+       : opt_attributes
+         opt_parameter_modifier
+         type
+         IDENTIFIER
+         {
+               LocatedToken lt = (LocatedToken) $4;
+               $$ = new Parameter ((Expression) $3, lt.Value, (Parameter.Modifier) $2, (Attributes) $1, lt.Location);
+         }
+       | opt_attributes
+         opt_parameter_modifier
+         type
+         IDENTIFIER OPEN_BRACKET CLOSE_BRACKET
+         {
+               LocatedToken lt = (LocatedToken) $4;
+               Report.Error (1552, lt.Location, "Array type specifier, [], must appear before parameter name");
+               $$ = null;
+         }
+       | opt_attributes
+         opt_parameter_modifier
+         type
+         {
+               Report.Error (1001, GetLocation ($3), "Identifier expected");
+               $$ = null;
+         }
+       | opt_attributes
+         opt_parameter_modifier
+         type
+         error {
+               CheckIdentifierToken (yyToken, GetLocation ($4));
+               $$ = null;
+         }
+       | opt_attributes
+         opt_parameter_modifier
+         type
+         IDENTIFIER
+         ASSIGN
+         constant_expression
+          {
+               LocatedToken lt = (LocatedToken) $4;
+               Report.Error (241, lt.Location, "Default parameter specifiers are not permitted");
+                $$ = null;
+          }
+       ;
+
+opt_parameter_modifier
+       : /* empty */           { $$ = Parameter.Modifier.NONE; }
+       | parameter_modifier
+       ;
+
+parameter_modifier
+       : REF                   { $$ = Parameter.Modifier.REF; }
+       | OUT                   { $$ = Parameter.Modifier.OUT; }
+       ;
+
+parameter_array
+       : opt_attributes PARAMS type IDENTIFIER
+         { 
+               LocatedToken lt = (LocatedToken) $4;
+               $$ = new ParamsParameter ((Expression) $3, lt.Value, (Attributes) $1, lt.Location);
+               note ("type must be a single-dimension array type"); 
+         }
+       | opt_attributes PARAMS parameter_modifier type IDENTIFIER 
+         {
+               Report.Error (1611, (Location) $2, "The params parameter cannot be declared as ref or out");
+                $$ = null;
+         }
+       | opt_attributes PARAMS type error {
+               CheckIdentifierToken (yyToken, GetLocation ($4));
+               $$ = null;
+         }
+       ;
+
+property_declaration
+       : opt_attributes
+         opt_modifiers
+         type
+         namespace_or_type_name
+         {
+               if (RootContext.Documentation != null)
+                       tmpComment = Lexer.consume_doc_comment ();
+         }
+         OPEN_BRACE 
+         {
+               implicit_value_parameter_type = (Expression) $3;
+
+               lexer.PropertyParsing = true;
+         }
+         accessor_declarations 
+         {
+               lexer.PropertyParsing = false;
+               has_get = has_set = false;
+         }
+         CLOSE_BRACE
+         { 
+               if ($8 == null)
+                       break;
+
+               Property prop;
+               Pair pair = (Pair) $8;
+               Accessor get_block = (Accessor) pair.First;
+               Accessor set_block = (Accessor) pair.Second;
+
+               MemberName name = (MemberName) $4;
+
+               prop = new Property (current_class, (Expression) $3, (int) $2,
+                       false, name, (Attributes) $1, get_block, set_block);
+               
+               current_container.AddProperty (prop);
+               implicit_value_parameter_type = null;
+
+               if (RootContext.Documentation != null)
+                       prop.DocComment = ConsumeStoredComment ();
+
+         }
+       ;
+
+accessor_declarations
+       : get_accessor_declaration
+        {
+               $$ = new Pair ($1, null);
+        }
+       | get_accessor_declaration accessor_declarations
+        { 
+               Pair pair = (Pair) $2;
+               pair.First = $1;
+               $$ = pair;
+        }
+       | set_accessor_declaration
+        {
+               $$ = new Pair (null, $1);
+        }
+       | set_accessor_declaration accessor_declarations
+        { 
+               Pair pair = (Pair) $2;
+               pair.Second = $1;
+               $$ = pair;
+        }
+       | error
+         {
+               Report.Error (1014, GetLocation ($1), "A get or set accessor expected");
+               $$ = null;
+         }
+       ;
+
+get_accessor_declaration
+       : opt_attributes opt_modifiers GET
+         {
+               // If this is not the case, then current_local_parameters has already
+               // been set in indexer_declaration
+               if (parsing_indexer == false)
+                       current_local_parameters = null;
+               else 
+                       current_local_parameters = indexer_parameters;
+               lexer.PropertyParsing = false;
+
+               anonymous_host = SimpleAnonymousHost.GetSimple ();
+         }
+          accessor_body
+         {
+               if (has_get) {
+                       Report.Error (1007, (Location) $3, "Property accessor already defined");
+                       break;
+               }
+               Accessor accessor = new Accessor ((ToplevelBlock) $5, (int) $2, (Attributes) $1, (Location) $3);
+               has_get = true;
+               current_local_parameters = null;
+               lexer.PropertyParsing = true;
+
+               SimpleAnonymousHost.Simple.Propagate (accessor);
+               anonymous_host = null;
+
+               if (RootContext.Documentation != null)
+                       if (Lexer.doc_state == XmlCommentState.Error)
+                               Lexer.doc_state = XmlCommentState.NotAllowed;
+
+               $$ = accessor;
+         }
+       ;
+
+set_accessor_declaration
+       : opt_attributes opt_modifiers SET 
+         {
+               Parameter [] args;
+               Parameter implicit_value_parameter = new Parameter (
+                       implicit_value_parameter_type, "value", 
+                       Parameter.Modifier.NONE, null, (Location) $3);
+
+               if (parsing_indexer == false) {
+                       args  = new Parameter [1];
+                       args [0] = implicit_value_parameter;
+                       current_local_parameters = new Parameters (args);
+               } else {
+                       Parameter [] fpars = indexer_parameters.FixedParameters;
+
+                       if (fpars != null){
+                               int count = fpars.Length;
+
+                               args = new Parameter [count + 1];
+                               fpars.CopyTo (args, 0);
+                               args [count] = implicit_value_parameter;
+                       } else 
+                               args = null;
+                       current_local_parameters = new Parameters (
+                               args);
+               }
+               
+               lexer.PropertyParsing = false;
+
+               anonymous_host = SimpleAnonymousHost.GetSimple ();
+         }
+         accessor_body
+         {
+               if (has_set) {
+                       Report.Error (1007, ((LocatedToken) $3).Location, "Property accessor already defined");
+                       break;
+               }
+               Accessor accessor = new Accessor ((ToplevelBlock) $5, (int) $2, (Attributes) $1, (Location) $3);
+               has_set = true;
+               current_local_parameters = null;
+               lexer.PropertyParsing = true;
+
+               SimpleAnonymousHost.Simple.Propagate (accessor);
+               anonymous_host = null;
+
+               if (RootContext.Documentation != null
+                       && Lexer.doc_state == XmlCommentState.Error)
+                       Lexer.doc_state = XmlCommentState.NotAllowed;
+
+               $$ = accessor;
+         }
+       ;
+
+accessor_body
+       : block 
+       | SEMICOLON             { $$ = null; }
+       ;
+
+interface_declaration
+       : opt_attributes
+         opt_modifiers
+         opt_partial
+         INTERFACE member_name
+         {
+               MemberName name = MakeName ((MemberName) $5);
+
+               push_current_class (new Interface (
+                       current_namespace, current_class, name, (int) $2,
+                       (Attributes) $1), true, $3);
+         }
+         opt_class_base
+         {
+               current_container.AddBasesForPart (current_class, (ArrayList) $7);
+
+               if (RootContext.Documentation != null) {
+                       current_container.DocComment = Lexer.consume_doc_comment ();
+                       Lexer.doc_state = XmlCommentState.Allowed;
+               }
+         }
+         interface_body 
+         {
+               if (RootContext.Documentation != null)
+                       Lexer.doc_state = XmlCommentState.Allowed;
+         }
+         opt_semicolon 
+         {
+               $$ = pop_current_class ();
+         }
+       | opt_attributes opt_modifiers opt_partial INTERFACE error {
+               CheckIdentifierToken (yyToken, GetLocation ($5));
+         }
+       ;
+
+interface_body
+       : OPEN_BRACE
+         opt_interface_member_declarations
+         CLOSE_BRACE
+       ;
+
+opt_interface_member_declarations
+       : /* empty */
+       | interface_member_declarations
+       ;
+
+interface_member_declarations
+       : interface_member_declaration
+       | interface_member_declarations interface_member_declaration
+       ;
+
+interface_member_declaration
+       : interface_method_declaration          
+         { 
+               if ($1 == null)
+                       break;
+
+               Method m = (Method) $1;
+
+               if (m.IsExplicitImpl)
+                       Report.Error (541, m.Location, "`{0}': explicit interface declaration can only be declared in a class or struct",
+                               m.GetSignatureForError ());
+
+               current_container.AddMethod (m);
+
+               if (RootContext.Documentation != null)
+                       Lexer.doc_state = XmlCommentState.Allowed;
+         }
+       | interface_property_declaration        
+         { 
+               if ($1 == null)
+                       break;
+
+               Property p = (Property) $1;
+
+               if (p.IsExplicitImpl)
+                       Report.Error (541, p.Location, "`{0}': explicit interface declaration can only be declared in a class or struct",
+                               p.GetSignatureForError ());
+
+               current_container.AddProperty (p);
+
+               if (RootContext.Documentation != null)
+                       Lexer.doc_state = XmlCommentState.Allowed;
+       }
+       | interface_event_declaration 
+          { 
+               if ($1 != null){
+                       Event e = (Event) $1;
+
+                       if (e.IsExplicitImpl)
+                       Report.Error (541, e.Location, "`{0}': explicit interface declaration can only be declared in a class or struct",
+                               e.GetSignatureForError ());
+                       
+                       current_container.AddEvent (e);
+               }
+
+               if (RootContext.Documentation != null)
+                       Lexer.doc_state = XmlCommentState.Allowed;
+         }
+       | interface_indexer_declaration
+         { 
+               if ($1 == null)
+                       break;
+
+               Indexer i = (Indexer) $1;
+
+               if (i.IsExplicitImpl)
+                       Report.Error (541, i.Location, "`{0}': explicit interface declaration can only be declared in a class or struct",
+                               i.GetSignatureForError ());
+
+               current_container.AddIndexer (i);
+
+               if (RootContext.Documentation != null)
+                       Lexer.doc_state = XmlCommentState.Allowed;
+         }
+       | delegate_declaration
+         {
+               if ($1 != null) {
+                       Report.Error (524, GetLocation ($1), "`{0}': Interfaces cannot declare classes, structs, interfaces, delegates, enumerations or constants",
+                               ((MemberCore)$1).GetSignatureForError ());
+               }
+         }
+       | class_declaration
+         {
+               if ($1 != null) {
+                       Report.Error (524, GetLocation ($1), "`{0}': Interfaces cannot declare classes, structs, interfaces, delegates, enumerations or constants",
+                               ((MemberCore)$1).GetSignatureForError ());
+               }
+         }
+       | struct_declaration
+         {
+               if ($1 != null) {
+                       Report.Error (524, GetLocation ($1), "`{0}': Interfaces cannot declare classes, structs, interfaces, delegates, enumerations or constants",
+                               ((MemberCore)$1).GetSignatureForError ());
+               }
+         }
+       | enum_declaration 
+         {
+               if ($1 != null) {
+                       Report.Error (524, GetLocation ($1), "`{0}': Interfaces cannot declare classes, structs, interfaces, delegates, enumerations or constants",
+                               ((MemberCore)$1).GetSignatureForError ());
+               }
+         }
+       | interface_declaration 
+         {
+               if ($1 != null) {
+                       Report.Error (524, GetLocation ($1), "`{0}': Interfaces cannot declare classes, structs, interfaces, delegates, enumerations or constants",
+                               ((MemberCore)$1).GetSignatureForError ());
+               }
+         } 
+       | constant_declaration
+         {
+               Report.Error (525, GetLocation ($1), "Interfaces cannot contain fields or constants");
+         }
+       ;
+
+opt_new
+       : opt_modifiers 
+         {
+               int val = (int) $1;
+               val = Modifiers.Check (Modifiers.NEW | Modifiers.UNSAFE, val, 0, GetLocation ($1));
+               $$ = val;
+         }
+       ;
+
+interface_method_declaration
+       : opt_attributes opt_new type namespace_or_type_name
+         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
+         SEMICOLON
+         {
+               $$ = new Method (current_class, null, (Expression) $3, (int) $2, true,
+                                (MemberName) $4, (Parameters) $6, (Attributes) $1);
+               if (RootContext.Documentation != null)
+                       ((Method) $$).DocComment = Lexer.consume_doc_comment ();
+         }
+       | opt_attributes opt_new type namespace_or_type_name
+         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
+         OPEN_BRACE opt_statement_list CLOSE_BRACE
+         {
+               $$ = new Method (current_class, null, (Expression) $3, (int) $2, true,
+                                (MemberName) $4, (Parameters) $6, (Attributes) $1);
+
+               Report.Error (531, lexer.Location, "`{0}': interface members cannot have a definition",
+                       ((Method)$$).GetSignatureForError ());
+         }
+       ;
+
+interface_property_declaration
+       : opt_attributes
+         opt_new
+         type IDENTIFIER 
+         OPEN_BRACE 
+         { lexer.PropertyParsing = true; }
+         accessor_declarations 
+         {
+               has_get = has_set = false; 
+               lexer.PropertyParsing = false;
+         }
+         CLOSE_BRACE
+         {
+               LocatedToken lt = (LocatedToken) $4;
+               MemberName name = new MemberName (lt.Value, lt.Location);
+
+               if ($3 == TypeManager.system_void_expr) {
+                       Report.Error (547, lt.Location, "`{0}': property or indexer cannot have void type", lt.Value);
+                       break;
+               }
+
+               Property p = null;
+               if ($7 == null) {
+                       p = new Property (current_class, (Expression) $3, (int) $2, true,
+                                  name, (Attributes) $1,
+                                  null, null);
+
+                       Report.Error (548, p.Location, "`{0}': property or indexer must have at least one accessor", p.GetSignatureForError ());
+                       break;
+               }
+
+               Pair pair = (Pair) $7;
+               p = new Property (current_class, (Expression) $3, (int) $2, true,
+                                  name, (Attributes) $1,
+                                  (Accessor)pair.First, (Accessor)pair.Second);
+
+               if (pair.First != null && ((Accessor)(pair.First)).Block != null) {
+                       Report.Error (531, p.Location, "`{0}.get': interface members cannot have a definition", p.GetSignatureForError ());
+                       $$ = null;
+                       break;
+               }
+
+               if (pair.Second != null && ((Accessor)(pair.Second)).Block != null) {
+                       Report.Error (531, p.Location, "`{0}.set': interface members cannot have a definition", p.GetSignatureForError ());
+                       $$ = null;
+                       break;
+               }
+
+               if (RootContext.Documentation != null)
+                       p.DocComment = Lexer.consume_doc_comment ();
+
+               $$ = p;
+         }
+       | opt_attributes
+         opt_new
+         type error {
+               CheckIdentifierToken (yyToken, GetLocation ($4));
+               $$ = null;
+         }
+       ;
+
+
+interface_event_declaration
+       : opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON
+         {
+               LocatedToken lt = (LocatedToken) $5;
+               $$ = new EventField (current_class, (Expression) $4, (int) $2, true,
+                                    new MemberName (lt.Value, lt.Location),
+                                    (Attributes) $1);
+               if (RootContext.Documentation != null)
+                       ((EventField) $$).DocComment = Lexer.consume_doc_comment ();
+         }
+       | opt_attributes opt_new EVENT type error {
+               CheckIdentifierToken (yyToken, GetLocation ($5));
+               $$ = null;
+         }
+       | opt_attributes opt_new EVENT type IDENTIFIER ASSIGN  {
+               LocatedToken lt = (LocatedToken) $5;
+               Report.Error (68, lt.Location, "`{0}.{1}': event in interface cannot have initializer", current_container.Name, lt.Value);
+               $$ = null;
+         }
+       | opt_attributes opt_new EVENT type IDENTIFIER OPEN_BRACE
+         {
+               lexer.EventParsing = true;
+         }
+         event_accessor_declarations
+         {
+               lexer.EventParsing = false;
+         }
+         CLOSE_BRACE {
+               Report.Error (69, (Location) $3, "Event in interface cannot have add or remove accessors");
+               $$ = null;
+         }
+       ;
+
+interface_indexer_declaration 
+       : opt_attributes opt_new type THIS 
+         OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
+         OPEN_BRACE 
+         { lexer.PropertyParsing = true; }
+         accessor_declarations 
+         { 
+               has_get = has_set = false;
+               lexer.PropertyParsing = false;
+         }
+         CLOSE_BRACE
+         {
+               Indexer i = null;
+               if ($10 == null) {
+                       i = new Indexer (current_class, (Expression) $3,
+                                 new MemberName (TypeContainer.DefaultIndexerName, (Location) $4),
+                                 (int) $2, true, (Parameters) $6, (Attributes) $1,
+                                 null, null);
+
+                       Report.Error (548, i.Location, "`{0}': property or indexer must have at least one accessor", i.GetSignatureForError ());
+                       break;
+               }
+
+               Pair pair = (Pair) $10;
+               i = new Indexer (current_class, (Expression) $3,
+                                 new MemberName (TypeContainer.DefaultIndexerName, (Location) $4),
+                                 (int) $2, true, (Parameters) $6, (Attributes) $1,
+                                  (Accessor)pair.First, (Accessor)pair.Second);
+
+               if (pair.First != null && ((Accessor)(pair.First)).Block != null) {
+                       Report.Error (531, i.Location, "`{0}.get': interface members cannot have a definition", i.GetSignatureForError ());
+                       $$ = null;
+                       break;
+               }
+
+               if (pair.Second != null && ((Accessor)(pair.Second)).Block != null) {
+                       Report.Error (531, i.Location, "`{0}.set': interface members cannot have a definition", i.GetSignatureForError ());
+                       $$ = null;
+                       break;
+               }
+
+               if (RootContext.Documentation != null)
+                       i.DocComment = ConsumeStoredComment ();
+
+               $$ = i;
+         }
+       ;
+
+operator_declaration
+       : opt_attributes opt_modifiers operator_declarator 
+         {
+               anonymous_host = SimpleAnonymousHost.GetSimple ();
+         }
+         operator_body
+         {
+               if ($3 == null)
+                       break;
+
+               OperatorDeclaration decl = (OperatorDeclaration) $3;
+               
+               Parameter [] param_list = new Parameter [decl.arg2type != null ? 2 : 1];
+
+               param_list[0] = new Parameter (decl.arg1type, decl.arg1name, Parameter.Modifier.NONE, null, decl.location);
+               if (decl.arg2type != null)
+                       param_list[1] = new Parameter (decl.arg2type, decl.arg2name, Parameter.Modifier.NONE, null, decl.location);
+
+               Operator op = new Operator (
+                       current_class, decl.optype, decl.ret_type, (int) $2, 
+                       new Parameters (param_list),
+                       (ToplevelBlock) $5, (Attributes) $1, decl.location);
+
+               if (RootContext.Documentation != null) {
+                       op.DocComment = tmpComment;
+                       Lexer.doc_state = XmlCommentState.Allowed;
+               }
+
+               SimpleAnonymousHost.Simple.Propagate (op);
+               anonymous_host = null;
+
+               // Note again, checking is done in semantic analysis
+               current_container.AddOperator (op);
+
+               current_local_parameters = null;
+         }
+       ;
+
+operator_body 
+       : block
+       | SEMICOLON { $$ = null; }
+       ; 
+operator_declarator
+       : type OPERATOR overloadable_operator 
+         OPEN_PARENS type IDENTIFIER CLOSE_PARENS
+         {
+               LocatedToken lt = (LocatedToken) $6;
+               Operator.OpType op = (Operator.OpType) $3;
+               CheckUnaryOperator (op, lt.Location);
+
+               if (op == Operator.OpType.Addition)
+                       op = Operator.OpType.UnaryPlus;
+
+               if (op == Operator.OpType.Subtraction)
+                       op = Operator.OpType.UnaryNegation;
+
+               Parameter [] pars = new Parameter [1];
+               Expression type = (Expression) $5;
+
+               pars [0] = new Parameter (type, lt.Value, Parameter.Modifier.NONE, null, lt.Location);
+
+               current_local_parameters = new Parameters (pars);
+
+               if (RootContext.Documentation != null) {
+                       tmpComment = Lexer.consume_doc_comment ();
+                       Lexer.doc_state = XmlCommentState.NotAllowed;
+               }
+
+               $$ = new OperatorDeclaration (op, (Expression) $1, type, lt.Value,
+                                             null, null, (Location) $2);
+         }
+       | type OPERATOR overloadable_operator
+         OPEN_PARENS 
+               type IDENTIFIER COMMA
+               type IDENTIFIER 
+         CLOSE_PARENS
+          {
+               LocatedToken ltParam1 = (LocatedToken) $6;
+               LocatedToken ltParam2 = (LocatedToken) $9;
+               CheckBinaryOperator ((Operator.OpType) $3, (Location) $2);
+
+               Parameter [] pars = new Parameter [2];
+
+               Expression typeL = (Expression) $5;
+               Expression typeR = (Expression) $8;
+
+              pars [0] = new Parameter (typeL, ltParam1.Value, Parameter.Modifier.NONE, null, ltParam1.Location);
+              pars [1] = new Parameter (typeR, ltParam2.Value, Parameter.Modifier.NONE, null, ltParam2.Location);
+
+              current_local_parameters = new Parameters (pars);
+
+               if (RootContext.Documentation != null) {
+                       tmpComment = Lexer.consume_doc_comment ();
+                       Lexer.doc_state = XmlCommentState.NotAllowed;
+               }
+              
+              $$ = new OperatorDeclaration ((Operator.OpType) $3, (Expression) $1, 
+                                            typeL, ltParam1.Value,
+                                            typeR, ltParam2.Value, (Location) $2);
+          }
+       | conversion_operator_declarator
+       | type OPERATOR overloadable_operator
+         OPEN_PARENS 
+               type IDENTIFIER COMMA
+               type IDENTIFIER COMMA
+               type IDENTIFIER
+         CLOSE_PARENS
+         {
+               Report.Error (1534, (Location) $2, "Overloaded binary operator `{0}' takes two parameters",
+                       Operator.GetName ((Operator.OpType) $3));
+               $$ = null;
+         }
+       | type OPERATOR overloadable_operator 
+         OPEN_PARENS CLOSE_PARENS
+         {
+               Report.Error (1535, (Location) $2, "Overloaded unary operator `{0}' takes one parameter",
+                       Operator.GetName ((Operator.OpType) $3));
+               $$ = null;
+         }
+       ;
+
+overloadable_operator
+// Unary operators:
+       : BANG   { $$ = Operator.OpType.LogicalNot; }
+        | TILDE  { $$ = Operator.OpType.OnesComplement; }  
+        | OP_INC { $$ = Operator.OpType.Increment; }
+        | OP_DEC { $$ = Operator.OpType.Decrement; }
+        | TRUE   { $$ = Operator.OpType.True; }
+        | FALSE  { $$ = Operator.OpType.False; }
+// Unary and binary:
+        | PLUS { $$ = Operator.OpType.Addition; }
+        | MINUS { $$ = Operator.OpType.Subtraction; }
+// Binary:
+        | STAR { $$ = Operator.OpType.Multiply; }
+        | DIV {  $$ = Operator.OpType.Division; }
+        | PERCENT { $$ = Operator.OpType.Modulus; }
+        | BITWISE_AND { $$ = Operator.OpType.BitwiseAnd; }
+        | BITWISE_OR { $$ = Operator.OpType.BitwiseOr; }
+        | CARRET { $$ = Operator.OpType.ExclusiveOr; }
+        | OP_SHIFT_LEFT { $$ = Operator.OpType.LeftShift; }
+        | OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; }
+        | OP_EQ { $$ = Operator.OpType.Equality; }
+        | OP_NE { $$ = Operator.OpType.Inequality; }
+        | OP_GT { $$ = Operator.OpType.GreaterThan; }
+        | OP_LT { $$ = Operator.OpType.LessThan; }
+        | OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; }
+        | OP_LE { $$ = Operator.OpType.LessThanOrEqual; }
+       ;
+
+conversion_operator_declarator
+       : IMPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
+         {
+               LocatedToken lt = (LocatedToken) $6;
+               Parameter [] pars = new Parameter [1];
+
+               pars [0] = new Parameter ((Expression) $5, lt.Value, Parameter.Modifier.NONE, null, lt.Location);
+
+               current_local_parameters = new Parameters (pars);  
+                 
+               if (RootContext.Documentation != null) {
+                       tmpComment = Lexer.consume_doc_comment ();
+                       Lexer.doc_state = XmlCommentState.NotAllowed;
+               }
+
+               $$ = new OperatorDeclaration (Operator.OpType.Implicit, (Expression) $3, (Expression) $5, lt.Value,
+                                             null, null, (Location) $2);
+         }
+       | EXPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
+         {
+               LocatedToken lt = (LocatedToken) $6;
+               Parameter [] pars = new Parameter [1];
+
+               pars [0] = new Parameter ((Expression) $5, lt.Value, Parameter.Modifier.NONE, null, lt.Location);
+
+               current_local_parameters = new Parameters (pars);  
+                 
+               if (RootContext.Documentation != null) {
+                       tmpComment = Lexer.consume_doc_comment ();
+                       Lexer.doc_state = XmlCommentState.NotAllowed;
+               }
+
+               $$ = new OperatorDeclaration (Operator.OpType.Explicit, (Expression) $3, (Expression) $5, lt.Value,
+                                             null, null, (Location) $2);
+         }
+       | IMPLICIT error 
+         {
+               syntax_error ((Location) $1, "'operator' expected");
+         }
+       | EXPLICIT error 
+         {
+               syntax_error ((Location) $1, "'operator' expected");
+         }
+       ;
+
+constructor_declaration
+       : opt_attributes
+         opt_modifiers
+         constructor_declarator
+         constructor_body
+         { 
+               Constructor c = (Constructor) $3;
+               c.Block = (ToplevelBlock) $4;
+               c.OptAttributes = (Attributes) $1;
+               c.ModFlags = (int) $2;
+       
+               if (RootContext.Documentation != null)
+                       c.DocComment = ConsumeStoredComment ();
+
+               if (c.Name == current_container.Basename){
+                       if ((c.ModFlags & Modifiers.STATIC) != 0){
+                               if ((c.ModFlags & Modifiers.Accessibility) != 0){
+                                       Report.Error (515, c.Location,
+                                               "`{0}': access modifiers are not allowed on static constructors",
+                                               c.GetSignatureForError ());
+                               }
+       
+                               c.ModFlags = Modifiers.Check (Constructor.AllowedModifiers, (int) $2, Modifiers.PRIVATE, c.Location);   
+       
+                               if (c.Initializer != null){
+                                       Report.Error (514, c.Location,
+                                               "`{0}': static constructor cannot have an explicit `this' or `base' constructor call",
+                                               c.GetSignatureForError ());
+                               }
+                       } else {
+                               c.ModFlags = Modifiers.Check (Constructor.AllowedModifiers, (int) $2, Modifiers.PRIVATE, c.Location);
+                       }
+               } else {
+                       // We let another layer check the validity of the constructor.
+                       //Console.WriteLine ("{0} and {1}", c.Name, current_container.Basename);
+               }
+
+               current_container.AddConstructor (c);
+
+               current_local_parameters = null;
+               if (RootContext.Documentation != null)
+                       Lexer.doc_state = XmlCommentState.Allowed;
+         }
+       ;
+
+constructor_declarator
+       : IDENTIFIER
+         {
+               if (RootContext.Documentation != null) {
+                       tmpComment = Lexer.consume_doc_comment ();
+                       Lexer.doc_state = XmlCommentState.Allowed;
+               }
+         }
+         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
+         {
+               current_local_parameters = (Parameters) $4;
+         }
+         opt_constructor_initializer
+         {
+               LocatedToken lt = (LocatedToken) $1;
+               $$ = new Constructor (current_class, lt.Value, 0, (Parameters) $4,
+                                     (ConstructorInitializer) $7, lt.Location);
+
+               anonymous_host = (IAnonymousHost) $$;
+         }
+       ;
+
+constructor_body
+       : block
+       | SEMICOLON             { $$ = null; }
+       ;
+
+opt_constructor_initializer
+       : /* empty */                   { $$ = null; }
+       | constructor_initializer
+       ;
+
+constructor_initializer
+       : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS
+         {
+               $$ = new ConstructorBaseInitializer ((ArrayList) $4, (Location) $2);
+         }
+       | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS
+         {
+               $$ = new ConstructorThisInitializer ((ArrayList) $4, (Location) $2);
+         }
+       | COLON error {
+               Report.Error (1018, (Location) $1, "Keyword this or base expected");
+               $$ = null;
+         }
+       ;
+
+opt_finalizer
+        : /* EMPTY */           { $$ = 0; }
+        | UNSAFE               { $$ = Modifiers.UNSAFE; }
+       | EXTERN                { $$ = Modifiers.EXTERN; }
+        ;
+        
+destructor_declaration
+       : opt_attributes opt_finalizer TILDE 
+         {
+               if (RootContext.Documentation != null) {
+                       tmpComment = Lexer.consume_doc_comment ();
+                       Lexer.doc_state = XmlCommentState.NotAllowed;
+               }
+         }
+         IDENTIFIER OPEN_PARENS CLOSE_PARENS block
+         {
+               LocatedToken lt = (LocatedToken) $5;
+               if (lt.Value != current_container.Basename){
+                       Report.Error (574, lt.Location, "Name of destructor must match name of class");
+               } else if (current_container.Kind != Kind.Class){
+                       Report.Error (575, lt.Location, "Only class types can contain destructor");
+               } else {
+                       Location l = lt.Location;
+
+                       int m = (int) $2;
+                       if (!RootContext.StdLib && current_container.Name == "System.Object")
+                               m |= Modifiers.PROTECTED | Modifiers.VIRTUAL;
+                       else
+                               m |= Modifiers.PROTECTED | Modifiers.OVERRIDE;
+                        
+                       Method d = new Destructor (
+                               current_class, TypeManager.system_void_expr, m, "Finalize", 
+                               Parameters.EmptyReadOnlyParameters, (Attributes) $1, l);
+                       if (RootContext.Documentation != null)
+                               d.DocComment = ConsumeStoredComment ();
+                 
+                       d.Block = (ToplevelBlock) $8;
+                       current_container.AddMethod (d);
+               }
+         }
+       ;
+
+event_declaration
+       : opt_attributes
+         opt_modifiers
+         EVENT type variable_declarators SEMICOLON
+         {
+               current_array_type = null;
+               foreach (VariableDeclaration var in (ArrayList) $5) {
+
+                       MemberName name = new MemberName (var.identifier,
+                               var.Location);
+
+                       EventField e = new EventField (
+                               current_class, (Expression) $4, (int) $2, false, name,
+                               (Attributes) $1);
+
+                       e.Initializer = var.expression_or_array_initializer;
+
+                       current_container.AddEvent (e);
+
+                       if (RootContext.Documentation != null) {
+                               e.DocComment = Lexer.consume_doc_comment ();
+                               Lexer.doc_state = XmlCommentState.Allowed;
+                       }
+               }
+         }
+       | opt_attributes
+         opt_modifiers
+         EVENT type namespace_or_type_name
+         OPEN_BRACE
+         {
+               implicit_value_parameter_type = (Expression) $4;  
+               lexer.EventParsing = true;
+         }
+         event_accessor_declarations
+         {
+               lexer.EventParsing = false;  
+         }
+         CLOSE_BRACE
+         {
+               MemberName name = (MemberName) $5;
+
+               if ($8 == null){
+                       Report.Error (65, (Location) $3, "`{0}.{1}': event property must have both add and remove accessors",
+                               current_container.Name, name.ToString ());
+                       $$ = null;
+               } else {
+                       Pair pair = (Pair) $8;
+                       if (pair.First == null || pair.Second == null)
+                               // CS0073 is already reported, so no CS0065 here.
+                               $$ = null;
+                       else {
+                               Event e = new EventProperty (
+                                       current_class, (Expression) $4, (int) $2, false, name,
+                                       (Attributes) $1, (Accessor) pair.First, (Accessor) pair.Second);
+                               if (RootContext.Documentation != null) {
+                                       e.DocComment = Lexer.consume_doc_comment ();
+                                       Lexer.doc_state = XmlCommentState.Allowed;
+                               }
+
+                               current_container.AddEvent (e);
+                               implicit_value_parameter_type = null;
+                       }
+               }
+         }
+       | opt_attributes opt_modifiers EVENT type namespace_or_type_name error {
+               MemberName mn = (MemberName) $5;
+
+               if (mn.Left != null)
+                       Report.Error (71, mn.Location, "An explicit interface implementation of an event must use property syntax");
+               else 
+                       Report.Error (71, mn.Location, "Event declaration should use property syntax");
+
+               if (RootContext.Documentation != null)
+                       Lexer.doc_state = XmlCommentState.Allowed;
+         }
+       ;
+
+event_accessor_declarations
+       : add_accessor_declaration remove_accessor_declaration
+         {
+               $$ = new Pair ($1, $2);
+         }
+       | remove_accessor_declaration add_accessor_declaration
+         {
+               $$ = new Pair ($2, $1);
+         }     
+       | add_accessor_declaration  { $$ = null; } 
+       | remove_accessor_declaration { $$ = null; } 
+       | error
+         { 
+               Report.Error (1055, GetLocation ($1), "An add or remove accessor expected");
+               $$ = null;
+         }
+       | { $$ = null; }
+       ;
+
+add_accessor_declaration
+       : opt_attributes ADD
+         {
+               Parameter [] args = new Parameter [1];
+               Parameter implicit_value_parameter = new Parameter (
+                       implicit_value_parameter_type, "value", 
+                       Parameter.Modifier.NONE, null, (Location) $2);
+
+               args [0] = implicit_value_parameter;
+               
+               current_local_parameters = new Parameters (args);  
+               lexer.EventParsing = false;
+         }
+          block
+         {
+               $$ = new Accessor ((ToplevelBlock) $4, 0, (Attributes) $1, (Location) $2);
+               lexer.EventParsing = true;
+         }
+       | opt_attributes ADD error {
+               Report.Error (73, (Location) $2, "An add or remove accessor must have a body");
+               $$ = null;
+         }
+       | opt_attributes modifiers ADD {
+               Report.Error (1609, (Location) $3, "Modifiers cannot be placed on event accessor declarations");
+               $$ = null;
+         }
+       ;
+
+remove_accessor_declaration
+       : opt_attributes REMOVE
+         {
+               Parameter [] args = new Parameter [1];
+               Parameter implicit_value_parameter = new Parameter (
+                       implicit_value_parameter_type, "value", 
+                       Parameter.Modifier.NONE, null, (Location) $2);
+
+               args [0] = implicit_value_parameter;
+               
+               current_local_parameters = new Parameters (args);  
+               lexer.EventParsing = false;
+         }
+          block
+         {
+               $$ = new Accessor ((ToplevelBlock) $4, 0, (Attributes) $1, (Location) $2);
+               lexer.EventParsing = true;
+         }
+       | opt_attributes REMOVE error {
+               Report.Error (73, (Location) $2, "An add or remove accessor must have a body");
+               $$ = null;
+         }
+       | opt_attributes modifiers REMOVE {
+               Report.Error (1609, (Location) $3, "Modifiers cannot be placed on event accessor declarations");
+               $$ = null;
+         }
+       ;
+
+indexer_declaration
+       : opt_attributes opt_modifiers indexer_declarator 
+         OPEN_BRACE
+         {
+               IndexerDeclaration decl = (IndexerDeclaration) $3;
+
+               implicit_value_parameter_type = decl.type;
+               
+               lexer.PropertyParsing = true;
+               parsing_indexer  = true;
+               
+               indexer_parameters = decl.param_list;
+               anonymous_host = SimpleAnonymousHost.GetSimple ();
+         }
+          accessor_declarations 
+         {
+                 lexer.PropertyParsing = false;
+                 has_get = has_set = false;
+                 parsing_indexer  = false;
+         }
+         CLOSE_BRACE
+         { 
+               if ($6 == null)
+                       break;
+
+               // The signature is computed from the signature of the indexer.  Look
+               // at section 3.6 on the spec
+               Indexer indexer;
+               IndexerDeclaration decl = (IndexerDeclaration) $3;
+               Location loc = decl.location;
+               Pair pair = (Pair) $6;
+               Accessor get_block = (Accessor) pair.First;
+               Accessor set_block = (Accessor) pair.Second;
+
+               MemberName name;
+               if (decl.interface_type != null)
+                       name = new MemberName (decl.interface_type, TypeContainer.DefaultIndexerName, loc);
+               else
+                       name = new MemberName (TypeContainer.DefaultIndexerName, loc);
+
+               indexer = new Indexer (current_class, decl.type, name,
+                                      (int) $2, false, decl.param_list, (Attributes) $1,
+                                      get_block, set_block);
+
+               if (RootContext.Documentation != null)
+                       indexer.DocComment = ConsumeStoredComment ();
+
+               current_container.AddIndexer (indexer);
+               
+               current_local_parameters = null;
+               implicit_value_parameter_type = null;
+               indexer_parameters = null;
+         }
+       ;
+
+indexer_declarator
+       : type THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
+         {
+               Parameters pars = (Parameters) $4;
+               if (pars.HasArglist) {
+                       // "__arglist is not valid in this context"
+                       Report.Error (1669, (Location) $2, "__arglist is not valid in this context");
+               } else if (pars.Empty){
+                       Report.Error (1551, (Location) $2, "Indexers must have at least one parameter");
+               }
+               if (RootContext.Documentation != null) {
+                       tmpComment = Lexer.consume_doc_comment ();
+                       Lexer.doc_state = XmlCommentState.Allowed;
+               }
+
+               $$ = new IndexerDeclaration ((Expression) $1, null, pars, (Location) $2);
+         }
+       | type namespace_or_type_name DOT THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
+         {
+               Parameters pars = (Parameters) $6;
+
+               if (pars.HasArglist) {
+                       // "__arglist is not valid in this context"
+                       Report.Error (1669, (Location) $4, "__arglist is not valid in this context");
+               } else if (pars.Empty){
+                       Report.Error (1551, (Location) $4, "Indexers must have at least one parameter");
+               }
+
+               MemberName name = (MemberName) $2;
+               $$ = new IndexerDeclaration ((Expression) $1, name, pars, (Location) $4);
+
+               if (RootContext.Documentation != null) {
+                       tmpComment = Lexer.consume_doc_comment ();
+                       Lexer.doc_state = XmlCommentState.Allowed;
+               }
+         }
+       ;
+
+enum_declaration
+       : opt_attributes
+         opt_modifiers
+         ENUM IDENTIFIER 
+         opt_enum_base {
+               if (RootContext.Documentation != null)
+                       enumTypeComment = Lexer.consume_doc_comment ();
+         }
+         enum_body
+         opt_semicolon
+         {
+               LocatedToken lt = (LocatedToken) $4;
+               Location enum_location = lt.Location;
+
+               MemberName name = MakeName (new MemberName (lt.Value, enum_location));
+               Enum e = new Enum (current_namespace, current_class, (Expression) $5, (int) $2,
+                                  name, (Attributes) $1);
+               
+               if (RootContext.Documentation != null)
+                       e.DocComment = enumTypeComment;
+
+
+               EnumMember em = null;
+               foreach (VariableDeclaration ev in (ArrayList) $7) {
+                       em = new EnumMember (e, em, (Expression) ev.expression_or_array_initializer,
+                               new MemberName (ev.identifier, ev.Location), ev.OptAttributes);
+
+//                     if (RootContext.Documentation != null)
+                               em.DocComment = ev.DocComment;
+
+                       e.AddEnumMember (em);
+               }
+
+               current_container.AddEnum (e);
+               $$ = e;
+
+         }
+       ;
+
+opt_enum_base
+       : /* empty */           { $$ = TypeManager.system_int32_expr; }
+       | COLON type            { $$ = $2;   }
+       ;
+
+enum_body
+       : OPEN_BRACE
+         {
+               if (RootContext.Documentation != null)
+                       Lexer.doc_state = XmlCommentState.Allowed;
+         }
+         opt_enum_member_declarations
+         {
+               // here will be evaluated after CLOSE_BLACE is consumed.
+               if (RootContext.Documentation != null)
+                       Lexer.doc_state = XmlCommentState.Allowed;
+         }
+         CLOSE_BRACE
+         {
+               $$ = $3;
+         }
+       ;
+
+opt_enum_member_declarations
+       : /* empty */                   { $$ = new ArrayList (4); }
+       | enum_member_declarations opt_comma { $$ = $1; }
+       ;
+
+enum_member_declarations
+       : enum_member_declaration 
+         {
+               ArrayList l = new ArrayList (4);
+
+               l.Add ($1);
+               $$ = l;
+         }
+       | enum_member_declarations COMMA enum_member_declaration
+         {
+               ArrayList l = (ArrayList) $1;
+
+               l.Add ($3);
+
+               $$ = l;
+         }
+       ;
+
+enum_member_declaration
+       : opt_attributes IDENTIFIER 
+         {
+               VariableDeclaration vd = new VariableDeclaration (
+                       (LocatedToken) $2, null, (Attributes) $1);
+
+               if (RootContext.Documentation != null) {
+                       vd.DocComment = Lexer.consume_doc_comment ();
+                       Lexer.doc_state = XmlCommentState.Allowed;
+               }
+
+               $$ = vd;
+         }
+       | opt_attributes IDENTIFIER
+         {
+               if (RootContext.Documentation != null) {
+                       tmpComment = Lexer.consume_doc_comment ();
+                       Lexer.doc_state = XmlCommentState.NotAllowed;
+               }
+         }
+          ASSIGN expression
+         { 
+               VariableDeclaration vd = new VariableDeclaration (
+                       (LocatedToken) $2, $5, (Attributes) $1);
+
+               if (RootContext.Documentation != null)
+                       vd.DocComment = ConsumeStoredComment ();
+
+               $$ = vd;
+         }
+       ;
+
+delegate_declaration
+       : opt_attributes
+         opt_modifiers
+         DELEGATE type member_name
+         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
+         SEMICOLON
+         {
+               MemberName name = MakeName ((MemberName) $5);
+               Parameters p = (Parameters) $7;
+               if (p.HasArglist) {
+                       // TODO: wrong location
+                       Report.Error (1669, name.Location, "__arglist is not valid in this context");
+               }
+
+               Delegate del = new Delegate (current_namespace, current_class, (Expression) $4,
+                                            (int) $2, name, p, (Attributes) $1);
+
+               if (RootContext.Documentation != null) {
+                       del.DocComment = Lexer.consume_doc_comment ();
+                       Lexer.doc_state = XmlCommentState.Allowed;
+               }
+
+               current_container.AddDelegate (del);
+               $$ = del;
+         }     
+       ;
+
+namespace_or_type_name
+       : member_name
+       | IDENTIFIER DOUBLE_COLON IDENTIFIER {
+               LocatedToken lt1 = (LocatedToken) $1;
+               LocatedToken lt2 = (LocatedToken) $3;
+               $$ = new MemberName (lt1.Value, lt2.Value, lt2.Location);
+         }
+       | namespace_or_type_name DOT IDENTIFIER {
+               LocatedToken lt = (LocatedToken) $3;
+               $$ = new MemberName ((MemberName) $1, lt.Value);
+         }
+       ;
+
+member_name
+       : IDENTIFIER {
+               LocatedToken lt = (LocatedToken) $1;
+               $$ = new MemberName (lt.Value, lt.Location);
+         }
+       ;
+
+/* 
+ * Before you think of adding a return_type, notice that we have been
+ * using two rules in the places where it matters (one rule using type
+ * and another identical one that uses VOID as the return type).  This
+ * gets rid of a shift/reduce couple
+ */
+type
+       : namespace_or_type_name
+         {
+               MemberName name = (MemberName) $1;
+               $$ = name.GetTypeExpression ();
+         }
+       | builtin_types
+       | array_type
+       | pointer_type    
+       ;
+
+
+pointer_type
+       : type STAR
+         {
+               //
+               // Note that here only unmanaged types are allowed but we
+               // can't perform checks during this phase - we do it during
+               // semantic analysis.
+               //
+               $$ = new ComposedCast ((Expression) $1, "*", Lexer.Location);
+         }
+       | VOID STAR
+         {
+               $$ = new ComposedCast (TypeManager.system_void_expr, "*", (Location) $1);
+         }
+       ;
+
+non_expression_type
+       : builtin_types 
+       | non_expression_type rank_specifier
+         {
+               Location loc = GetLocation ($1);
+               if (loc.IsNull)
+                       loc = lexer.Location;
+               $$ = new ComposedCast ((Expression) $1, (string) $2, loc);
+         }
+       | non_expression_type STAR
+         {
+               Location loc = GetLocation ($1);
+               if (loc.IsNull)
+                       loc = lexer.Location;
+               $$ = new ComposedCast ((Expression) $1, "*", loc);
+         }
+       | expression rank_specifiers 
+         {
+               $$ = new ComposedCast ((Expression) $1, (string) $2);
+         }
+       | expression STAR 
+         {
+               $$ = new ComposedCast ((Expression) $1, "*");
+         }
+       
+       //
+       // We need this because the parser will happily go and reduce IDENTIFIER STAR
+       // through this different path
+       //
+       | multiplicative_expression STAR 
+         {
+               $$ = new ComposedCast ((Expression) $1, "*");
+         }
+       ;
+
+type_list
+       : type
+         {
+               ArrayList types = new ArrayList (4);
+
+               types.Add ($1);
+               $$ = types;
+         }
+       | type_list COMMA type
+         {
+               ArrayList types = (ArrayList) $1;
+
+               types.Add ($3);
+               $$ = types;
+         }
+       ;
+
+/*
+ * replaces all the productions for isolating the various
+ * simple types, but we need this to reuse it easily in local_variable_type
+ */
+builtin_types
+       : OBJECT        { $$ = TypeManager.system_object_expr; }
+       | STRING        { $$ = TypeManager.system_string_expr; }
+       | BOOL          { $$ = TypeManager.system_boolean_expr; }
+       | DECIMAL       { $$ = TypeManager.system_decimal_expr; }
+       | FLOAT         { $$ = TypeManager.system_single_expr; }
+       | DOUBLE        { $$ = TypeManager.system_double_expr; }
+       | integral_type
+       ;
+
+integral_type
+       : SBYTE         { $$ = TypeManager.system_sbyte_expr; }
+       | BYTE          { $$ = TypeManager.system_byte_expr; }
+       | SHORT         { $$ = TypeManager.system_int16_expr; }
+       | USHORT        { $$ = TypeManager.system_uint16_expr; }
+       | INT           { $$ = TypeManager.system_int32_expr; }
+       | UINT          { $$ = TypeManager.system_uint32_expr; }
+       | LONG          { $$ = TypeManager.system_int64_expr; }
+       | ULONG         { $$ = TypeManager.system_uint64_expr; }
+       | CHAR          { $$ = TypeManager.system_char_expr; }
+       | VOID          { $$ = TypeManager.system_void_expr; }
+       ;
+
+array_type
+       : type rank_specifiers
+         {
+               $$ = current_array_type = new ComposedCast ((Expression) $1, (string) $2);
+         }
+       ;
+
+//
+// Expressions, section 7.5
+//
+primary_expression
+       : literal
+         {
+               // 7.5.1: Literals
+         }
+       | member_name
+         {
+               MemberName mn = (MemberName) $1;
+               $$ = mn.GetTypeExpression ();
+         }
+       | IDENTIFIER DOUBLE_COLON IDENTIFIER
+         {
+               LocatedToken lt1 = (LocatedToken) $1;
+               LocatedToken lt2 = (LocatedToken) $3;
+               $$ = new QualifiedAliasMember (lt1.Value, lt2.Value, lt2.Location);
+         }
+       | parenthesized_expression
+       | member_access
+       | invocation_expression
+       | element_access
+       | this_access
+       | base_access
+       | post_increment_expression
+       | post_decrement_expression
+       | new_expression
+       | typeof_expression
+       | sizeof_expression
+       | checked_expression
+       | unchecked_expression
+       | pointer_member_access
+       | anonymous_method_expression
+       ;
+
+literal
+       : boolean_literal
+       | integer_literal
+       | real_literal
+       | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value, lexer.Location); }
+       | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value, lexer.Location); } 
+       | NULL                  { $$ = new NullLiteral (lexer.Location); }
+       ;
+
+real_literal
+       : LITERAL_FLOAT         { $$ = new FloatLiteral ((float) lexer.Value, lexer.Location); }
+       | LITERAL_DOUBLE        { $$ = new DoubleLiteral ((double) lexer.Value, lexer.Location); }
+       | LITERAL_DECIMAL       { $$ = new DecimalLiteral ((decimal) lexer.Value, lexer.Location); }
+       ;
+
+integer_literal
+       : LITERAL_INTEGER       { 
+               object v = lexer.Value;
+
+               if (v is int){
+                       $$ = new IntLiteral ((int) v, lexer.Location);
+               } else if (v is uint)
+                       $$ = new UIntLiteral ((UInt32) v, lexer.Location);
+               else if (v is long)
+                       $$ = new LongLiteral ((Int64) v, lexer.Location);
+               else if (v is ulong)
+                       $$ = new ULongLiteral ((UInt64) v, lexer.Location);
+               else
+                       Console.WriteLine ("OOPS.  Unexpected result from scanner");
+         }
+       ;
+
+boolean_literal
+       : TRUE                  { $$ = new BoolLiteral (true, lexer.Location); }
+       | FALSE                 { $$ = new BoolLiteral (false, lexer.Location); }
+       ;
+
+parenthesized_expression_0
+       : OPEN_PARENS expression CLOSE_PARENS
+         {
+               $$ = $2;
+               lexer.Deambiguate_CloseParens ($$);
+               // After this, the next token returned is one of
+               // CLOSE_PARENS_CAST, CLOSE_PARENS_NO_CAST (CLOSE_PARENS), CLOSE_PARENS_OPEN_PARENS
+               // or CLOSE_PARENS_MINUS.
+         }
+       | OPEN_PARENS expression error { CheckToken (1026, yyToken, "Expecting ')'", lexer.Location); }
+       ;
+
+parenthesized_expression
+       : parenthesized_expression_0 CLOSE_PARENS_NO_CAST
+         {
+               $$ = $1;
+         }  
+       | parenthesized_expression_0 CLOSE_PARENS
+         {
+               $$ = $1;
+         }       
+       | parenthesized_expression_0 CLOSE_PARENS_MINUS
+         {
+               // If a parenthesized expression is followed by a minus, we need to wrap
+               // the expression inside a ParenthesizedExpression for the CS0075 check
+               // in Binary.DoResolve().
+               $$ = new ParenthesizedExpression ((Expression) $1);
+         }
+       ;
+
+member_access
+       : primary_expression DOT IDENTIFIER
+         {
+               LocatedToken lt = (LocatedToken) $3;
+               $$ = new MemberAccess ((Expression) $1, lt.Value);
+         }
+       | predefined_type DOT IDENTIFIER
+         {
+               LocatedToken lt = (LocatedToken) $3;
+               // TODO: Location is wrong as some predefined types doesn't hold a location
+               $$ = new MemberAccess ((Expression) $1, lt.Value, lt.Location);
+         }
+       ;
+
+predefined_type
+       : builtin_types
+       ;
+
+invocation_expression
+       : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
+         {
+               if ($1 == null)
+                       Report.Error (1, (Location) $2, "Parse error");
+               else
+                       $$ = new Invocation ((Expression) $1, (ArrayList) $3);
+         }
+       | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS OPEN_PARENS CLOSE_PARENS
+         {
+               $$ = new Invocation ((Expression) $1, new ArrayList ());
+         }
+       | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS primary_expression
+         {
+               $$ = new InvocationOrCast ((Expression) $1, (Expression) $3);
+         }
+       | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS OPEN_PARENS non_simple_argument CLOSE_PARENS
+         {
+               ArrayList args = new ArrayList (1);
+               args.Add ($4);
+               $$ = new Invocation ((Expression) $1, args);
+         }
+       | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS OPEN_PARENS argument_list COMMA argument CLOSE_PARENS
+         {
+               ArrayList args = ((ArrayList) $4);
+               args.Add ($6);
+               $$ = new Invocation ((Expression) $1, args);
+         }
+       ;
+
+opt_argument_list
+       : /* empty */           { $$ = null; }
+       | argument_list
+       ;
+
+argument_list
+       : argument
+         { 
+               ArrayList list = new ArrayList (4);
+               list.Add ($1);
+               $$ = list;
+         }
+       | argument_list COMMA argument
+         {
+               ArrayList list = (ArrayList) $1;
+               list.Add ($3);
+               $$ = list;
+         }
+       | argument_list error {
+               CheckToken (1026, yyToken, "Expected `,' or `)'", GetLocation ($2));
+               $$ = null;
+         }
+       ;
+
+argument
+       : expression
+         {
+               $$ = new Argument ((Expression) $1, Argument.AType.Expression);
+         }
+       | non_simple_argument
+         {
+               $$ = $1;
+         }
+       ;
+
+non_simple_argument
+       : REF variable_reference 
+         { 
+               $$ = new Argument ((Expression) $2, Argument.AType.Ref);
+         }
+       | OUT variable_reference 
+         { 
+               $$ = new Argument ((Expression) $2, Argument.AType.Out);
+         }
+       | ARGLIST OPEN_PARENS argument_list CLOSE_PARENS
+         {
+               ArrayList list = (ArrayList) $3;
+               Argument[] args = new Argument [list.Count];
+               list.CopyTo (args, 0);
+
+               Expression expr = new Arglist (args, (Location) $1);
+               $$ = new Argument (expr, Argument.AType.Expression);
+         }
+       | ARGLIST
+         {
+               $$ = new Argument (new ArglistAccess ((Location) $1), Argument.AType.ArgList);
+         }
+       ;
+
+variable_reference
+       : expression { note ("section 5.4"); $$ = $1; }
+       ;
+
+element_access
+       : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET 
+         {
+               $$ = new ElementAccess ((Expression) $1, (ArrayList) $3);
+         }
+       | primary_expression rank_specifiers
+         {
+               // So the super-trick is that primary_expression
+               // can only be either a SimpleName or a MemberAccess. 
+               // The MemberAccess case arises when you have a fully qualified type-name like :
+               // Foo.Bar.Blah i;
+               // SimpleName is when you have
+               // Blah i;
+                 
+               Expression expr = (Expression) $1;  
+               if (expr is ComposedCast){
+                       $$ = new ComposedCast (expr, (string) $2);
+               } else if (!(expr is SimpleName || expr is MemberAccess || expr is QualifiedAliasMember)){
+                       Error_ExpectingTypeName (expr);
+                       $$ = TypeManager.system_object_expr;
+               } else {
+                       //
+                       // So we extract the string corresponding to the SimpleName
+                       // or MemberAccess
+                       // 
+                       $$ = new ComposedCast (expr, (string) $2);
+               }
+               current_array_type = (Expression)$$;
+         }
+       ;
+
+expression_list
+       : expression
+         {
+               ArrayList list = new ArrayList (4);
+               list.Add ($1);
+               $$ = list;
+         }
+       | expression_list COMMA expression
+         {
+               ArrayList list = (ArrayList) $1;
+               list.Add ($3);
+               $$ = list;
+         }
+       ;
+
+this_access
+       : THIS
+         {
+               $$ = new This (current_block, (Location) $1);
+         }
+       ;
+
+base_access
+       : BASE DOT IDENTIFIER
+         {
+               LocatedToken lt = (LocatedToken) $3;
+               $$ = new BaseAccess (lt.Value, lt.Location);
+         }
+       | BASE OPEN_BRACKET expression_list CLOSE_BRACKET
+         {
+               $$ = new BaseIndexerAccess ((ArrayList) $3, (Location) $1);
+         }
+       | BASE error {
+               Report.Error (175, (Location) $1, "Use of keyword `base' is not valid in this context");
+               $$ = null;
+         }
+       ;
+
+post_increment_expression
+       : primary_expression OP_INC
+         {
+               $$ = new UnaryMutator (UnaryMutator.Mode.PostIncrement,
+                                      (Expression) $1, (Location) $2);
+         }
+       ;
+
+post_decrement_expression
+       : primary_expression OP_DEC
+         {
+               $$ = new UnaryMutator (UnaryMutator.Mode.PostDecrement,
+                                      (Expression) $1, (Location) $2);
+         }
+       ;
+
+new_expression
+       : object_or_delegate_creation_expression
+       | array_creation_expression
+       ;
+
+object_or_delegate_creation_expression
+       : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
+         {
+               $$ = new New ((Expression) $2, (ArrayList) $4, (Location) $1);
+         }
+       ;
+
+array_creation_expression
+       : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET 
+         opt_rank_specifier
+         opt_array_initializer
+         {
+               $$ = new ArrayCreation ((Expression) $2, (ArrayList) $4, (string) $6, (ArrayList) $7, (Location) $1);
+         }
+       | NEW type rank_specifiers array_initializer
+         {
+               $$ = new ArrayCreation ((Expression) $2, (string) $3, (ArrayList) $4, (Location) $1);
+         }
+       | NEW error
+         {
+               Report.Error (1031, (Location) $1, "Type expected");
+                $$ = null;
+         }          
+       | NEW type error 
+         {
+               Report.Error (1526, (Location) $1, "A new expression requires () or [] after type");
+               $$ = null;
+         }
+       ;
+
+opt_rank_specifier
+       : /* empty */
+         {
+                 $$ = "";
+         }
+       | rank_specifiers
+         {
+                       $$ = $1;
+         }
+       ;
+
+rank_specifiers
+       : rank_specifier opt_rank_specifier
+         {
+                 $$ = (string) $2 + (string) $1;
+         }
+        ;
+
+rank_specifier
+       : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
+         {
+               $$ = "[" + (string) $2 + "]";
+         }
+       ;
+
+opt_dim_separators
+       : /* empty */
+         {
+               $$ = "";
+         }
+       | dim_separators
+         {
+                 $$ = $1;
+         }               
+       ;
+
+dim_separators
+       : COMMA
+         {
+               $$ = ",";
+         }
+       | dim_separators COMMA
+         {
+               $$ = (string) $1 + ",";
+         }
+       ;
+
+opt_array_initializer
+       : /* empty */
+         {
+               $$ = null;
+         }
+        | array_initializer
+         {
+               $$ = $1;
+         }
+       ;
+
+array_initializer
+       : OPEN_BRACE CLOSE_BRACE
+         {
+               ArrayList list = new ArrayList (4);
+               $$ = list;
+         }
+       | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
+         {
+               $$ = (ArrayList) $2;
+         }
+       ;
+
+variable_initializer_list
+       : variable_initializer
+         {
+               ArrayList list = new ArrayList (4);
+               list.Add ($1);
+               $$ = list;
+         }
+       | variable_initializer_list COMMA variable_initializer
+         {
+               ArrayList list = (ArrayList) $1;
+               list.Add ($3);
+               $$ = list;
+         }
+       ;
+
+typeof_expression
+       : TYPEOF
+      {
+               pushed_current_array_type = current_array_type;
+         }
+         OPEN_PARENS type CLOSE_PARENS
+         {
+               Expression type = (Expression)$4;
+               if (type == TypeManager.system_void_expr)
+                       $$ = new TypeOfVoid ((Location) $1);
+               else
+                       $$ = new TypeOf (type, (Location) $1);
+               current_array_type = pushed_current_array_type;
+         }
+       ;
+
+sizeof_expression
+       : SIZEOF OPEN_PARENS type CLOSE_PARENS { 
+               $$ = new SizeOf ((Expression) $3, (Location) $1);
+         }
+       ;
+
+checked_expression
+       : CHECKED OPEN_PARENS expression CLOSE_PARENS
+         {
+               $$ = new CheckedExpr ((Expression) $3, (Location) $1);
+         }
+       ;
+
+unchecked_expression
+       : UNCHECKED OPEN_PARENS expression CLOSE_PARENS
+         {
+               $$ = new UnCheckedExpr ((Expression) $3, (Location) $1);
+         }
+       ;
+
+pointer_member_access 
+       : primary_expression OP_PTR IDENTIFIER
+         {
+               Expression deref;
+               LocatedToken lt = (LocatedToken) $3;
+
+               deref = new Unary (Unary.Operator.Indirection, (Expression) $1, lt.Location);
+               $$ = new MemberAccess (deref, lt.Value);
+         }
+       ;
+
+anonymous_method_expression
+       : DELEGATE opt_anonymous_method_signature
+         {
+               if (oob_stack == null)
+                       oob_stack = new Stack (6);
+
+               oob_stack.Push (current_anonymous_method);
+               oob_stack.Push (current_local_parameters);
+               current_local_parameters = (Parameters)$2;
+
+               // Force the next block to be created as a ToplevelBlock
+               oob_stack.Push (current_block);
+               oob_stack.Push (top_current_block);
+
+               Location loc = (Location) $1;
+               current_anonymous_method = new AnonymousMethodExpression (
+                       current_anonymous_method, null, current_container,
+                       (Parameters) $2, (ToplevelBlock) top_current_block, loc);
+
+               parsing_anonymous_method = true;
+         }
+         block
+         {
+               Location loc = (Location) $1;
+               top_current_block = (Block) oob_stack.Pop ();
+               current_block = (Block) oob_stack.Pop ();
+
+               if (RootContext.Version == LanguageVersion.ISO_1){
+                       Report.FeatureIsNotStandardized (loc, "anonymous methods");
+                       $$ = null;
+               } else  {
+                       ToplevelBlock anon_block = (ToplevelBlock) $4;
+
+                       anon_block.Parent = current_block;
+
+                       current_anonymous_method.Block = anon_block;
+                       if ((anonymous_host != null) && (current_anonymous_method.Parent == null))
+                               anonymous_host.AddAnonymousMethod (current_anonymous_method);
+
+                       $$ = current_anonymous_method;
+               }
+
+               current_local_parameters = (Parameters) oob_stack.Pop ();
+               current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop ();
+       }
+       ;
+
+opt_anonymous_method_signature
+       : /* empty */                   { $$ = null; } 
+       | anonymous_method_signature
+       ;
+
+anonymous_method_signature
+       : OPEN_PARENS opt_anonymous_method_parameter_list CLOSE_PARENS 
+         {
+               if ($2 == null)
+                       $$ = Parameters.EmptyReadOnlyParameters;
+               else {
+                       ArrayList par_list = (ArrayList) $2;
+                       Parameter [] pars = new Parameter [par_list.Count];
+                       par_list.CopyTo (pars);
+                       $$ = new Parameters (pars);
+               }
+         }
+       ;
+
+opt_anonymous_method_parameter_list
+       : /* empty */                      { $$ = null; } 
+       | anonymous_method_parameter_list  { $$ = $1; }
+       ;
+
+anonymous_method_parameter_list
+       : anonymous_method_parameter 
+         {
+               ArrayList a = new ArrayList (4);
+               a.Add ($1);
+               $$ = a;
+         }
+       | anonymous_method_parameter_list COMMA anonymous_method_parameter 
+         {
+               ArrayList a = (ArrayList) $1;
+               a.Add ($3);
+               $$ = a;
+         }
+       ; 
+
+anonymous_method_parameter
+       : opt_parameter_modifier type IDENTIFIER {
+               LocatedToken lt = (LocatedToken) $3;
+               $$ = new Parameter ((Expression) $2, lt.Value, (Parameter.Modifier) $1, null, lt.Location);
+         }
+       | PARAMS type IDENTIFIER {
+               Report.Error (1670, ((LocatedToken) $3).Location, "The `params' modifier is not allowed in anonymous method declaration");
+               $$ = null;
+         }
+       ;
+
+unary_expression
+       : primary_expression
+       | BANG prefixed_unary_expression
+         {
+               $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, (Location) $1);
+         }
+       | TILDE prefixed_unary_expression
+         {
+               $$ = new Unary (Unary.Operator.OnesComplement, (Expression) $2, (Location) $1);
+         }
+       | cast_expression
+       ;
+
+cast_list
+       : parenthesized_expression_0 CLOSE_PARENS_CAST unary_expression
+         {
+               $$ = new Cast ((Expression) $1, (Expression) $3);
+         }
+       | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS cast_expression
+         {
+               $$ = new Cast ((Expression) $1, (Expression) $3);
+         }     
+       ;
+
+cast_expression
+       : cast_list
+       | OPEN_PARENS non_expression_type CLOSE_PARENS prefixed_unary_expression
+         {
+               // TODO: wrong location
+               $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
+         }
+       ;
+
+       //
+       // The idea to split this out is from Rhys' grammar
+       // to solve the problem with casts.
+       //
+prefixed_unary_expression
+       : unary_expression
+       | PLUS prefixed_unary_expression
+         { 
+               $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, (Location) $1);
+         } 
+       | MINUS prefixed_unary_expression 
+         { 
+               $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, (Location) $1);
+         }
+       | OP_INC prefixed_unary_expression 
+         {
+               $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
+                                      (Expression) $2, (Location) $1);
+         }
+       | OP_DEC prefixed_unary_expression 
+         {
+               $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
+                                      (Expression) $2, (Location) $1);
+         }
+       | STAR prefixed_unary_expression
+         {
+               $$ = new Unary (Unary.Operator.Indirection, (Expression) $2, (Location) $1);
+         }
+       | BITWISE_AND prefixed_unary_expression
+         {
+               $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2, (Location) $1);
+         }
+       ;
+
+pre_increment_expression
+       : OP_INC prefixed_unary_expression 
+         {
+               $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
+                                      (Expression) $2, (Location) $1);
+         }
+       ;
+
+pre_decrement_expression
+       : OP_DEC prefixed_unary_expression 
+         {
+               $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
+                                      (Expression) $2, (Location) $1);
+         }
+       ;
+
+multiplicative_expression
+       : prefixed_unary_expression
+       | multiplicative_expression STAR prefixed_unary_expression
+         {
+               $$ = new Binary (Binary.Operator.Multiply, 
+                                (Expression) $1, (Expression) $3);
+         }
+       | multiplicative_expression DIV prefixed_unary_expression
+         {
+               $$ = new Binary (Binary.Operator.Division, 
+                                (Expression) $1, (Expression) $3);
+         }
+       | multiplicative_expression PERCENT prefixed_unary_expression 
+         {
+               $$ = new Binary (Binary.Operator.Modulus, 
+                                (Expression) $1, (Expression) $3);
+         }
+       ;
+
+additive_expression
+       : multiplicative_expression
+       | additive_expression PLUS multiplicative_expression 
+         {
+               $$ = new Binary (Binary.Operator.Addition, 
+                                (Expression) $1, (Expression) $3);
+         }
+       | additive_expression MINUS multiplicative_expression
+         {
+               $$ = new Binary (Binary.Operator.Subtraction, 
+                                (Expression) $1, (Expression) $3);
+         }
+       ;
+
+shift_expression
+       : additive_expression
+       | shift_expression OP_SHIFT_LEFT additive_expression
+         {
+               $$ = new Binary (Binary.Operator.LeftShift, 
+                                (Expression) $1, (Expression) $3);
+         }
+       | shift_expression OP_SHIFT_RIGHT additive_expression
+         {
+               $$ = new Binary (Binary.Operator.RightShift, 
+                                (Expression) $1, (Expression) $3);
+         }
+       ; 
+
+relational_expression
+       : shift_expression
+       | relational_expression OP_LT shift_expression
+         {
+               $$ = new Binary (Binary.Operator.LessThan, 
+                                (Expression) $1, (Expression) $3);
+         }
+       | relational_expression OP_GT shift_expression
+         {
+               $$ = new Binary (Binary.Operator.GreaterThan, 
+                                (Expression) $1, (Expression) $3);
+         }
+       | relational_expression OP_LE shift_expression
+         {
+               $$ = new Binary (Binary.Operator.LessThanOrEqual, 
+                                (Expression) $1, (Expression) $3);
+         }
+       | relational_expression OP_GE shift_expression
+         {
+               $$ = new Binary (Binary.Operator.GreaterThanOrEqual, 
+                                (Expression) $1, (Expression) $3);
+         }
+       | relational_expression IS type
+         {
+               $$ = new Is ((Expression) $1, (Expression) $3, (Location) $2);
+         }
+       | relational_expression AS type
+         {
+               $$ = new As ((Expression) $1, (Expression) $3, (Location) $2);
+         }
+       ;
+
+equality_expression
+       : relational_expression
+       | equality_expression OP_EQ relational_expression
+         {
+               $$ = new Binary (Binary.Operator.Equality, 
+                                (Expression) $1, (Expression) $3);
+         }
+       | equality_expression OP_NE relational_expression
+         {
+               $$ = new Binary (Binary.Operator.Inequality, 
+                                (Expression) $1, (Expression) $3);
+         }
+       ; 
+
+and_expression
+       : equality_expression
+       | and_expression BITWISE_AND equality_expression
+         {
+               $$ = new Binary (Binary.Operator.BitwiseAnd, 
+                                (Expression) $1, (Expression) $3);
+         }
+       ;
+
+exclusive_or_expression
+       : and_expression
+       | exclusive_or_expression CARRET and_expression
+         {
+               $$ = new Binary (Binary.Operator.ExclusiveOr, 
+                                (Expression) $1, (Expression) $3);
+         }
+       ;
+
+inclusive_or_expression
+       : exclusive_or_expression
+       | inclusive_or_expression BITWISE_OR exclusive_or_expression
+         {
+               $$ = new Binary (Binary.Operator.BitwiseOr, 
+                                (Expression) $1, (Expression) $3);
+         }
+       ;
+
+conditional_and_expression
+       : inclusive_or_expression
+       | conditional_and_expression OP_AND inclusive_or_expression
+         {
+               $$ = new Binary (Binary.Operator.LogicalAnd, 
+                                (Expression) $1, (Expression) $3);
+         }
+       ;
+
+conditional_or_expression
+       : conditional_and_expression
+       | conditional_or_expression OP_OR conditional_and_expression
+         {
+               $$ = new Binary (Binary.Operator.LogicalOr, 
+                                (Expression) $1, (Expression) $3);
+         }
+       ;
+
+conditional_expression
+       : conditional_or_expression
+       | conditional_or_expression INTERR expression COLON expression 
+         {
+               $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5);
+         }
+       ;
+
+assignment_expression
+       : prefixed_unary_expression ASSIGN expression
+         {
+               $$ = new Assign ((Expression) $1, (Expression) $3);
+         }
+       | prefixed_unary_expression OP_MULT_ASSIGN expression
+         {
+               $$ = new CompoundAssign (
+                       Binary.Operator.Multiply, (Expression) $1, (Expression) $3);
+         }
+       | prefixed_unary_expression OP_DIV_ASSIGN expression
+         {
+               $$ = new CompoundAssign (
+                       Binary.Operator.Division, (Expression) $1, (Expression) $3);
+         }
+       | prefixed_unary_expression OP_MOD_ASSIGN expression
+         {
+               $$ = new CompoundAssign (
+                       Binary.Operator.Modulus, (Expression) $1, (Expression) $3);
+         }
+       | prefixed_unary_expression OP_ADD_ASSIGN expression
+         {
+               $$ = new CompoundAssign (
+                       Binary.Operator.Addition, (Expression) $1, (Expression) $3);
+         }
+       | prefixed_unary_expression OP_SUB_ASSIGN expression
+         {
+               $$ = new CompoundAssign (
+                       Binary.Operator.Subtraction, (Expression) $1, (Expression) $3);
+         }
+       | prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression
+         {
+               $$ = new CompoundAssign (
+                       Binary.Operator.LeftShift, (Expression) $1, (Expression) $3);
+         }
+       | prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression
+         {
+               $$ = new CompoundAssign (
+                       Binary.Operator.RightShift, (Expression) $1, (Expression) $3);
+         }
+       | prefixed_unary_expression OP_AND_ASSIGN expression
+         {
+               $$ = new CompoundAssign (
+                       Binary.Operator.BitwiseAnd, (Expression) $1, (Expression) $3);
+         }
+       | prefixed_unary_expression OP_OR_ASSIGN expression
+         {
+               $$ = new CompoundAssign (
+                       Binary.Operator.BitwiseOr, (Expression) $1, (Expression) $3);
+         }
+       | prefixed_unary_expression OP_XOR_ASSIGN expression
+         {
+               $$ = new CompoundAssign (
+                       Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $3);
+         }
+       ;
+
+expression
+       : conditional_expression
+       | assignment_expression
+       ;
+
+constant_expression
+       : expression
+       ;
+
+boolean_expression
+       : expression
+       ;
+
+//
+// 10 classes
+//
+class_declaration
+       : opt_attributes
+         opt_modifiers
+         opt_partial
+         CLASS member_name
+         {
+               MemberName name = MakeName ((MemberName) $5);
+               int mod_flags = (int) $2;
+
+               push_current_class (new Class (
+                       current_namespace, current_class, name,
+                       mod_flags, (Attributes) $1), false, $3);
+         }
+         opt_class_base
+         {
+               if ($7 != null) {
+                       if (current_class.Name == "System.Object") {
+                               Report.Error (537, current_class.Location,
+                                             "The class System.Object cannot have a base " +
+                                             "class or implement an interface.");
+                       }
+                       current_container.AddBasesForPart (current_class, (ArrayList) $7);
+               }
+
+               if (RootContext.Documentation != null) {
+                       current_container.DocComment = Lexer.consume_doc_comment ();
+                       Lexer.doc_state = XmlCommentState.Allowed;
+               }
+         }
+         class_body
+         {
+               if (RootContext.Documentation != null)
+                       Lexer.doc_state = XmlCommentState.Allowed;
+         }
+         opt_semicolon 
+         {
+               $$ = pop_current_class ();
+         }
+       ;       
+
+opt_partial
+       : /* empty */
+         { $$ = null; }
+       | PARTIAL
+         { $$ = $1; } // location
+       ;
+
+opt_modifiers
+       : /* empty */           { $$ = (int) 0; }
+       | modifiers
+       ;
+       
+modifiers
+       : modifier
+       | modifiers modifier
+         { 
+               int m1 = (int) $1;
+               int m2 = (int) $2;
+
+               if ((m1 & m2) != 0) {
+                       Location l = lexer.Location;
+                       Report.Error (1004, l, "Duplicate `{0}' modifier", Modifiers.Name (m2));
+               }
+               $$ = (int) (m1 | m2);
+         }
+      ;
+
+modifier
+       : NEW                   { $$ = Modifiers.NEW; }
+       | PUBLIC                { $$ = Modifiers.PUBLIC; }
+       | PROTECTED             { $$ = Modifiers.PROTECTED; }
+       | INTERNAL              { $$ = Modifiers.INTERNAL; }
+       | PRIVATE               { $$ = Modifiers.PRIVATE; }
+       | ABSTRACT              { $$ = Modifiers.ABSTRACT; }
+       | SEALED                { $$ = Modifiers.SEALED; }
+       | STATIC                { $$ = Modifiers.STATIC; }
+       | READONLY              { $$ = Modifiers.READONLY; }
+       | VIRTUAL               { $$ = Modifiers.VIRTUAL; }
+       | OVERRIDE              { $$ = Modifiers.OVERRIDE; }
+       | EXTERN                { $$ = Modifiers.EXTERN; }
+       | VOLATILE              { $$ = Modifiers.VOLATILE; }
+       | UNSAFE                { $$ = Modifiers.UNSAFE; }
+       ;
+
+opt_class_base
+       : /* empty */           { $$ = null; }
+       | class_base            { $$ = $1;   }
+       ;
+
+class_base
+       : COLON type_list { $$ = $2; }
+       ;
+
+//
+// Statements (8.2)
+//
+
+//
+// A block is "contained" on the following places:
+//     method_body
+//     property_declaration as part of the accessor body (get/set)
+//      operator_declaration
+//     constructor_declaration
+//     destructor_declaration
+//     event_declaration as part of add_accessor_declaration or remove_accessor_declaration
+//      
+block
+       : OPEN_BRACE 
+         {
+               if (parsing_anonymous_method) {
+                       top_current_block = new ToplevelBlock (
+                               current_block, current_local_parameters, null, (Location) $1);
+                       if (current_block != null)
+                               current_block.AddAnonymousChild ((ToplevelBlock) top_current_block);
+                       current_block = top_current_block;
+                       parsing_anonymous_method = false;
+               } else if (current_block == null){
+                       current_block = new ToplevelBlock ((ToplevelBlock) top_current_block, current_local_parameters, (Location) $1);
+                       top_current_block = current_block;
+               } else {
+                       current_block = new Block (current_block, (Location) $1, Location.Null);
+               }
+         } 
+         opt_statement_list CLOSE_BRACE 
+         { 
+               while (current_block.Implicit)
+                       current_block = current_block.Parent;
+               $$ = current_block;
+               current_block.SetEndLocation ((Location) $4);
+               current_block = current_block.Parent;
+               if (current_block == null)
+                       top_current_block = null;
+         }
+       ;
+
+opt_statement_list
+       : /* empty */
+       | statement_list 
+       ;
+
+statement_list
+       : statement
+       | statement_list statement
+       ;
+
+statement
+       : declaration_statement
+         {
+               if ($1 != null && (Block) $1 != current_block){
+                       current_block.AddStatement ((Statement) $1);
+                       current_block = (Block) $1;
+               }
+         }
+       | valid_declaration_statement
+         {
+               current_block.AddStatement ((Statement) $1);
+         }
+       | labeled_statement
+       ;
+
+valid_declaration_statement
+       : block
+       | empty_statement
+        | expression_statement
+       | selection_statement
+       | iteration_statement
+       | jump_statement                  
+       | try_statement
+       | checked_statement
+       | unchecked_statement
+       | lock_statement
+       | using_statement
+       | unsafe_statement
+       | fixed_statement
+       ;
+
+embedded_statement
+       : valid_declaration_statement
+       | declaration_statement
+         {
+                 Report.Error (1023, GetLocation ($1), "An embedded statement may not be a declaration or labeled statement");
+                 $$ = null;
+         }
+       | labeled_statement
+         {
+                 Report.Error (1023, GetLocation ($1), "An embedded statement may not be a declaration or labeled statement");
+                 $$ = null;
+         }
+       ;
+
+empty_statement
+       : SEMICOLON
+         {
+                 $$ = EmptyStatement.Value;
+         }
+       ;
+
+labeled_statement
+       : IDENTIFIER COLON 
+         {
+               LocatedToken lt = (LocatedToken) $1;
+               LabeledStatement labeled = new LabeledStatement (lt.Value, lt.Location);
+
+               if (current_block.AddLabel (labeled))
+                       current_block.AddStatement (labeled);
+         }
+         statement
+       ;
+
+declaration_statement
+       : local_variable_declaration SEMICOLON
+         {
+               current_array_type = null;
+               if ($1 != null){
+                       DictionaryEntry de = (DictionaryEntry) $1;
+                       Expression e = (Expression) de.Key;
+
+                       $$ = declare_local_variables (e, (ArrayList) de.Value, e.Location);
+               }
+         }
+
+       | local_constant_declaration SEMICOLON
+         {
+               current_array_type = null;
+               if ($1 != null){
+                       DictionaryEntry de = (DictionaryEntry) $1;
+
+                       $$ = declare_local_constants ((Expression) de.Key, (ArrayList) de.Value);
+               }
+         }
+       ;
+
+/* 
+ * The following is from Rhys' grammar:
+ * > Types in local variable declarations must be recognized as 
+ * > expressions to prevent reduce/reduce errors in the grammar.
+ * > The expressions are converted into types during semantic analysis.
+ */
+local_variable_type
+       : primary_expression opt_rank_specifier
+         { 
+               // FIXME: Do something smart here regarding the composition of the type.
+
+               // Ok, the above "primary_expression" is there to get rid of
+               // both reduce/reduce and shift/reduces in the grammar, it should
+               // really just be "type_name".  If you use type_name, a reduce/reduce
+               // creeps up.  If you use namespace_or_type_name (which is all we need
+               // really) two shift/reduces appear.
+               // 
+
+               // So the super-trick is that primary_expression
+               // can only be either a SimpleName or a MemberAccess. 
+               // The MemberAccess case arises when you have a fully qualified type-name like :
+               // Foo.Bar.Blah i;
+               // SimpleName is when you have
+               // Blah i;
+                 
+               Expression expr = (Expression) $1;  
+               if (!(expr is SimpleName || expr is MemberAccess || expr is ComposedCast || expr is QualifiedAliasMember)) {
+                       Error_ExpectingTypeName (expr);
+                       $$ = null;
+               } else {
+                       //
+                       // So we extract the string corresponding to the SimpleName
+                       // or MemberAccess
+                       // 
+
+                       if ((string) $2 == "")
+                               $$ = $1;
+                       else
+                               $$ = new ComposedCast ((Expression) $1, (string) $2);
+               }
+         }
+       | builtin_types opt_rank_specifier
+         {
+               if ((string) $2 == "")
+                       $$ = $1;
+               else
+                       $$ = current_array_type = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
+         }
+        ;
+
+local_variable_pointer_type
+       : primary_expression STAR
+         {
+               Expression expr = (Expression) $1;  
+
+               if (!(expr is SimpleName || expr is MemberAccess || expr is ComposedCast || expr is QualifiedAliasMember)) {
+                       Error_ExpectingTypeName (expr);
+
+                       $$ = null;
+               } else 
+                       $$ = new ComposedCast ((Expression) $1, "*");
+         }
+        | builtin_types STAR
+         {
+               $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
+         }
+        | VOID STAR
+         {
+               $$ = new ComposedCast (TypeManager.system_void_expr, "*", (Location) $1);
+         }
+       | local_variable_pointer_type STAR
+          {
+               $$ = new ComposedCast ((Expression) $1, "*");
+         }
+        ;
+
+local_variable_declaration
+       : local_variable_type variable_declarators
+         {
+               if ($1 != null)
+                       $$ = new DictionaryEntry ($1, $2);
+               else
+                       $$ = null;
+         }
+        | local_variable_pointer_type opt_rank_specifier variable_declarators
+         {
+               if ($1 != null){
+                       Expression t;
+
+                       if ((string) $2 == "")
+                               t = (Expression) $1;
+                       else
+                               t = new ComposedCast ((Expression) $1, (string) $2);
+                       $$ = new DictionaryEntry (t, $3);
+               } else 
+                       $$ = null;
+         }
+       ;
+
+local_constant_declaration
+       : CONST local_variable_type constant_declarators
+         {
+               if ($2 != null)
+                       $$ = new DictionaryEntry ($2, $3);
+               else
+                       $$ = null;
+         }
+       ;
+
+expression_statement
+       : statement_expression SEMICOLON { $$ = $1; }
+       ;
+
+       //
+       // We have to do the wrapping here and not in the case above,
+       // because statement_expression is used for example in for_statement
+       //
+statement_expression
+       : expression
+         {
+               Expression expr = (Expression) $1;
+               ExpressionStatement s = expr as ExpressionStatement;
+               if (s == null) {
+                       Report.Error (201, expr.Location, "Only assignment, call, increment, decrement, and new object expressions can be used as a statement");
+                       $$ = null;
+               }
+               $$ = new StatementExpression (s);
+         }
+       | error
+         {
+               Report.Error (1002, GetLocation ($1), "Expecting `;'");
+               $$ = null;
+         }
+       ;
+
+object_creation_expression
+       : object_or_delegate_creation_expression
+         { note ("complain if this is a delegate maybe?"); } 
+       ;
+
+selection_statement
+       : if_statement
+       | switch_statement
+       ; 
+
+if_statement
+       : IF OPEN_PARENS boolean_expression CLOSE_PARENS 
+         embedded_statement
+         { 
+               Location l = (Location) $1;
+
+               $$ = new If ((Expression) $3, (Statement) $5, l);
+
+               // FIXME: location for warning should be loc property of $5.
+               if ($5 == EmptyStatement.Value)
+                       Report.Warning (642, 3, l, "Possible mistaken empty statement");
+
+         }
+       | IF OPEN_PARENS boolean_expression CLOSE_PARENS
+         embedded_statement ELSE embedded_statement
+         {
+               Location l = (Location) $1;
+
+               $$ = new If ((Expression) $3, (Statement) $5, (Statement) $7, l);
+
+               // FIXME: location for warning should be loc property of $5 and $7.
+               if ($5 == EmptyStatement.Value)
+                       Report.Warning (642, 3, l, "Possible mistaken empty statement");
+               if ($7 == EmptyStatement.Value)
+                       Report.Warning (642, 3, l, "Possible mistaken empty statement");
+         }
+       ;
+
+switch_statement
+       : SWITCH OPEN_PARENS
+         { 
+               if (switch_stack == null)
+                       switch_stack = new Stack (2);
+               switch_stack.Push (current_block);
+         }
+         expression CLOSE_PARENS 
+         switch_block
+         {
+               $$ = new Switch ((Expression) $4, (ArrayList) $6, (Location) $1);
+               current_block = (Block) switch_stack.Pop ();
+         }
+       ;
+
+switch_block
+       : OPEN_BRACE
+         opt_switch_sections
+         CLOSE_BRACE
+         {
+               $$ = $2;
+         }
+       ;
+
+opt_switch_sections
+       : /* empty */           
+          {
+               Report.Warning (1522, 1, lexer.Location, "Empty switch block"); 
+               $$ = new ArrayList ();
+         }
+       | switch_sections
+       ;
+
+switch_sections
+       : switch_section 
+         {
+               ArrayList sections = new ArrayList (4);
+
+               sections.Add ($1);
+               $$ = sections;
+         }
+       | switch_sections switch_section
+         {
+               ArrayList sections = (ArrayList) $1;
+
+               sections.Add ($2);
+               $$ = sections;
+         }
+       ;
+
+switch_section
+       : switch_labels
+         {
+               current_block = current_block.CreateSwitchBlock (lexer.Location);
+         }
+         statement_list 
+         {
+               Block topmost = current_block;
+
+               while (topmost.Implicit)
+                       topmost = topmost.Parent;
+               $$ = new SwitchSection ((ArrayList) $1, topmost);
+         }
+       ;
+
+switch_labels
+       : switch_label 
+         {
+               ArrayList labels = new ArrayList (4);
+
+               labels.Add ($1);
+               $$ = labels;
+         }
+       | switch_labels switch_label 
+         {
+               ArrayList labels = (ArrayList) ($1);
+               labels.Add ($2);
+
+               $$ = labels;
+         }
+       ;
+
+switch_label
+       : CASE constant_expression COLON        { $$ = new SwitchLabel ((Expression) $2, (Location) $1); }
+       | DEFAULT COLON                         { $$ = new SwitchLabel (null, (Location) $1); }
+       | error {
+               Report.Error (
+                       1523, GetLocation ($1), 
+                       "The keyword case or default must precede code in switch block");
+         }
+       ;
+
+iteration_statement
+       : while_statement
+       | do_statement
+       | for_statement
+       | foreach_statement
+       ;
+
+while_statement
+       : WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement
+         {
+               Location l = (Location) $1;
+               $$ = new While ((Expression) $3, (Statement) $5, l);
+         }
+       ;
+
+do_statement
+       : DO embedded_statement 
+         WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON
+         {
+               Location l = (Location) $1;
+
+               $$ = new Do ((Statement) $2, (Expression) $5, l);
+         }
+       ;
+
+for_statement
+       : FOR OPEN_PARENS 
+         opt_for_initializer SEMICOLON
+         {
+               Block assign_block = new Block (current_block);
+               current_block = assign_block;
+
+               if ($3 is DictionaryEntry){
+                       DictionaryEntry de = (DictionaryEntry) $3;
+                       
+                       Expression type = (Expression) de.Key;
+                       ArrayList var_declarators = (ArrayList) de.Value;
+
+                       foreach (VariableDeclaration decl in var_declarators){
+
+                               LocalInfo vi;
+
+                               vi = current_block.AddVariable (type, decl.identifier, decl.Location);
+                               if (vi == null)
+                                       continue;
+
+                               Location l = lexer.Location;
+                               Expression expr = decl.expression_or_array_initializer;
+                                       
+                               LocalVariableReference var;
+                               var = new LocalVariableReference (assign_block, decl.identifier, l);
+
+                               if (expr != null) {
+                                       Assign a = new Assign (var, expr, decl.Location);
+                                       
+                                       assign_block.AddStatement (new StatementExpression (a));
+                               }
+                       }
+                       
+                       // Note: the $$ below refers to the value of this code block, not of the LHS non-terminal.
+                       // This can be referred to as $5 below.
+                       $$ = null;
+               } else {
+                       $$ = $3;
+               }
+         } 
+         opt_for_condition SEMICOLON
+         opt_for_iterator CLOSE_PARENS 
+         embedded_statement
+         {
+               Location l = (Location) $1;
+
+               For f = new For ((Statement) $5, (Expression) $6, (Statement) $8, (Statement) $10, l);
+
+               current_block.AddStatement (f);
+               while (current_block.Implicit)
+                       current_block = current_block.Parent;
+               $$ = current_block;
+               current_block = current_block.Parent;
+         }
+       ;
+
+opt_for_initializer
+       : /* empty */           { $$ = EmptyStatement.Value; }
+       | for_initializer       
+       ;
+
+for_initializer
+       : local_variable_declaration
+       | statement_expression_list
+       ;
+
+opt_for_condition
+       : /* empty */           { $$ = null; }
+       | boolean_expression
+       ;
+
+opt_for_iterator
+       : /* empty */           { $$ = EmptyStatement.Value; }
+       | for_iterator
+       ;
+
+for_iterator
+       : statement_expression_list
+       ;
+
+statement_expression_list
+       : statement_expression  
+         {
+               // CHANGE: was `null'
+               Statement s = (Statement) $1;
+               Block b = new Block (current_block, Block.Flags.Implicit, s.loc, lexer.Location);   
+
+               b.AddStatement (s);
+               $$ = b;
+         }
+       | statement_expression_list COMMA statement_expression
+         {
+               Block b = (Block) $1;
+
+               b.AddStatement ((Statement) $3);
+               $$ = $1;
+         }
+       ;
+
+foreach_statement
+       : FOREACH OPEN_PARENS type IN expression CLOSE_PARENS
+         {
+               Report.Error (230, (Location) $1, "Type and identifier are both required in a foreach statement");
+               $$ = null;
+         }
+       | FOREACH OPEN_PARENS type IDENTIFIER IN
+         expression CLOSE_PARENS 
+         {
+               Block foreach_block = new Block (current_block);
+               current_block = foreach_block;
+
+               LocatedToken lt = (LocatedToken) $4;
+               Location l = lt.Location;
+               LocalInfo vi;
+
+               vi = foreach_block.AddVariable ((Expression) $3, lt.Value, l);
+               if (vi != null) {
+                       vi.SetReadOnlyContext (LocalInfo.ReadOnlyContext.Foreach);
+
+                       // Get a writable reference to this read-only variable.
+                       //
+                       // Note that the $$ here refers to the value of _this_ code block,
+                       // not the value of the LHS non-terminal.  This can be referred to as $8 below.
+                       $$ = new LocalVariableReference (foreach_block, lt.Value, l, vi, false);
+               } else {
+                       $$ = null;
+               }
+         } 
+         embedded_statement 
+         {
+               LocalVariableReference v = (LocalVariableReference) $8;
+               Location l = (Location) $1;
+
+               if (v != null) {
+                       Foreach f = new Foreach ((Expression) $3, v, (Expression) $6, (Statement) $9, l);
+                       current_block.AddStatement (f);
+               }
+
+               while (current_block.Implicit)
+                         current_block = current_block.Parent;
+               $$ = current_block;
+               current_block = current_block.Parent;
+         }
+       ;
+
+jump_statement
+       : break_statement
+       | continue_statement
+       | goto_statement
+       | return_statement
+       | throw_statement
+       | yield_statement
+       ;
+
+break_statement
+       : BREAK SEMICOLON
+         {
+               $$ = new Break ((Location) $1);
+         }
+       ;
+
+continue_statement
+       : CONTINUE SEMICOLON
+         {
+               $$ = new Continue ((Location) $1);
+         }
+       ;
+
+goto_statement
+       : GOTO IDENTIFIER SEMICOLON 
+         {
+               LocatedToken lt = (LocatedToken) $2;
+               $$ = new Goto (lt.Value, lt.Location);
+         }
+       | GOTO CASE constant_expression SEMICOLON
+         {
+               $$ = new GotoCase ((Expression) $3, (Location) $1);
+         }
+       | GOTO DEFAULT SEMICOLON 
+         {
+               $$ = new GotoDefault ((Location) $1);
+         }
+       ; 
+
+return_statement
+       : RETURN opt_expression SEMICOLON
+         {
+               $$ = new Return ((Expression) $2, (Location) $1);
+         }
+       ;
+
+throw_statement
+       : THROW opt_expression SEMICOLON
+         {
+               $$ = new Throw ((Expression) $2, (Location) $1);
+         }
+       ;
+
+yield_statement 
+       : IDENTIFIER RETURN expression SEMICOLON
+         {
+               LocatedToken lt = (LocatedToken) $1;
+               string s = lt.Value;
+               if (s != "yield"){
+                       Report.Error (1003, lt.Location, "; expected");
+                       $$ = null;
+               }
+               if (RootContext.Version == LanguageVersion.ISO_1){
+                       Report.FeatureIsNotStandardized (lt.Location, "yield statement");
+                       $$ = null;
+               }
+               if (anonymous_host == null){
+                       Report.Error (204, lt.Location, "yield statement can only be used within a method, operator or property");
+                       $$ = null;
+               } else {
+                       anonymous_host.SetYields ();
+                       $$ = new Yield ((Expression) $3, lt.Location); 
+               }
+         }
+       | IDENTIFIER RETURN SEMICOLON
+         {
+               Report.Error (1627, (Location) $2, "Expression expected after yield return");
+               $$ = null;
+         }
+       | IDENTIFIER BREAK SEMICOLON
+         {
+               LocatedToken lt = (LocatedToken) $1;
+               string s = lt.Value;
+               if (s != "yield"){
+                       Report.Error (1003, lt.Location, "; expected");
+                       $$ = null;
+               }
+               if (RootContext.Version == LanguageVersion.ISO_1){
+                       Report.FeatureIsNotStandardized (lt.Location, "yield statement");
+                       $$ = null;
+               }
+               if (anonymous_host == null){
+                       Report.Error (204, lt.Location, "yield statement can only be used within a method, operator or property");
+                       $$ = null;
+               } else {
+                       anonymous_host.SetYields ();
+                       $$ = new YieldBreak (lt.Location);
+               }
+         }
+       ;
+
+opt_expression
+       : /* empty */
+       | expression
+       ;
+
+try_statement
+       : TRY block catch_clauses 
+         {
+               Catch g = null;
+               
+               ArrayList c = (ArrayList)$3;
+               for (int i = 0; i < c.Count; ++i) {
+                       Catch cc = (Catch) c [i];
+                       if (cc.IsGeneral) {
+                               if (i != c.Count - 1)
+                                       Report.Error (1017, cc.loc, "Try statement already has an empty catch block");
+                               g = cc;
+                               c.RemoveAt (i);
+                               i--;
+                       }
+               }
+
+               // Now s contains the list of specific catch clauses
+               // and g contains the general one.
+               
+               $$ = new Try ((Block) $2, c, g, null, ((Block) $2).loc);
+         }
+       | TRY block opt_catch_clauses FINALLY block
+         {
+               Catch g = null;
+               ArrayList s = new ArrayList (4);
+               ArrayList catch_list = (ArrayList) $3;
+
+               if (catch_list != null){
+                       foreach (Catch cc in catch_list) {
+                               if (cc.IsGeneral)
+                                       g = cc;
+                               else
+                                       s.Add (cc);
+                       }
+               }
+
+               $$ = new Try ((Block) $2, s, g, (Block) $5, ((Block) $2).loc);
+         }
+       | TRY block error 
+         {
+               Report.Error (1524, (Location) $1, "Expected catch or finally");
+               $$ = null;
+         }
+       ;
+
+opt_catch_clauses
+       : /* empty */  { $$ = null; }
+        | catch_clauses
+       ;
+
+catch_clauses
+       : catch_clause 
+         {
+               ArrayList l = new ArrayList (4);
+
+               l.Add ($1);
+               $$ = l;
+         }
+       | catch_clauses catch_clause
+         {
+               ArrayList l = (ArrayList) $1;
+
+               l.Add ($2);
+               $$ = l;
+         }
+       ;
+
+opt_identifier
+       : /* empty */   { $$ = null; }
+       | IDENTIFIER
+       ;
+
+catch_clause 
+       : CATCH opt_catch_args 
+         {
+               Expression type = null;
+               
+               if ($2 != null) {
+                       DictionaryEntry cc = (DictionaryEntry) $2;
+                       type = (Expression) cc.Key;
+                       LocatedToken lt = (LocatedToken) cc.Value;
+
+                       if (lt != null){
+                               ArrayList one = new ArrayList (4);
+
+                               one.Add (new VariableDeclaration (lt, null));
+
+                               current_block = new Block (current_block);
+                               Block b = declare_local_variables (type, one, lt.Location);
+                               current_block = b;
+                       }
+               }
+         } block {
+               Expression type = null;
+               string id = null;
+               Block var_block = null;
+
+               if ($2 != null){
+                       DictionaryEntry cc = (DictionaryEntry) $2;
+                       type = (Expression) cc.Key;
+                       LocatedToken lt = (LocatedToken) cc.Value;
+
+                       if (lt != null){
+                               id = lt.Value;
+                               while (current_block.Implicit)
+                                       current_block = current_block.Parent;
+                               var_block = current_block;
+                               current_block = current_block.Parent;
+                       }
+               }
+
+               $$ = new Catch (type, id, (Block) $4, var_block, ((Block) $4).loc);
+         }
+        ;
+
+opt_catch_args
+       : /* empty */ { $$ = null; }
+        | catch_args
+       ;         
+
+catch_args 
+        : OPEN_PARENS type opt_identifier CLOSE_PARENS 
+          {
+               $$ = new DictionaryEntry ($2, $3);
+         }
+        ;
+
+
+checked_statement
+       : CHECKED block
+         {
+               $$ = new Checked ((Block) $2);
+         }
+       ;
+
+unchecked_statement
+       : UNCHECKED block
+         {
+               $$ = new Unchecked ((Block) $2);
+         }
+       ;
+
+unsafe_statement
+       : UNSAFE 
+         {
+               RootContext.CheckUnsafeOption ((Location) $1);
+         } block {
+               $$ = new Unsafe ((Block) $3);
+         }
+       ;
+
+fixed_statement
+       : FIXED OPEN_PARENS 
+         type fixed_pointer_declarators 
+         CLOSE_PARENS
+         {
+               ArrayList list = (ArrayList) $4;
+               Expression type = (Expression) $3;
+               Location l = (Location) $1;
+               int top = list.Count;
+
+               Block assign_block = new Block (current_block);
+               current_block = assign_block;
+
+               for (int i = 0; i < top; i++){
+                       Pair p = (Pair) list [i];
+                       LocalInfo v;
+
+                       v = current_block.AddVariable (type, (string) p.First, l);
+                       if (v == null)
+                               continue;
+
+                       v.SetReadOnlyContext (LocalInfo.ReadOnlyContext.Fixed);
+                       v.Pinned = true;
+                       p.First = v;
+                       list [i] = p;
+               }
+         }
+         embedded_statement 
+         {
+               Location l = (Location) $1;
+
+               Fixed f = new Fixed ((Expression) $3, (ArrayList) $4, (Statement) $7, l);
+
+               current_block.AddStatement (f);
+               while (current_block.Implicit)
+                       current_block = current_block.Parent;
+               $$ = current_block;
+               current_block = current_block.Parent;
+         }
+       ;
+
+fixed_pointer_declarators
+       : fixed_pointer_declarator      { 
+               ArrayList declarators = new ArrayList (4);
+               if ($1 != null)
+                       declarators.Add ($1);
+               $$ = declarators;
+         }
+       | fixed_pointer_declarators COMMA fixed_pointer_declarator
+         {
+               ArrayList declarators = (ArrayList) $1;
+               if ($3 != null)
+                       declarators.Add ($3);
+               $$ = declarators;
+         }
+       ;
+
+fixed_pointer_declarator
+       : IDENTIFIER ASSIGN expression
+         {
+               LocatedToken lt = (LocatedToken) $1;
+               // FIXME: keep location
+               $$ = new Pair (lt.Value, $3);
+         }
+       | IDENTIFIER
+         {
+               Report.Error (210, ((LocatedToken) $1).Location, "You must provide an initializer in a fixed or using statement declaration");
+               $$ = null;
+         }
+       ;
+
+lock_statement
+       : LOCK OPEN_PARENS expression CLOSE_PARENS 
+         {
+               //
+         } 
+         embedded_statement
+         {
+               $$ = new Lock ((Expression) $3, (Statement) $6, (Location) $1);
+         }
+       ;
+
+using_statement
+       : USING OPEN_PARENS resource_acquisition CLOSE_PARENS
+         {
+               Block assign_block = new Block (current_block);
+               current_block = assign_block;
+
+               if ($3 is DictionaryEntry){
+                       DictionaryEntry de = (DictionaryEntry) $3;
+                       Location l = (Location) $1;
+
+                       Expression type = (Expression) de.Key;
+                       ArrayList var_declarators = (ArrayList) de.Value;
+
+                       ArrayList vars = new ArrayList (4);
+
+                       foreach (VariableDeclaration decl in var_declarators){
+
+                               LocalInfo vi = current_block.AddVariable (type, decl.identifier, decl.Location);
+                               if (vi == null)
+                                       continue;
+                               vi.SetReadOnlyContext (LocalInfo.ReadOnlyContext.Using);
+
+                               Expression expr = decl.expression_or_array_initializer;
+                               if (expr == null) {
+                                       Report.Error (210, l, "You must provide an initializer in a fixed or using statement declaration");
+                               }
+
+                               LocalVariableReference var;
+
+                               // Get a writable reference to this read-only variable.
+                               var = new LocalVariableReference (assign_block, decl.identifier, l, vi, false);
+
+                               // This is so that it is not a warning on using variables
+                               vi.Used = true;
+
+                               vars.Add (new DictionaryEntry (var, expr));                             
+
+                               // Assign a = new Assign (var, expr, decl.Location);
+                               // assign_block.AddStatement (new StatementExpression (a));
+                       }
+
+                       // Note: the $$ here refers to the value of this code block and not of the LHS non-terminal.
+                       // It can be referred to as $5 below.
+                       $$ = new DictionaryEntry (type, vars);
+                } else {
+                       $$ = $3;
+                }
+         } 
+         embedded_statement
+         {
+               Using u = new Using ($5, (Statement) $6, (Location) $1);
+               current_block.AddStatement (u);
+               while (current_block.Implicit)
+                       current_block = current_block.Parent;
+               $$ = current_block;
+               current_block = current_block.Parent;
+         }
+       ; 
+
+resource_acquisition
+       : local_variable_declaration
+       | expression
+       ;
+
+%%
+
+// <summary>
+//   A class used to pass around variable declarations and constants
+// </summary>
+public class VariableDeclaration {
+       public string identifier;
+       public Expression expression_or_array_initializer;
+       public Location Location;
+       public Attributes OptAttributes;
+       public string DocComment;
+
+       public VariableDeclaration (LocatedToken lt, object eoai, Attributes opt_attrs)
+       {
+               this.identifier = lt.Value;
+               if (eoai is ArrayList) {
+                       if (CSharpParser.current_array_type == null)
+                               Report.Error (622, lt.Location,
+                                       "Can only use array initializer expressions to assign to array types. Try using a new expression instead.");
+                       this.expression_or_array_initializer = new ArrayCreation (CSharpParser.current_array_type, "", (ArrayList)eoai, lt.Location);
+               } else {
+                       this.expression_or_array_initializer = (Expression)eoai;
+               }
+               this.Location = lt.Location;
+               this.OptAttributes = opt_attrs;
+       }
+
+       public VariableDeclaration (LocatedToken lt, object eoai) : this (lt, eoai, null)
+       {
+       }
+}
+
+// <summary>
+//   A class used to hold info about an indexer declarator
+// </summary>
+public class IndexerDeclaration {
+       public Expression type;
+       public MemberName interface_type;
+       public Parameters param_list;
+       public Location location;
+
+       public IndexerDeclaration (Expression type, MemberName interface_type,
+                                  Parameters param_list, Location loc)
+       {
+               this.type = type;
+               this.interface_type = interface_type;
+               this.param_list = param_list;
+               this.location = loc;
+       }
+}
+
+//
+// We use this when we do not have an object in advance that is an IAnonymousHost
+//
+public class SimpleAnonymousHost : IAnonymousHost {
+       public static readonly SimpleAnonymousHost Simple = new SimpleAnonymousHost ();
+
+       bool yields;
+       ArrayList anonymous_methods;
+
+       public static SimpleAnonymousHost GetSimple () {
+               Simple.yields = false;
+               Simple.anonymous_methods = null;
+               return Simple;
+       }
+
+       public void SetYields ()
+       {
+               yields = true;
+       }
+
+       public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
+       {
+               if (anonymous_methods == null)
+                       anonymous_methods = new ArrayList ();
+               anonymous_methods.Add (anonymous);
+       }
+
+       public void Propagate (IAnonymousHost real_host)
+       {
+               if (yields)
+                       real_host.SetYields ();
+               if (anonymous_methods != null) {
+                       foreach (AnonymousMethodExpression ame in anonymous_methods)
+                               real_host.AddAnonymousMethod (ame);
+               }
+       }
+}
+
+// <summary>
+//  A class used to hold info about an operator declarator
+// </summary>
+public class OperatorDeclaration {
+       public Operator.OpType optype;
+       public Expression ret_type, arg1type, arg2type;
+       public string arg1name, arg2name;
+       public Location location;
+
+       public OperatorDeclaration (Operator.OpType op, Expression ret_type, 
+                                   Expression arg1type, string arg1name,
+                                   Expression arg2type, string arg2name, Location location)
+       {
+               optype = op;
+               this.ret_type = ret_type;
+               this.arg1type = arg1type;
+               this.arg1name = arg1name;
+               this.arg2type = arg2type;
+               this.arg2name = arg2name;
+               this.location = location;
+       }
+
+}
+
+void Error_ExpectingTypeName (Expression expr)
+{
+       if (expr is Invocation){
+               Report.Error (1002, expr.Location, "Expecting `;'");
+       } else {
+               Report.Error (201, expr.Location, "Only assignment, call, increment, decrement, and new object expressions can be used as a statement");
+       }
+}
+
+void push_current_class (TypeContainer tc, bool is_interface, object partial_token)
+{
+       if (partial_token != null)
+               current_container = current_container.AddPartial (tc, is_interface);
+       else
+               current_container = current_container.AddTypeContainer (tc, is_interface);
+       current_class = tc;
+}
+
+DeclSpace pop_current_class ()
+{
+       DeclSpace retval = current_class;
+
+       current_class = current_class.Parent;
+       current_container = current_class.PartialContainer;
+
+       return retval;
+}
+
+// <summary>
+//   Given the @class_name name, it creates a fully qualified name
+//   based on the containing declaration space
+// </summary>
+MemberName
+MakeName (MemberName class_name)
+{
+       Namespace ns = current_namespace.NS;
+
+       if (current_container.Name.Length == 0){
+               if (ns.Name.Length != 0)
+                       return new MemberName (ns.MemberName, class_name);
+               else
+                       return class_name;
+       } else {
+               return new MemberName (current_container.MemberName, class_name);
+       }
+}
+
+Block declare_local_variables (Expression type, ArrayList variable_declarators, Location loc)
+{
+       Block implicit_block;
+       ArrayList inits = null;
+
+       //
+       // We use the `Used' property to check whether statements
+       // have been added to the current block.  If so, we need
+       // to create another block to contain the new declaration
+       // otherwise, as an optimization, we use the same block to
+       // add the declaration.
+       //
+       // FIXME: A further optimization is to check if the statements
+       // that were added were added as part of the initialization
+       // below.  In which case, no other statements have been executed
+       // and we might be able to reduce the number of blocks for
+       // situations like this:
+       //
+       // int j = 1;  int k = j + 1;
+       //
+       if (current_block.Used)
+               implicit_block = new Block (current_block, Block.Flags.Implicit, loc, Location.Null);
+       else
+               implicit_block = current_block;
+
+       foreach (VariableDeclaration decl in variable_declarators){
+
+               if (implicit_block.AddVariable (type, decl.identifier, decl.Location) != null) {
+                       if (decl.expression_or_array_initializer != null){
+                               if (inits == null)
+                                       inits = new ArrayList (4);
+                               inits.Add (decl);
+                       }
+               }
+       }
+
+       if (inits == null)
+               return implicit_block;
+
+       foreach (VariableDeclaration decl in inits){
+               Assign assign;
+               Expression expr = decl.expression_or_array_initializer;
+               
+               LocalVariableReference var;
+               var = new LocalVariableReference (implicit_block, decl.identifier, loc);
+
+               assign = new Assign (var, expr, decl.Location);
+
+               implicit_block.AddStatement (new StatementExpression (assign));
+       }
+       
+       return implicit_block;
+}
+
+Block declare_local_constants (Expression type, ArrayList declarators)
+{
+       Block implicit_block;
+
+       if (current_block.Used)
+               implicit_block = new Block (current_block, Block.Flags.Implicit);
+       else
+               implicit_block = current_block;
+
+       foreach (VariableDeclaration decl in declarators){
+               implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer, decl.Location);
+       }
+       
+       return implicit_block;
+}
+
+void CheckAttributeTarget (string a, Location l)
+{
+       switch (a) {
+
+       case "assembly" : case "module" : case "field" : case "method" : case "param" : case "property" : case "type" :
+               return;
+               
+       default :
+               Report.Error (658, l, "`" + a + "' is an invalid attribute target");
+               break;
+       }
+
+}
+
+void CheckUnaryOperator (Operator.OpType op, Location l)
+{
+       switch (op) {
+               
+       case Operator.OpType.LogicalNot: 
+       case Operator.OpType.OnesComplement: 
+       case Operator.OpType.Increment:
+       case Operator.OpType.Decrement:
+       case Operator.OpType.True: 
+       case Operator.OpType.False: 
+       case Operator.OpType.Addition: 
+       case Operator.OpType.Subtraction:
+               
+               break;
+               
+       default :
+               Report.Error (1019, l, "Overloadable unary operator expected"); 
+               break;
+               
+       }
+}
+
+void CheckBinaryOperator (Operator.OpType op, Location l)
+{
+       switch (op) {
+               
+       case Operator.OpType.Addition: 
+       case Operator.OpType.Subtraction: 
+       case Operator.OpType.Multiply:
+       case Operator.OpType.Division:
+       case Operator.OpType.Modulus: 
+       case Operator.OpType.BitwiseAnd: 
+       case Operator.OpType.BitwiseOr:
+       case Operator.OpType.ExclusiveOr: 
+       case Operator.OpType.LeftShift: 
+       case Operator.OpType.RightShift:
+       case Operator.OpType.Equality: 
+       case Operator.OpType.Inequality:
+       case Operator.OpType.GreaterThan: 
+       case Operator.OpType.LessThan: 
+       case Operator.OpType.GreaterThanOrEqual:
+       case Operator.OpType.LessThanOrEqual:
+               break;
+               
+       default :
+               Report.Error (1020, l, "Overloadable binary operator expected");
+               break;
+       }
+       
+}
+
+void syntax_error (Location l, string msg)
+{
+       Report.Error (1003, l, "Syntax error, " + msg);
+}
+
+void note (string s)
+{
+       // Used to put annotations
+}
+
+Tokenizer lexer;
+
+public Tokenizer Lexer {
+       get {
+               return lexer;
+       }
+}                 
+
+public CSharpParser (SeekableStreamReader reader, SourceFile file, ArrayList defines)
+{
+       this.name = file.Name;
+       this.file = file;
+       current_namespace = new NamespaceEntry (null, file, null);
+       current_class = current_namespace.SlaveDeclSpace;
+       current_container = current_class.PartialContainer; // == RootContest.ToplevelTypes
+
+       lexer = new Tokenizer (reader, file, defines);
+}
+
+public void parse ()
+{
+       int errors = Report.Errors;
+       try {
+               if (yacc_verbose_flag > 1)
+                       yyparse (lexer, new yydebug.yyDebugSimple ());
+               else
+                       yyparse (lexer);
+               Tokenizer tokenizer = lexer as Tokenizer;
+               tokenizer.cleanup ();
+       } catch (Exception e){
+               // 
+               // Removed for production use, use parser verbose to get the output.
+               //
+               // Console.WriteLine (e);
+               if (Report.Errors == errors)
+                       Report.Error (-25, lexer.Location, "Parsing error");
+               if (yacc_verbose_flag > 0)
+                       Console.WriteLine (e);
+       }
+
+       if (RootContext.ToplevelTypes.NamespaceEntry != null)
+               throw new InternalErrorException ("who set it?");
+}
+
+static void CheckToken (int error, int yyToken, string msg, Location loc)
+{
+       if (yyToken >= Token.FIRST_KEYWORD && yyToken <= Token.LAST_KEYWORD)
+               Report.Error (error, loc, "{0}: `{1}' is a keyword", msg, yyNames [yyToken].ToLower ());
+       else
+               Report.Error (error, loc, msg);
+}
+
+void CheckIdentifierToken (int yyToken, Location loc)
+{
+       CheckToken (1041, yyToken, "Identifier expected", loc);
+}
+
+string ConsumeStoredComment ()
+{
+       string s = tmpComment;
+       tmpComment = null;
+       Lexer.doc_state = XmlCommentState.Allowed;
+       return s;
+}
+
+Location GetLocation (object obj)
+{
+       if (obj is MemberCore)
+               return ((MemberCore) obj).Location;
+       if (obj is MemberName)
+               return ((MemberName) obj).Location;
+       if (obj is LocatedToken)
+               return ((LocatedToken) obj).Location;
+       if (obj is Location)
+               return (Location) obj;
+       return lexer.Location;
+}
+
+/* end end end */
+}
diff --git a/mcs/mcs/cs-tokenizer.cs b/mcs/mcs/cs-tokenizer.cs
new file mode 100644 (file)
index 0000000..4c9ab64
--- /dev/null
@@ -0,0 +1,2601 @@
+//
+// cs-tokenizer.cs: The Tokenizer for the C# compiler
+//                  This also implements the preprocessor
+//
+// Author: Miguel de Icaza (miguel@gnu.org)
+//         Marek Safar (marek.safar@seznam.cz)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)
+// (C) 2004 Novell, Inc
+//
+
+/*
+ * TODO:
+ *   Make sure we accept the proper Unicode ranges, per the spec.
+ *   Report error 1032
+*/
+
+using System;
+using System.Text;
+using System.Collections;
+using System.IO;
+using System.Globalization;
+using System.Reflection;
+
+namespace Mono.CSharp
+{
+       /// <summary>
+       ///    Tokenizer for C# source code. 
+       /// </summary>
+
+       public class Tokenizer : yyParser.yyInput
+       {
+               SeekableStreamReader reader;
+               SourceFile ref_name;
+               SourceFile file_name;
+               int ref_line = 1;
+               int line = 1;
+               int col = 0;
+               int previous_col;
+               int current_token;
+               bool handle_get_set = false;
+               bool handle_remove_add = false;
+               bool handle_assembly = false;
+               bool handle_constraints = false;
+               bool handle_typeof = false;
+               Location current_location;
+               Location current_comment_location = Location.Null;
+               ArrayList escapedIdentifiers = new ArrayList ();
+
+               //
+               // XML documentation buffer. The save point is used to divide
+               // comments on types and comments on members.
+               //
+               StringBuilder xml_comment_buffer;
+
+               //
+               // See comment on XmlCommentState enumeration.
+               //
+               XmlCommentState xmlDocState = XmlCommentState.Allowed;
+
+               //
+               // Whether tokens have been seen on this line
+               //
+               bool tokens_seen = false;
+
+               //
+               // Whether a token has been seen on the file
+               // This is needed because `define' is not allowed to be used
+               // after a token has been seen.
+               //
+               bool any_token_seen = false;
+
+               static Hashtable tokenValues;
+
+               private static Hashtable TokenValueName
+               {
+                       get {
+                               if (tokenValues == null)
+                                       tokenValues = GetTokenValueNameHash ();
+
+                               return tokenValues;
+                       }
+               }
+
+               private static Hashtable GetTokenValueNameHash ()
+               {
+                       Type t = typeof (Token);
+                       FieldInfo [] fields = t.GetFields ();
+                       Hashtable hash = new Hashtable ();
+                       foreach (FieldInfo field in fields) {
+                               if (field.IsLiteral && field.IsStatic && field.FieldType == typeof (int))
+                                       hash.Add (field.GetValue (null), field.Name);
+                       }
+                       return hash;
+               }
+               
+               //
+               // Returns a verbose representation of the current location
+               //
+               public string location {
+                       get {
+                               string det;
+
+                               if (current_token == Token.ERROR)
+                                       det = "detail: " + error_details;
+                               else
+                                       det = "";
+                               
+                               // return "Line:     "+line+" Col: "+col + "\n" +
+                               //       "VirtLine: "+ref_line +
+                               //       " Token: "+current_token + " " + det;
+                               string current_token_name = TokenValueName [current_token] as string;
+                               if (current_token_name == null)
+                                       current_token_name = current_token.ToString ();
+
+                               return String.Format ("{0} ({1},{2}), Token: {3} {4}", ref_name.Name,
+                                                                                      ref_line,
+                                                                                      col,
+                                                                                      current_token_name,
+                                                                                      det);
+                       }
+               }
+
+               public bool PropertyParsing {
+                       get {
+                               return handle_get_set;
+                       }
+
+                       set {
+                               handle_get_set = value;
+                       }
+                }
+
+               public bool AssemblyTargetParsing {
+                       get {
+                               return handle_assembly;
+                       }
+
+                       set {
+                               handle_assembly = value;
+                       }
+               }
+
+               public bool EventParsing {
+                       get {
+                               return handle_remove_add;
+                       }
+
+                       set {
+                               handle_remove_add = value;
+                       }
+               }
+
+               public bool ConstraintsParsing {
+                       get {
+                               return handle_constraints;
+                       }
+
+                       set {
+                               handle_constraints = value;
+                       }
+               }
+
+               public bool TypeOfParsing {
+                       get {
+                               return handle_typeof;
+                       }
+
+                       set {
+                               handle_typeof = value;
+                       }
+               }
+
+               public XmlCommentState doc_state {
+                       get { return xmlDocState; }
+                       set {
+                               if (value == XmlCommentState.Allowed) {
+                                       check_incorrect_doc_comment ();
+                                       reset_doc_comment ();
+                               }
+                               xmlDocState = value;
+                       }
+               }
+
+               public bool IsEscapedIdentifier (Location loc)
+               {
+                       foreach (LocatedToken lt in escapedIdentifiers)
+                               if (lt.Location.Equals (loc))
+                                       return true;
+                       return false;
+               }
+
+               //
+               // Class variables
+               // 
+               static CharArrayHashtable[] keywords;
+               static Hashtable keywordStrings = new Hashtable ();
+               static NumberStyles styles;
+               static NumberFormatInfo csharp_format_info;
+               
+               //
+               // Values for the associated token returned
+               //
+               int putback_char;
+               Object val;
+
+               //
+               // Pre-processor
+               //
+               Hashtable defines;
+
+               const int TAKING        = 1;
+               const int TAKEN_BEFORE  = 2;
+               const int ELSE_SEEN     = 4;
+               const int PARENT_TAKING = 8;
+               const int REGION        = 16;           
+
+               //
+               // pre-processor if stack state:
+               //
+               Stack ifstack;
+
+               static System.Text.StringBuilder string_builder;
+
+               const int max_id_size = 512;
+               static char [] id_builder = new char [max_id_size];
+
+               static CharArrayHashtable [] identifiers = new CharArrayHashtable [max_id_size + 1];
+
+               const int max_number_size = 512;
+               static char [] number_builder = new char [max_number_size];
+               static int number_pos;
+               
+               //
+               // Details about the error encoutered by the tokenizer
+               //
+               string error_details;
+               
+               public string error {
+                       get {
+                               return error_details;
+                       }
+               }
+               
+               public int Line {
+                       get {
+                               return ref_line;
+                       }
+               }
+
+               public int Col {
+                       get {
+                               return col;
+                       }
+               }
+
+               //
+               // This is used when the tokenizer needs to save
+               // the current position as it needs to do some parsing
+               // on its own to deamiguate a token in behalf of the
+               // parser.
+               //
+               Stack position_stack = new Stack (2);
+               class Position {
+                       public int position;
+                       public int ref_line;
+                       public int col;
+                       public int putback_char;
+                       public int previous_col;
+#if GMCS_SOURCES
+                       public int parsing_generic_less_than;
+#endif                 
+                       public Position (Tokenizer t)
+                       {
+                               position = t.reader.Position;
+                               ref_line = t.ref_line;
+                               col = t.col;
+                               putback_char = t.putback_char;
+                               previous_col = t.previous_col;
+#if GMCS_SOURCES
+                               parsing_generic_less_than = t.parsing_generic_less_than;
+#endif
+                       }
+               }
+               
+               public void PushPosition ()
+               {
+                       position_stack.Push (new Position (this));
+               }
+
+               public void PopPosition ()
+               {
+                       Position p = (Position) position_stack.Pop ();
+
+                       reader.Position = p.position;
+                       ref_line = p.ref_line;
+                       col = p.col;
+                       putback_char = p.putback_char;
+                       previous_col = p.previous_col;
+
+               }
+
+               // Do not reset the position, ignore it.
+               public void DiscardPosition ()
+               {
+                       position_stack.Pop ();
+               }
+               
+               static void AddKeyword (string kw, int token) {
+                       keywordStrings.Add (kw, kw);
+                       if (keywords [kw.Length] == null) {
+                               keywords [kw.Length] = new CharArrayHashtable (kw.Length);
+                       }
+                       keywords [kw.Length] [kw.ToCharArray ()] = token;
+               }
+
+               static void InitTokens ()
+               {
+                       keywords = new CharArrayHashtable [64];
+
+                       AddKeyword ("__arglist", Token.ARGLIST);
+                       AddKeyword ("abstract", Token.ABSTRACT);
+                       AddKeyword ("as", Token.AS);
+                       AddKeyword ("add", Token.ADD);
+                       AddKeyword ("assembly", Token.ASSEMBLY);
+                       AddKeyword ("base", Token.BASE);
+                       AddKeyword ("bool", Token.BOOL);
+                       AddKeyword ("break", Token.BREAK);
+                       AddKeyword ("byte", Token.BYTE);
+                       AddKeyword ("case", Token.CASE);
+                       AddKeyword ("catch", Token.CATCH);
+                       AddKeyword ("char", Token.CHAR);
+                       AddKeyword ("checked", Token.CHECKED);
+                       AddKeyword ("class", Token.CLASS);
+                       AddKeyword ("const", Token.CONST);
+                       AddKeyword ("continue", Token.CONTINUE);
+                       AddKeyword ("decimal", Token.DECIMAL);
+                       AddKeyword ("default", Token.DEFAULT);
+                       AddKeyword ("delegate", Token.DELEGATE);
+                       AddKeyword ("do", Token.DO);
+                       AddKeyword ("double", Token.DOUBLE);
+                       AddKeyword ("else", Token.ELSE);
+                       AddKeyword ("enum", Token.ENUM);
+                       AddKeyword ("event", Token.EVENT);
+                       AddKeyword ("explicit", Token.EXPLICIT);
+                       AddKeyword ("extern", Token.EXTERN);
+                       AddKeyword ("false", Token.FALSE);
+                       AddKeyword ("finally", Token.FINALLY);
+                       AddKeyword ("fixed", Token.FIXED);
+                       AddKeyword ("float", Token.FLOAT);
+                       AddKeyword ("for", Token.FOR);
+                       AddKeyword ("foreach", Token.FOREACH);
+                       AddKeyword ("goto", Token.GOTO);
+                       AddKeyword ("get", Token.GET);
+                       AddKeyword ("if", Token.IF);
+                       AddKeyword ("implicit", Token.IMPLICIT);
+                       AddKeyword ("in", Token.IN);
+                       AddKeyword ("int", Token.INT);
+                       AddKeyword ("interface", Token.INTERFACE);
+                       AddKeyword ("internal", Token.INTERNAL);
+                       AddKeyword ("is", Token.IS);
+                       AddKeyword ("lock", Token.LOCK);
+                       AddKeyword ("long", Token.LONG);
+                       AddKeyword ("namespace", Token.NAMESPACE);
+                       AddKeyword ("new", Token.NEW);
+                       AddKeyword ("null", Token.NULL);
+                       AddKeyword ("object", Token.OBJECT);
+                       AddKeyword ("operator", Token.OPERATOR);
+                       AddKeyword ("out", Token.OUT);
+                       AddKeyword ("override", Token.OVERRIDE);
+                       AddKeyword ("params", Token.PARAMS);
+                       AddKeyword ("private", Token.PRIVATE);
+                       AddKeyword ("protected", Token.PROTECTED);
+                       AddKeyword ("public", Token.PUBLIC);
+                       AddKeyword ("readonly", Token.READONLY);
+                       AddKeyword ("ref", Token.REF);
+                       AddKeyword ("remove", Token.REMOVE);
+                       AddKeyword ("return", Token.RETURN);
+                       AddKeyword ("sbyte", Token.SBYTE);
+                       AddKeyword ("sealed", Token.SEALED);
+                       AddKeyword ("set", Token.SET);
+                       AddKeyword ("short", Token.SHORT);
+                       AddKeyword ("sizeof", Token.SIZEOF);
+                       AddKeyword ("stackalloc", Token.STACKALLOC);
+                       AddKeyword ("static", Token.STATIC);
+                       AddKeyword ("string", Token.STRING);
+                       AddKeyword ("struct", Token.STRUCT);
+                       AddKeyword ("switch", Token.SWITCH);
+                       AddKeyword ("this", Token.THIS);
+                       AddKeyword ("throw", Token.THROW);
+                       AddKeyword ("true", Token.TRUE);
+                       AddKeyword ("try", Token.TRY);
+                       AddKeyword ("typeof", Token.TYPEOF);
+                       AddKeyword ("uint", Token.UINT);
+                       AddKeyword ("ulong", Token.ULONG);
+                       AddKeyword ("unchecked", Token.UNCHECKED);
+                       AddKeyword ("unsafe", Token.UNSAFE);
+                       AddKeyword ("ushort", Token.USHORT);
+                       AddKeyword ("using", Token.USING);
+                       AddKeyword ("virtual", Token.VIRTUAL);
+                       AddKeyword ("void", Token.VOID);
+                       AddKeyword ("volatile", Token.VOLATILE);
+                       AddKeyword ("while", Token.WHILE);
+                       AddKeyword ("partial", Token.PARTIAL);
+#if GMCS_SOURCE
+                       AddKeyword ("where", Token.WHERE);
+#endif
+               }
+
+               //
+               // Class initializer
+               // 
+               static Tokenizer ()
+               {
+                       InitTokens ();
+                       csharp_format_info = NumberFormatInfo.InvariantInfo;
+                       styles = NumberStyles.Float;
+                       
+                       string_builder = new System.Text.StringBuilder ();
+               }
+
+               int GetKeyword (char[] id, int id_len)
+               {
+                       /*
+                        * Keywords are stored in an array of hashtables grouped by their
+                        * length.
+                        */
+
+                       if ((id_len >= keywords.Length) || (keywords [id_len] == null))
+                               return -1;
+                       object o = keywords [id_len] [id];
+
+                       if (o == null)
+                               return -1;
+                       
+                       int res = (int) o;
+
+                       if (handle_get_set == false && (res == Token.GET || res == Token.SET))
+                               return -1;
+                       if (handle_remove_add == false && (res == Token.REMOVE || res == Token.ADD))
+                               return -1;
+                       if (handle_assembly == false && res == Token.ASSEMBLY)
+                               return -1;
+#if GMCS_SOURCE
+                       if (handle_constraints == false && res == Token.WHERE)
+                               return -1;
+#endif
+                       return res;
+                       
+               }
+
+               public Location Location {
+                       get { return current_location; }
+               }
+
+               void define (string def)
+               {
+                       if (!RootContext.AllDefines.Contains (def)){
+                               RootContext.AllDefines [def] = true;
+                       }
+                       if (defines.Contains (def))
+                               return;
+                       defines [def] = true;
+               }
+               
+               public Tokenizer (SeekableStreamReader input, SourceFile file, ArrayList defs)
+               {
+                       this.ref_name = file;
+                       this.file_name = file;
+                       reader = input;
+                       
+                       putback_char = -1;
+
+                       if (defs != null){
+                               defines = new Hashtable ();
+                               foreach (string def in defs)
+                                       define (def);
+                       }
+
+                       xml_comment_buffer = new StringBuilder ();
+
+                       //
+                       // FIXME: This could be `Location.Push' but we have to
+                       // find out why the MS compiler allows this
+                       //
+                       Mono.CSharp.Location.Push (file);
+               }
+
+               static bool is_identifier_start_character (char c)
+               {
+                       return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || Char.IsLetter (c);
+               }
+
+               static bool is_identifier_part_character (char c)
+               {
+                       return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= '0' && c <= '9') || Char.IsLetter (c);
+               }
+
+               public static bool IsKeyword (string s)
+               {
+                       return keywordStrings [s] != null;
+               }
+
+               public static bool IsValidIdentifier (string s)
+               {
+                       if (s == null || s.Length == 0)
+                               return false;
+
+                       if (!is_identifier_start_character (s [0]))
+                               return false;
+                       
+                       for (int i = 1; i < s.Length; i ++)
+                               if (! is_identifier_part_character (s [i]))
+                                       return false;
+                       
+                       return true;
+               }
+
+#if GMCS_SOURCE
+               bool parse_generic_dimension (out int dimension)
+               {
+                       dimension = 1;
+
+               again:
+                       int the_token = token ();
+                       if (the_token == Token.OP_GENERICS_GT)
+                               return true;
+                       else if (the_token == Token.COMMA) {
+                               dimension++;
+                               goto again;
+                       }
+
+                       return false;
+               }
+
+               bool parse_less_than ()
+               {
+               start:
+                       int the_token = token ();
+                       if (the_token == Token.OPEN_BRACKET) {
+                               do {
+                                       the_token = token ();
+                               } while (the_token != Token.CLOSE_BRACKET);
+                               the_token = token ();
+                       }
+                       switch (the_token) {
+                       case Token.IDENTIFIER:
+                       case Token.OBJECT:
+                       case Token.STRING:
+                       case Token.BOOL:
+                       case Token.DECIMAL:
+                       case Token.FLOAT:
+                       case Token.DOUBLE:
+                       case Token.SBYTE:
+                       case Token.BYTE:
+                       case Token.SHORT:
+                       case Token.USHORT:
+                       case Token.INT:
+                       case Token.UINT:
+                       case Token.LONG:
+                       case Token.ULONG:
+                       case Token.CHAR:
+                       case Token.VOID:
+                               break;
+
+                       default:
+                               return false;
+                       }
+               again:
+                       the_token = token ();
+
+                       if (the_token == Token.OP_GENERICS_GT)
+                               return true;
+                       else if ((the_token == Token.COMMA) || (the_token == Token.DOT))
+                               goto start;
+                       else if (the_token == Token.INTERR || the_token == Token.STAR)
+                               goto again;
+                       else if (the_token == Token.OP_GENERICS_LT) {
+                               if (!parse_less_than ())
+                                       return false;
+                               goto again;
+                       } else if (the_token == Token.OPEN_BRACKET) {
+                       rank_specifiers:
+                               the_token = token ();
+                               if (the_token == Token.CLOSE_BRACKET)
+                                       goto again;
+                               else if (the_token == Token.COMMA)
+                                       goto rank_specifiers;
+                               return false;
+                       }
+
+                       return false;
+               }
+
+               int parsing_generic_less_than = 0;
+
+               public void PutbackNullable ()
+               {
+                       if (nullable_pos < 0)
+                               throw new Exception ();
+
+                       current_token = -1;
+                       val = null;
+                       reader.Position = nullable_pos;
+
+                       putback_char = '?';
+               }
+
+               public void PutbackCloseParens ()
+               {
+                       putback_char = ')';
+               }
+
+
+               int nullable_pos = -1;
+
+               public void CheckNullable (bool is_nullable)
+               {
+                       if (is_nullable)
+                               nullable_pos = reader.Position;
+                       else
+                               nullable_pos = -1;
+               }
+#endif
+               int is_punct (char c, ref bool doread)
+               {
+                       int d;
+                       int t;
+
+                       doread = false;
+
+                       switch (c){
+                       case '{':
+                               val = Location;
+                               return Token.OPEN_BRACE;
+                       case '}':
+                               val = Location;
+                               return Token.CLOSE_BRACE;
+                       case '[':
+                               // To block doccomment inside attribute declaration.
+                               if (doc_state == XmlCommentState.Allowed)
+                                       doc_state = XmlCommentState.NotAllowed;
+                               return Token.OPEN_BRACKET;
+                       case ']':
+                               return Token.CLOSE_BRACKET;
+                       case '(':
+                               return Token.OPEN_PARENS;
+                       case ')': {
+                               if (deambiguate_close_parens == 0)
+                                       return Token.CLOSE_PARENS;
+
+                               --deambiguate_close_parens;
+
+                               PushPosition ();
+
+                               // disable preprocessing directives when peeking
+                               process_directives = false;
+                               int new_token = xtoken ();
+                               process_directives = true;
+
+                               PopPosition ();
+
+                               if (new_token == Token.OPEN_PARENS)
+                                       return Token.CLOSE_PARENS_OPEN_PARENS;
+                               else if (new_token == Token.MINUS)
+                                       return Token.CLOSE_PARENS_MINUS;
+                               else if (IsCastToken (new_token))
+                                       return Token.CLOSE_PARENS_CAST;
+                               else
+                                       return Token.CLOSE_PARENS_NO_CAST;
+                       }
+
+                       case ',':
+                               return Token.COMMA;
+                       case ';':
+                               val = Location;
+                               return Token.SEMICOLON;
+                       case '~':
+                               val = Location;
+                               return Token.TILDE;
+                       case '?':
+                               return Token.INTERR;
+                       }
+#if GMCS_SOURCE
+                       if (c == '<') {
+                               if (parsing_generic_less_than++ > 0)
+                                       return Token.OP_GENERICS_LT;
+
+                               if (handle_typeof) {
+                                       int dimension;
+                                       PushPosition ();
+                                       if (parse_generic_dimension (out dimension)) {
+                                               val = dimension;
+                                               DiscardPosition ();
+                                               return Token.GENERIC_DIMENSION;
+                                       }
+                                       PopPosition ();
+                               }
+
+                               // Save current position and parse next token.
+                               PushPosition ();
+                               bool is_generic_lt = parse_less_than ();
+                               PopPosition ();
+
+                               if (is_generic_lt) {
+                                       parsing_generic_less_than++;
+                                       return Token.OP_GENERICS_LT;
+                               } else
+                                       parsing_generic_less_than = 0;
+
+                               d = peekChar ();
+                               if (d == '<'){
+                                       getChar ();
+                                       d = peekChar ();
+
+                                       if (d == '='){
+                                               doread = true;
+                                               return Token.OP_SHIFT_LEFT_ASSIGN;
+                                       }
+                                       return Token.OP_SHIFT_LEFT;
+                               } else if (d == '='){
+                                       doread = true;
+                                       return Token.OP_LE;
+                               }
+                               return Token.OP_LT;
+                       } else if (c == '>') {
+                               if (parsing_generic_less_than > 0) {
+                                       parsing_generic_less_than--;
+                                       return Token.OP_GENERICS_GT;
+                               }
+
+                               d = peekChar ();
+                               if (d == '>'){
+                                       getChar ();
+                                       d = peekChar ();
+
+                                       if (d == '='){
+                                               doread = true;
+                                               return Token.OP_SHIFT_RIGHT_ASSIGN;
+                                       }
+                                       return Token.OP_SHIFT_RIGHT;
+                               } else if (d == '='){
+                                       doread = true;
+                                       return Token.OP_GE;
+                               }
+                               return Token.OP_GT;
+                       }
+#endif
+                       d = peekChar ();
+                       if (c == '+'){
+                               
+                               if (d == '+') {
+                                       val = Location;
+                                       t = Token.OP_INC;
+                               }
+                               else if (d == '=')
+                                       t = Token.OP_ADD_ASSIGN;
+                               else {
+                                       val = Location;
+                                       return Token.PLUS;
+                               }
+                               doread = true;
+                               return t;
+                       }
+                       if (c == '-'){
+                               if (d == '-') {
+                                       val = Location;
+                                       t = Token.OP_DEC;
+                               }
+                               else if (d == '=')
+                                       t = Token.OP_SUB_ASSIGN;
+                               else if (d == '>')
+                                       t = Token.OP_PTR;
+                               else {
+                                       val = Location;
+                                       return Token.MINUS;
+                               }
+                               doread = true;
+                               return t;
+                       }
+
+                       if (c == '!'){
+                               if (d == '='){
+                                       doread = true;
+                                       return Token.OP_NE;
+                               }
+                               val = Location;
+                               return Token.BANG;
+                       }
+
+                       if (c == '='){
+                               if (d == '='){
+                                       doread = true;
+                                       return Token.OP_EQ;
+                               }
+                               return Token.ASSIGN;
+                       }
+
+                       if (c == '&'){
+                               if (d == '&'){
+                                       doread = true;
+                                       return Token.OP_AND;
+                               } else if (d == '='){
+                                       doread = true;
+                                       return Token.OP_AND_ASSIGN;
+                               }
+                               val = Location;
+                               return Token.BITWISE_AND;
+                       }
+
+                       if (c == '|'){
+                               if (d == '|'){
+                                       doread = true;
+                                       return Token.OP_OR;
+                               } else if (d == '='){
+                                       doread = true;
+                                       return Token.OP_OR_ASSIGN;
+                               }
+                               return Token.BITWISE_OR;
+                       }
+
+                       if (c == '*'){
+                               if (d == '='){
+                                       doread = true;
+                                       return Token.OP_MULT_ASSIGN;
+                               }
+                               val = Location;
+                               return Token.STAR;
+                       }
+
+                       if (c == '/'){
+                               if (d == '='){
+                                       doread = true;
+                                       return Token.OP_DIV_ASSIGN;
+                               }
+                               return Token.DIV;
+                       }
+
+                       if (c == '%'){
+                               if (d == '='){
+                                       doread = true;
+                                       return Token.OP_MOD_ASSIGN;
+                               }
+                               return Token.PERCENT;
+                       }
+
+                       if (c == '^'){
+                               if (d == '='){
+                                       doread = true;
+                                       return Token.OP_XOR_ASSIGN;
+                               }
+                               return Token.CARRET;
+                       }
+
+#if !GMCS_SOURCE
+                       if (c == '<'){
+                               if (d == '<'){
+                                       getChar ();
+                                       d = peekChar ();
+
+                                       if (d == '='){
+                                               doread = true;
+                                               return Token.OP_SHIFT_LEFT_ASSIGN;
+                                       }
+                                       return Token.OP_SHIFT_LEFT;
+                               } else if (d == '='){
+                                       doread = true;
+                                       return Token.OP_LE;
+                               }
+                               return Token.OP_LT;
+                       }
+
+                       if (c == '>'){
+                               if (d == '>'){
+                                       getChar ();
+                                       d = peekChar ();
+
+                                       if (d == '='){
+                                               doread = true;
+                                               return Token.OP_SHIFT_RIGHT_ASSIGN;
+                                       }
+                                       return Token.OP_SHIFT_RIGHT;
+                               } else if (d == '='){
+                                       doread = true;
+                                       return Token.OP_GE;
+                               }
+                               return Token.OP_GT;
+                       }
+#endif
+                       if (c == ':'){
+                               if (d == ':'){
+                                       doread = true;
+                                       return Token.DOUBLE_COLON;
+                               }
+                               val = Location;
+                               return Token.COLON;
+                       }
+
+                       return Token.ERROR;
+               }
+
+               int deambiguate_close_parens = 0;
+
+               public void Deambiguate_CloseParens (object expression)
+               {
+                       putback (')');
+
+                       // When any binary operation is used we are sure it is not a cast
+                       if (expression is Binary)
+                               return;
+
+                       deambiguate_close_parens++;
+               }
+
+               bool decimal_digits (int c)
+               {
+                       int d;
+                       bool seen_digits = false;
+                       
+                       if (c != -1){
+                               if (number_pos == max_number_size)
+                                       Error_NumericConstantTooLong ();
+                               number_builder [number_pos++] = (char) c;
+                       }
+                       
+                       //
+                       // We use peekChar2, because decimal_digits needs to do a 
+                       // 2-character look-ahead (5.ToString for example).
+                       //
+                       while ((d = peekChar2 ()) != -1){
+                               if (d >= '0' && d <= '9'){
+                                       if (number_pos == max_number_size)
+                                               Error_NumericConstantTooLong ();
+                                       number_builder [number_pos++] = (char) d;
+                                       getChar ();
+                                       seen_digits = true;
+                               } else
+                                       break;
+                       }
+                       
+                       return seen_digits;
+               }
+
+               static bool is_hex (int e)
+               {
+                       return (e >= '0' && e <= '9') || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f');
+               }
+                               
+               static int real_type_suffix (int c)
+               {
+                       int t;
+
+                       switch (c){
+                       case 'F': case 'f':
+                               t =  Token.LITERAL_FLOAT;
+                               break;
+                       case 'D': case 'd':
+                               t = Token.LITERAL_DOUBLE;
+                               break;
+                       case 'M': case 'm':
+                                t= Token.LITERAL_DECIMAL;
+                               break;
+                       default:
+                               return Token.NONE;
+                       }
+                       return t;
+               }
+
+               int integer_type_suffix (ulong ul, int c)
+               {
+                       bool is_unsigned = false;
+                       bool is_long = false;
+
+                       if (c != -1){
+                               bool scanning = true;
+                               do {
+                                       switch (c){
+                                       case 'U': case 'u':
+                                               if (is_unsigned)
+                                                       scanning = false;
+                                               is_unsigned = true;
+                                               getChar ();
+                                               break;
+
+                                       case 'l':
+                                               if (!is_unsigned && (RootContext.WarningLevel >= 4)){
+                                                       //
+                                                       // if we have not seen anything in between
+                                                       // report this error
+                                                       //
+                                                       Report.Warning (78, 4, Location, "The 'l' suffix is easily confused with the digit '1' (use 'L' for clarity)");
+                                               }
+                                               //
+                                               // This goto statement causes the MS CLR 2.0 beta 1 csc to report an error, so
+                                               // work around that.
+                                               //
+                                               //goto case 'L';
+                                               if (is_long)
+                                                       scanning = false;
+                                               is_long = true;
+                                               getChar ();
+                                               break;
+
+                                       case 'L': 
+                                               if (is_long)
+                                                       scanning = false;
+                                               is_long = true;
+                                               getChar ();
+                                               break;
+                                               
+                                       default:
+                                               scanning = false;
+                                               break;
+                                       }
+                                       c = peekChar ();
+                               } while (scanning);
+                       }
+
+                       if (is_long && is_unsigned){
+                               val = ul;
+                               return Token.LITERAL_INTEGER;
+                       } else if (is_unsigned){
+                               // uint if possible, or ulong else.
+
+                               if ((ul & 0xffffffff00000000) == 0)
+                                       val = (uint) ul;
+                               else
+                                       val = ul;
+                       } else if (is_long){
+                               // long if possible, ulong otherwise
+                               if ((ul & 0x8000000000000000) != 0)
+                                       val = ul;
+                               else
+                                       val = (long) ul;
+                       } else {
+                               // int, uint, long or ulong in that order
+                               if ((ul & 0xffffffff00000000) == 0){
+                                       uint ui = (uint) ul;
+                                       
+                                       if ((ui & 0x80000000) != 0)
+                                               val = ui;
+                                       else
+                                               val = (int) ui;
+                               } else {
+                                       if ((ul & 0x8000000000000000) != 0)
+                                               val = ul;
+                                       else
+                                               val = (long) ul;
+                               }
+                       }
+                       return Token.LITERAL_INTEGER;
+               }
+                               
+               //
+               // given `c' as the next char in the input decide whether
+               // we need to convert to a special type, and then choose
+               // the best representation for the integer
+               //
+               int adjust_int (int c)
+               {
+                       try {
+                               if (number_pos > 9){
+                                       ulong ul = (uint) (number_builder [0] - '0');
+
+                                       for (int i = 1; i < number_pos; i++){
+                                               ul = checked ((ul * 10) + ((uint)(number_builder [i] - '0')));
+                                       }
+                                       return integer_type_suffix (ul, c);
+                               } else {
+                                       uint ui = (uint) (number_builder [0] - '0');
+
+                                       for (int i = 1; i < number_pos; i++){
+                                               ui = checked ((ui * 10) + ((uint)(number_builder [i] - '0')));
+                                       }
+                                       return integer_type_suffix (ui, c);
+                               }
+                       } catch (OverflowException) {
+                               error_details = "Integral constant is too large";
+                               Report.Error (1021, Location, error_details);
+                               val = 0ul;
+                               return Token.LITERAL_INTEGER;
+                       }
+                       catch (FormatException) {
+                               Report.Error (1013, Location, "Invalid number");
+                               val = 0ul;
+                               return Token.LITERAL_INTEGER;
+                       }
+               }
+               
+               int adjust_real (int t)
+               {
+                       string s = new String (number_builder, 0, number_pos);
+                       const string error_details = "Floating-point constant is outside the range of type `{0}'";
+
+                       switch (t){
+                       case Token.LITERAL_DECIMAL:
+                               try {
+                                       val = System.Decimal.Parse (s, styles, csharp_format_info);
+                               } catch (OverflowException) {
+                                       val = 0m;     
+                                       Report.Error (594, Location, error_details, "decimal");
+                               }
+                               break;
+                       case Token.LITERAL_FLOAT:
+                               try {
+                                       val = float.Parse (s, styles, csharp_format_info);
+                               } catch (OverflowException) {
+                                       val = 0.0f;     
+                                       Report.Error (594, Location, error_details, "float");
+                               }
+                               break;
+                               
+                       case Token.LITERAL_DOUBLE:
+                       case Token.NONE:
+                               t = Token.LITERAL_DOUBLE;
+                               try {
+                                       val = System.Double.Parse (s, styles, csharp_format_info);
+                               } catch (OverflowException) {
+                                       val = 0.0;     
+                                       Report.Error (594, Location, error_details, "double");
+                               }
+                               break;
+                       }
+                       return t;
+               }
+
+               int handle_hex ()
+               {
+                       int d;
+                       ulong ul;
+                       
+                       getChar ();
+                       while ((d = peekChar ()) != -1){
+                               if (is_hex (d)){
+                                       number_builder [number_pos++] = (char) d;
+                                       getChar ();
+                               } else
+                                       break;
+                       }
+                       
+                       string s = new String (number_builder, 0, number_pos);
+                       try {
+                               if (number_pos <= 8)
+                                       ul = System.UInt32.Parse (s, NumberStyles.HexNumber);
+                               else
+                                       ul = System.UInt64.Parse (s, NumberStyles.HexNumber);
+                       } catch (OverflowException){
+                               error_details = "Integral constant is too large";
+                               Report.Error (1021, Location, error_details);
+                               val = 0ul;
+                               return Token.LITERAL_INTEGER;
+                       }
+                       catch (FormatException) {
+                               Report.Error (1013, Location, "Invalid number");
+                               val = 0ul;
+                               return Token.LITERAL_INTEGER;
+                       }
+                       
+                       return integer_type_suffix (ul, peekChar ());
+               }
+
+               //
+               // Invoked if we know we have .digits or digits
+               //
+               int is_number (int c)
+               {
+                       bool is_real = false;
+                       int type;
+
+                       number_pos = 0;
+
+                       if (c >= '0' && c <= '9'){
+                               if (c == '0'){
+                                       int peek = peekChar ();
+
+                                       if (peek == 'x' || peek == 'X')
+                                               return handle_hex ();
+                               }
+                               decimal_digits (c);
+                               c = getChar ();
+                       }
+
+                       //
+                       // We need to handle the case of
+                       // "1.1" vs "1.string" (LITERAL_FLOAT vs NUMBER DOT IDENTIFIER)
+                       //
+                       if (c == '.'){
+                               if (decimal_digits ('.')){
+                                       is_real = true;
+                                       c = getChar ();
+                               } else {
+                                       putback ('.');
+                                       number_pos--;
+                                       return adjust_int (-1);
+                               }
+                       }
+                       
+                       if (c == 'e' || c == 'E'){
+                               is_real = true;
+                               if (number_pos == max_number_size)
+                                       Error_NumericConstantTooLong ();
+                               number_builder [number_pos++] = 'e';
+                               c = getChar ();
+                               
+                               if (c == '+'){
+                                       if (number_pos == max_number_size)
+                                               Error_NumericConstantTooLong ();
+                                       number_builder [number_pos++] = '+';
+                                       c = -1;
+                               } else if (c == '-') {
+                                       if (number_pos == max_number_size)
+                                               Error_NumericConstantTooLong ();
+                                       number_builder [number_pos++] = '-';
+                                       c = -1;
+                               } else {
+                                       if (number_pos == max_number_size)
+                                               Error_NumericConstantTooLong ();
+                                       number_builder [number_pos++] = '+';
+                               }
+                                       
+                               decimal_digits (c);
+                               c = getChar ();
+                       }
+
+                       type = real_type_suffix (c);
+                       if (type == Token.NONE && !is_real){
+                               putback (c);
+                               return adjust_int (c);
+                       } else 
+                               is_real = true;
+
+                       if (type == Token.NONE){
+                               putback (c);
+                       }
+                       
+                       if (is_real)
+                               return adjust_real (type);
+
+                       Console.WriteLine ("This should not be reached");
+                       throw new Exception ("Is Number should never reach this point");
+               }
+
+               //
+               // Accepts exactly count (4 or 8) hex, no more no less
+               //
+               int getHex (int count, out bool error)
+               {
+                       int i;
+                       int total = 0;
+                       int c;
+                       int top = count != -1 ? count : 4;
+                       
+                       getChar ();
+                       error = false;
+                       for (i = 0; i < top; i++){
+                               c = getChar ();
+                               
+                               if (c >= '0' && c <= '9')
+                                       c = (int) c - (int) '0';
+                               else if (c >= 'A' && c <= 'F')
+                                       c = (int) c - (int) 'A' + 10;
+                               else if (c >= 'a' && c <= 'f')
+                                       c = (int) c - (int) 'a' + 10;
+                               else {
+                                       error = true;
+                                       return 0;
+                               }
+                               
+                               total = (total * 16) + c;
+                               if (count == -1){
+                                       int p = peekChar ();
+                                       if (p == -1)
+                                               break;
+                                       if (!is_hex ((char)p))
+                                               break;
+                               }
+                       }
+                       return total;
+               }
+
+               int escape (int c)
+               {
+                       bool error;
+                       int d;
+                       int v;
+
+                       d = peekChar ();
+                       if (c != '\\')
+                               return c;
+                       
+                       switch (d){
+                       case 'a':
+                               v = '\a'; break;
+                       case 'b':
+                               v = '\b'; break;
+                       case 'n':
+                               v = '\n'; break;
+                       case 't':
+                               v = '\t'; break;
+                       case 'v':
+                               v = '\v'; break;
+                       case 'r':
+                               v = '\r'; break;
+                       case '\\':
+                               v = '\\'; break;
+                       case 'f':
+                               v = '\f'; break;
+                       case '0':
+                               v = 0; break;
+                       case '"':
+                               v = '"'; break;
+                       case '\'':
+                               v = '\''; break;
+                       case 'x':
+                               v = getHex (-1, out error);
+                               if (error)
+                                       goto default;
+                               return v;
+                       case 'u':
+                               v = getHex (4, out error);
+                               if (error)
+                                       goto default;
+                               return v;
+                       case 'U':
+                               v = getHex (8, out error);
+                               if (error)
+                                       goto default;
+                               return v;
+                       default:
+                               Report.Error (1009, Location, "Unrecognized escape sequence `\\{0}'", ((char)d).ToString ());
+                               return d;
+                       }
+                       getChar ();
+                       return v;
+               }
+
+               int getChar ()
+               {
+                       int x;
+                       if (putback_char != -1) {
+                               x = putback_char;
+                               putback_char = -1;
+                       } else
+                               x = reader.Read ();
+                       if (x == '\n') {
+                               line++;
+                               ref_line++;
+                               previous_col = col;
+                               col = 0;
+                       }
+                       else
+                               col++;
+                       return x;
+               }
+
+               int peekChar ()
+               {
+                       if (putback_char != -1)
+                               return putback_char;
+                       putback_char = reader.Read ();
+                       return putback_char;
+               }
+
+               int peekChar2 ()
+               {
+                       if (putback_char != -1)
+                               return putback_char;
+                       return reader.Peek ();
+               }
+               
+               void putback (int c)
+               {
+                       if (putback_char != -1){
+                               Console.WriteLine ("Col: " + col);
+                               Console.WriteLine ("Row: " + line);
+                               Console.WriteLine ("Name: " + ref_name.Name);
+                               Console.WriteLine ("Current [{0}] putting back [{1}]  ", putback_char, c);
+                               throw new Exception ("This should not happen putback on putback");
+                       }
+                       if (c == '\n' || col == 0) {
+                               // It won't happen though.
+                               line--;
+                               ref_line--;
+                               col = previous_col;
+                       }
+                       else
+                               col--;
+                       putback_char = c;
+               }
+
+               public bool advance ()
+               {
+                       return peekChar () != -1;
+               }
+
+               public Object Value {
+                       get {
+                               return val;
+                       }
+               }
+
+               public Object value ()
+               {
+                       return val;
+               }
+
+               static bool IsCastToken (int token)
+               {
+                       switch (token) {
+                       case Token.BANG:
+                       case Token.TILDE:
+                       case Token.IDENTIFIER:
+                       case Token.LITERAL_INTEGER:
+                       case Token.LITERAL_FLOAT:
+                       case Token.LITERAL_DOUBLE:
+                       case Token.LITERAL_DECIMAL:
+                       case Token.LITERAL_CHARACTER:
+                       case Token.LITERAL_STRING:
+                       case Token.BASE:
+                       case Token.CHECKED:
+                       case Token.DELEGATE:
+                       case Token.FALSE:
+                       case Token.FIXED:
+                       case Token.NEW:
+                       case Token.NULL:
+                       case Token.SIZEOF:
+                       case Token.THIS:
+                       case Token.THROW:
+                       case Token.TRUE:
+                       case Token.TYPEOF:
+                       case Token.UNCHECKED:
+                       case Token.UNSAFE:
+#if GMCS_SOURCE
+                       case Token.DEFAULT:
+#endif
+
+                               //
+                               // These can be part of a member access
+                               //
+                       case Token.INT:
+                       case Token.UINT:
+                       case Token.SHORT:
+                       case Token.USHORT:
+                       case Token.LONG:
+                       case Token.ULONG:
+                       case Token.DOUBLE:
+                       case Token.FLOAT:
+                       case Token.CHAR:
+                               return true;
+
+                       default:
+                               return false;
+                       }
+               }
+
+               public int token ()
+               {
+                       current_token = xtoken ();
+
+#if GMCS_SOURCE
+                       if (current_token != Token.DEFAULT)
+                               return current_token;
+
+                       PushPosition();
+                       int c = xtoken();
+                       if (c == -1)
+                               current_token = Token.ERROR;
+                       else if (c == Token.OPEN_PARENS)
+                               current_token = Token.DEFAULT_OPEN_PARENS;
+                       else if (c == Token.COLON)
+                               current_token = Token.DEFAULT_COLON;
+                       else
+                               PopPosition();
+#endif
+                       return current_token;
+               }
+
+               static StringBuilder static_cmd_arg = new System.Text.StringBuilder ();
+               
+               void get_cmd_arg (out string cmd, out string arg)
+               {
+                       int c;
+                       
+                       tokens_seen = false;
+                       arg = "";
+                       static_cmd_arg.Length = 0;
+
+                       // skip over white space
+                       while ((c = getChar ()) != -1 && (c != '\n') && ((c == '\r') || (c == ' ') || (c == '\t')))
+                               ;
+                               
+                       while ((c != -1) && (c != '\n') && (c != ' ') && (c != '\t') && (c != '\r')){
+                               if (is_identifier_part_character ((char) c)){
+                                       static_cmd_arg.Append ((char) c);
+                                       c = getChar ();
+                               } else {
+                                       putback (c);
+                                       break;
+                               }
+                       }
+
+                       cmd = static_cmd_arg.ToString ();
+
+                       if (c == '\n'){
+                               return;
+                       }
+
+                       // skip over white space
+                       while ((c = getChar ()) != -1 && (c != '\n') && ((c == '\r') || (c == ' ') || (c == '\t')))
+                               ;
+
+                       if (c == '\n'){
+                               return;
+                       } else if (c == '\r'){
+                               return;
+                       } else if (c == -1){
+                               arg = "";
+                               return;
+                       }
+                       
+                       static_cmd_arg.Length = 0;
+                       static_cmd_arg.Append ((char) c);
+                       
+                       while ((c = getChar ()) != -1 && (c != '\n') && (c != '\r')){
+                               static_cmd_arg.Append ((char) c);
+                       }
+
+                       arg = static_cmd_arg.ToString ().Trim ();
+               }
+
+               //
+               // Handles the #line directive
+               //
+               bool PreProcessLine (string arg)
+               {
+                       if (arg.Length == 0)
+                               return false;
+
+                       if (arg == "default"){
+                               ref_line = line;
+                               ref_name = file_name;
+                               Location.Push (ref_name);
+                               return true;
+                       } else if (arg == "hidden"){
+                               //
+                               // We ignore #line hidden
+                               //
+                               return true;
+                       }
+                       
+                       try {
+                               int pos;
+
+                               if ((pos = arg.IndexOf (' ')) != -1 && pos != 0){
+                                       ref_line = System.Int32.Parse (arg.Substring (0, pos));
+                                       pos++;
+                                       
+                                       char [] quotes = { '\"' };
+                                       
+                                       string name = arg.Substring (pos). Trim (quotes);
+                                       ref_name = Location.LookupFile (name);
+                                       file_name.HasLineDirective = true;
+                                       ref_name.HasLineDirective = true;
+                                       Location.Push (ref_name);
+                               } else {
+                                       ref_line = System.Int32.Parse (arg);
+                               }
+                       } catch {
+                               return false;
+                       }
+                       
+                       return true;
+               }
+
+               //
+               // Handles #define and #undef
+               //
+               void PreProcessDefinition (bool is_define, string arg)
+               {
+                       if (arg.Length == 0 || arg == "true" || arg == "false"){
+                               Report.Error (1001, Location, "Missing identifer to pre-processor directive");
+                               return;
+                       }
+
+                       char[] whitespace = { ' ', '\t' };
+                       if (arg.IndexOfAny (whitespace) != -1){
+                               Report.Error (1025, Location, "Single-line comment or end-of-line expected");
+                               return;
+                       }
+
+                       if (!is_identifier_start_character (arg [0]))
+                               Report.Error (1001, Location, "Identifier expected: " + arg);
+                       
+                       foreach (char c in arg.Substring (1)){
+                               if (!is_identifier_part_character (c)){
+                                       Report.Error (1001, Location, "Identifier expected: " + arg);
+                                       return;
+                               }
+                       }
+
+                       if (is_define){
+                               if (defines == null)
+                                       defines = new Hashtable ();
+                               define (arg);
+                       } else {
+                               if (defines == null)
+                                       return;
+                               if (defines.Contains (arg))
+                                       defines.Remove (arg);
+                       }
+               }
+
+               /// <summary>
+               /// Handles #pragma directive
+               /// </summary>
+               void PreProcessPragma (string arg)
+               {
+                       const string warning = "warning";
+                       const string w_disable = "warning disable";
+                       const string w_restore = "warning restore";
+
+                       if (arg == w_disable) {
+                               Report.RegisterWarningRegion (Location).WarningDisable (line);
+                               return;
+                       }
+
+                       if (arg == w_restore) {
+                               Report.RegisterWarningRegion (Location).WarningEnable (line);
+                               return;
+                       }
+
+                       if (arg.StartsWith (w_disable)) {
+                               int[] codes = ParseNumbers (arg.Substring (w_disable.Length));
+                               foreach (int code in codes) {
+                                       if (code != 0)
+                                               Report.RegisterWarningRegion (Location).WarningDisable (Location, code);
+                               }
+                               return;
+                       }
+
+                       if (arg.StartsWith (w_restore)) {
+                               int[] codes = ParseNumbers (arg.Substring (w_restore.Length));
+                               Hashtable w_table = Report.warning_ignore_table;
+                               foreach (int code in codes) {
+                                       if (w_table != null && w_table.Contains (code))
+                                               Report.Warning (1635, 1, Location, String.Format ("Cannot restore warning `CS{0:0000}' because it was disabled globally", code));
+                                       Report.RegisterWarningRegion (Location).WarningEnable (Location, code);
+                               }
+                               return;
+                       }
+
+                       if (arg.StartsWith (warning)) {
+                               Report.Warning (1634, 1, Location, "Expected disable or restore");
+                               return;
+                       }
+
+                       Report.Warning (1633, 1, Location, "Unrecognized #pragma directive");
+               }
+
+               int[] ParseNumbers (string text)
+               {
+                       string[] string_array = text.Split (',');
+                       int[] values = new int [string_array.Length];
+                       int index = 0;
+                       foreach (string string_code in string_array) {
+                               try {
+                                       values[index++] = int.Parse (string_code, System.Globalization.CultureInfo.InvariantCulture);
+                               }
+                               catch (FormatException) {
+                                       Report.Warning (1692, 1, Location, "Invalid number");
+                               }
+                       }
+                       return values;
+               }
+
+               bool eval_val (string s)
+               {
+                       if (s == "true")
+                               return true;
+                       if (s == "false")
+                               return false;
+                       
+                       if (defines == null)
+                               return false;
+                       if (defines.Contains (s))
+                               return true;
+
+                       return false;
+               }
+
+               bool pp_primary (ref string s)
+               {
+                       s = s.Trim ();
+                       int len = s.Length;
+
+                       if (len > 0){
+                               char c = s [0];
+                               
+                               if (c == '('){
+                                       s = s.Substring (1);
+                                       bool val = pp_expr (ref s);
+                                       if (s.Length > 0 && s [0] == ')'){
+                                               s = s.Substring (1);
+                                               return val;
+                                       }
+                                       Error_InvalidDirective ();
+                                       return false;
+                               }
+                               
+                               if (is_identifier_start_character (c)){
+                                       int j = 1;
+
+                                       while (j < len){
+                                               c = s [j];
+                                               
+                                               if (is_identifier_part_character (c)){
+                                                       j++;
+                                                       continue;
+                                               }
+                                               bool v = eval_val (s.Substring (0, j));
+                                               s = s.Substring (j);
+                                               return v;
+                                       }
+                                       bool vv = eval_val (s);
+                                       s = "";
+                                       return vv;
+                               }
+                       }
+                       Error_InvalidDirective ();
+                       return false;
+               }
+               
+               bool pp_unary (ref string s)
+               {
+                       s = s.Trim ();
+                       int len = s.Length;
+
+                       if (len > 0){
+                               if (s [0] == '!'){
+                                       if (len > 1 && s [1] == '='){
+                                               Error_InvalidDirective ();
+                                               return false;
+                                       }
+                                       s = s.Substring (1);
+                                       return ! pp_primary (ref s);
+                               } else
+                                       return pp_primary (ref s);
+                       } else {
+                               Error_InvalidDirective ();
+                               return false;
+                       }
+               }
+               
+               bool pp_eq (ref string s)
+               {
+                       bool va = pp_unary (ref s);
+
+                       s = s.Trim ();
+                       int len = s.Length;
+                       if (len > 0){
+                               if (s [0] == '='){
+                                       if (len > 2 && s [1] == '='){
+                                               s = s.Substring (2);
+                                               return va == pp_unary (ref s);
+                                       } else {
+                                               Error_InvalidDirective ();
+                                               return false;
+                                       }
+                               } else if (s [0] == '!' && len > 1 && s [1] == '='){
+                                       s = s.Substring (2);
+
+                                       return va != pp_unary (ref s);
+
+                               } 
+                       }
+
+                       return va;
+                               
+               }
+               
+               bool pp_and (ref string s)
+               {
+                       bool va = pp_eq (ref s);
+
+                       s = s.Trim ();
+                       int len = s.Length;
+                       if (len > 0){
+                               if (s [0] == '&'){
+                                       if (len > 2 && s [1] == '&'){
+                                               s = s.Substring (2);
+                                               return (va & pp_and (ref s));
+                                       } else {
+                                               Error_InvalidDirective ();
+                                               return false;
+                                       }
+                               } 
+                       }
+                       return va;
+               }
+               
+               //
+               // Evaluates an expression for `#if' or `#elif'
+               //
+               bool pp_expr (ref string s)
+               {
+                       bool va = pp_and (ref s);
+                       s = s.Trim ();
+                       int len = s.Length;
+                       if (len > 0){
+                               char c = s [0];
+                               
+                               if (c == '|'){
+                                       if (len > 2 && s [1] == '|'){
+                                               s = s.Substring (2);
+                                               return va | pp_expr (ref s);
+                                       } else {
+                                               Error_InvalidDirective ();
+                                               return false;
+                                       }
+                               } 
+                       }
+                       
+                       return va;
+               }
+
+               bool eval (string s)
+               {
+                       bool v = pp_expr (ref s);
+                       s = s.Trim ();
+                       if (s.Length != 0){
+                               return false;
+                       }
+
+                       return v;
+               }
+
+               void Error_NumericConstantTooLong ()
+               {
+                       Report.Error (1021, Location, "Numeric constant too long");                     
+               }
+               
+               void Error_InvalidDirective ()
+               {
+                       Report.Error (1517, Location, "Invalid preprocessor directive");
+               }
+
+               void Error_UnexpectedDirective (string extra)
+               {
+                       Report.Error (
+                               1028, Location,
+                               "Unexpected processor directive (" + extra + ")");
+               }
+
+               void Error_TokensSeen ()
+               {
+                       Report.Error (1032, Location,
+                               "Cannot define or undefine preprocessor symbols after first token in file");
+               }
+               
+               //
+               // Set to false to stop handling preprocesser directives
+               // 
+               bool process_directives = true;
+
+               //
+               // if true, then the code continues processing the code
+               // if false, the code stays in a loop until another directive is
+               // reached.
+               //
+               bool handle_preprocessing_directive (bool caller_is_taking)
+               {
+                       string cmd, arg;
+                       bool region_directive = false;
+
+                       get_cmd_arg (out cmd, out arg);
+
+                       // Eat any trailing whitespaces and single-line comments
+                       if (arg.IndexOf ("//") != -1)
+                               arg = arg.Substring (0, arg.IndexOf ("//"));
+                       arg = arg.TrimEnd (' ', '\t');
+
+                       //
+                       // The first group of pre-processing instructions is always processed
+                       //
+                       switch (cmd){
+                       case "pragma":
+                               if (RootContext.Version == LanguageVersion.ISO_1) {
+                                       Report.FeatureIsNotStandardized (Location, "#pragma");
+                                       return caller_is_taking;
+                               }
+
+                               PreProcessPragma (arg);
+                               return caller_is_taking;
+
+                       case "line":
+                               if (!PreProcessLine (arg))
+                                       Report.Error (
+                                               1576, Location,
+                                               "The line number specified for #line directive is missing or invalid");
+                               return caller_is_taking;
+
+                       case "region":
+                               region_directive = true;
+                               arg = "true";
+                               goto case "if";
+
+                       case "endregion":
+                               region_directive = true;
+                               goto case "endif";
+                               
+                       case "if":
+                               if (arg.Length == 0){
+                                       Error_InvalidDirective ();
+                                       return true;
+                               }
+                               bool taking = false;
+                               if (ifstack == null)
+                                       ifstack = new Stack (2);
+
+                               if (ifstack.Count == 0){
+                                       taking = true;
+                               } else {
+                                       int state = (int) ifstack.Peek ();
+                                       if ((state & TAKING) != 0)
+                                               taking = true;
+                               }
+
+                               if (eval (arg) && taking){
+                                       int push = TAKING | TAKEN_BEFORE | PARENT_TAKING;
+                                       if (region_directive)
+                                               push |= REGION;
+                                       ifstack.Push (push);
+                                       return true;
+                               } else {
+                                       int push = (taking ? PARENT_TAKING : 0);
+                                       if (region_directive)
+                                               push |= REGION;
+                                       ifstack.Push (push);
+                                       return false;
+                               }
+                               
+                       case "endif":
+                               if (ifstack == null || ifstack.Count == 0){
+                                       Error_UnexpectedDirective ("no #if for this #endif");
+                                       return true;
+                               } else {
+                                       int pop = (int) ifstack.Pop ();
+                                       
+                                       if (region_directive && ((pop & REGION) == 0))
+                                               Report.Error (1027, Location, "Expected `#endif' directive");
+                                       else if (!region_directive && ((pop & REGION) != 0))
+                                               Report.Error (1038, Location, "#endregion directive expected");
+                                       
+                                       if (!region_directive && arg.Length != 0) {
+                                               Report.Error (1025, Location, "Single-line comment or end-of-line expected");
+                                       }
+                                       
+                                       if (ifstack.Count == 0)
+                                               return true;
+                                       else {
+                                               int state = (int) ifstack.Peek ();
+
+                                               if ((state & TAKING) != 0)
+                                                       return true;
+                                               else
+                                                       return false;
+                                       }
+                               }
+
+                       case "elif":
+                               if (ifstack == null || ifstack.Count == 0){
+                                       Error_UnexpectedDirective ("no #if for this #elif");
+                                       return true;
+                               } else {
+                                       int state = (int) ifstack.Peek ();
+
+                                       if ((state & REGION) != 0) {
+                                               Report.Error (1038, Location, "#endregion directive expected");
+                                               return true;
+                                       }
+
+                                       if ((state & ELSE_SEEN) != 0){
+                                               Error_UnexpectedDirective ("#elif not valid after #else");
+                                               return true;
+                                       }
+
+                                       if ((state & (TAKEN_BEFORE | TAKING)) != 0)
+                                               return false;
+
+                                       if (eval (arg) && ((state & PARENT_TAKING) != 0)){
+                                               state = (int) ifstack.Pop ();
+                                               ifstack.Push (state | TAKING | TAKEN_BEFORE);
+                                               return true;
+                                       } else 
+                                               return false;
+                               }
+
+                       case "else":
+                               if (ifstack == null || ifstack.Count == 0){
+                                       Error_UnexpectedDirective ("no #if for this #else");
+                                       return true;
+                               } else {
+                                       int state = (int) ifstack.Peek ();
+
+                                       if ((state & REGION) != 0) {
+                                               Report.Error (1038, Location, "#endregion directive expected");
+                                               return true;
+                                       }
+
+                                       if ((state & ELSE_SEEN) != 0){
+                                               Error_UnexpectedDirective ("#else within #else");
+                                               return true;
+                                       }
+
+                                       ifstack.Pop ();
+
+                                       bool ret;
+                                       if ((state & TAKEN_BEFORE) == 0){
+                                               ret = ((state & PARENT_TAKING) != 0);
+                                       } else
+                                               ret = false;
+                                       
+                                       if (ret)
+                                               state |= TAKING;
+                                       else
+                                               state &= ~TAKING;
+                                       
+                                       ifstack.Push (state | ELSE_SEEN);
+                                       
+                                       return ret;
+                               }
+                       }
+
+                       //
+                       // These are only processed if we are in a `taking' block
+                       //
+                       if (!caller_is_taking)
+                               return false;
+                                       
+                       switch (cmd){
+                       case "define":
+                               if (any_token_seen){
+                                       Error_TokensSeen ();
+                                       return true;
+                               }
+                               PreProcessDefinition (true, arg);
+                               return true;
+
+                       case "undef":
+                               if (any_token_seen){
+                                       Error_TokensSeen ();
+                                       return true;
+                               }
+                               PreProcessDefinition (false, arg);
+                               return true;
+
+                       case "error":
+                               Report.Error (1029, Location, "#error: '" + arg + "'");
+                               return true;
+
+                       case "warning":
+                               Report.Warning (1030, 1, Location, "#warning: `{0}'", arg);
+                               return true;
+                       }
+
+                       Report.Error (1024, Location, "Wrong preprocessor directive");
+                       return true;
+
+               }
+
+               private int consume_string (bool quoted)
+               {
+                       int c;
+                       string_builder.Length = 0;
+                                                               
+                       while ((c = getChar ()) != -1){
+                               if (c == '"'){
+                                       if (quoted && peekChar () == '"'){
+                                               string_builder.Append ((char) c);
+                                               getChar ();
+                                               continue;
+                                       } else {
+                                               val = string_builder.ToString ();
+                                               return Token.LITERAL_STRING;
+                                       }
+                               }
+
+                               if (c == '\n'){
+                                       if (!quoted)
+                                               Report.Error (1010, Location, "Newline in constant");
+                               }
+
+                               if (!quoted){
+                                       c = escape (c);
+                                       if (c == -1)
+                                               return Token.ERROR;
+                               }
+                               string_builder.Append ((char) c);
+                       }
+
+                       Report.Error (1039, Location, "Unterminated string literal");
+                       return Token.EOF;
+               }
+
+               private int consume_identifier (int s)
+               {
+                       int res = consume_identifier (s, false);
+
+                       if (doc_state == XmlCommentState.Allowed)
+                               doc_state = XmlCommentState.NotAllowed;
+                       switch (res) {
+                       case Token.USING:
+                       case Token.NAMESPACE:
+                               check_incorrect_doc_comment ();
+                               break;
+                       }
+
+                       if (res == Token.PARTIAL) {
+                               // Save current position and parse next token.
+                               PushPosition ();
+
+                               int next_token = token ();
+                               bool ok = (next_token == Token.CLASS) ||
+                                       (next_token == Token.STRUCT) ||
+                                       (next_token == Token.INTERFACE);
+
+                               PopPosition ();
+
+                               if (ok)
+                                       return res;
+
+//                             Report.Error (267, Location, "The `partial' modifier can be used only immediately before keyword `class', `struct', or `interface'");
+                               val = new LocatedToken (Location, "partial");
+                               return Token.IDENTIFIER;
+                       }
+
+                       return res;
+               }
+
+               private int consume_identifier (int s, bool quoted) 
+               {
+                       int pos = 1;
+                       int c = -1;
+                       
+                       id_builder [0] = (char) s;
+
+                       current_location = new Location (ref_line, Col);
+
+                       while ((c = getChar ()) != -1) {
+                       loop:
+                               if (is_identifier_part_character ((char) c)){
+                                       if (pos == max_id_size){
+                                               Report.Error (645, Location, "Identifier too long (limit is 512 chars)");
+                                               return Token.ERROR;
+                                       }
+                                       
+                                       id_builder [pos++] = (char) c;
+//                                     putback_char = -1;
+                               } else if (c == '\\') {
+                                       c = escape (c);
+                                       goto loop;
+                               } else {
+//                                     putback_char = c;
+                                       putback (c);
+                                       break;
+                               }
+                       }
+
+                       //
+                       // Optimization: avoids doing the keyword lookup
+                       // on uppercase letters and _
+                       //
+                       if (!quoted && (s >= 'a' || s == '_')){
+                               int keyword = GetKeyword (id_builder, pos);
+                               if (keyword != -1) {
+                                       val = Location;
+                                       return keyword;
+                               }
+                       }
+
+                       //
+                       // Keep identifiers in an array of hashtables to avoid needless
+                       // allocations
+                       //
+
+                       if (identifiers [pos] != null) {
+                               val = identifiers [pos][id_builder];
+                               if (val != null) {
+                                       val = new LocatedToken (Location, (string) val);
+                                       if (quoted)
+                                               escapedIdentifiers.Add (val);
+                                       return Token.IDENTIFIER;
+                               }
+                       }
+                       else
+                               identifiers [pos] = new CharArrayHashtable (pos);
+
+                       val = new String (id_builder, 0, pos);
+                       if (RootContext.Version == LanguageVersion.ISO_1) {
+                               for (int i = 1; i < id_builder.Length; i += 3) {
+                                       if (id_builder [i] == '_' && (id_builder [i - 1] == '_' || id_builder [i + 1] == '_')) {
+                                               Report.Error (1638, Location, 
+                                                       "`{0}': Any identifier with double underscores cannot be used when ISO language version mode is specified", val.ToString ());
+                                               break;
+                                       }
+                               }
+                       }
+
+                       char [] chars = new char [pos];
+                       Array.Copy (id_builder, chars, pos);
+
+                       identifiers [pos] [chars] = val;
+
+                       val = new LocatedToken (Location, (string) val);
+                       if (quoted)
+                               escapedIdentifiers.Add (val);
+                       return Token.IDENTIFIER;
+               }
+               
+               public int xtoken ()
+               {
+                       int t;
+                       bool doread = false;
+                       int c;
+
+                       // Whether we have seen comments on the current line
+                       bool comments_seen = false;
+                       
+                       val = null;
+                       // optimization: eliminate col and implement #directive semantic correctly.
+                       for (;(c = getChar ()) != -1;) {
+                               if (c == ' ')
+                                       continue;
+                               
+                               if (c == '\t') {
+                                       continue;
+                               }
+                               
+                               if (c == ' ' || c == '\f' || c == '\v' || c == 0xa0)
+                                       continue;
+
+                               if (c == '\r') {
+                                       if (peekChar () == '\n')
+                                               getChar ();
+
+                                       any_token_seen |= tokens_seen;
+                                       tokens_seen = false;
+                                       comments_seen = false;
+                                       continue;
+                               }
+
+                               // Handle double-slash comments.
+                               if (c == '/'){
+                                       int d = peekChar ();
+                               
+                                       if (d == '/'){
+                                               getChar ();
+                                               if (RootContext.Documentation != null && peekChar () == '/') {
+                                                       getChar ();
+                                                       // Don't allow ////.
+                                                       if ((d = peekChar ()) != '/') {
+                                                               update_comment_location ();
+                                                               if (doc_state == XmlCommentState.Allowed)
+                                                                       handle_one_line_xml_comment ();
+                                                               else if (doc_state == XmlCommentState.NotAllowed)
+                                                                       warn_incorrect_doc_comment ();
+                                                       }
+                                               }
+                                               while ((d = getChar ()) != -1 && (d != '\n') && d != '\r')
+                                               if (d == '\n'){
+                                               }
+                                               any_token_seen |= tokens_seen;
+                                               tokens_seen = false;
+                                               comments_seen = false;
+                                               continue;
+                                       } else if (d == '*'){
+                                               getChar ();
+                                               bool docAppend = false;
+                                               if (RootContext.Documentation != null && peekChar () == '*') {
+                                                       getChar ();
+                                                       update_comment_location ();
+                                                       // But when it is /**/, just do nothing.
+                                                       if (peekChar () == '/') {
+                                                               getChar ();
+                                                               continue;
+                                                       }
+                                                       if (doc_state == XmlCommentState.Allowed)
+                                                               docAppend = true;
+                                                       else if (doc_state == XmlCommentState.NotAllowed)
+                                                               warn_incorrect_doc_comment ();
+                                               }
+
+                                               int current_comment_start = 0;
+                                               if (docAppend) {
+                                                       current_comment_start = xml_comment_buffer.Length;
+                                                       xml_comment_buffer.Append (Environment.NewLine);
+                                               }
+
+                                               Location start_location = Location;
+
+                                               while ((d = getChar ()) != -1){
+                                                       if (d == '*' && peekChar () == '/'){
+                                                               getChar ();
+                                                               comments_seen = true;
+                                                               break;
+                                                       }
+                                                       if (docAppend)
+                                                               xml_comment_buffer.Append ((char) d);
+                                                       
+                                                       if (d == '\n'){
+                                                               any_token_seen |= tokens_seen;
+                                                               tokens_seen = false;
+                                                               // 
+                                                               // Reset 'comments_seen' just to be consistent.
+                                                               // It doesn't matter either way, here.
+                                                               //
+                                                               comments_seen = false;
+                                                       }
+                                               }
+                                               if (!comments_seen)
+                                                       Report.Error (1035, start_location, "End-of-file found, '*/' expected");
+
+                                               if (docAppend)
+                                                       update_formatted_doc_comment (current_comment_start);
+                                               continue;
+                                       }
+                                       goto is_punct_label;
+                               }
+
+                               
+                               if (c == '\\' || is_identifier_start_character ((char)c)){
+                                       tokens_seen = true;
+                                       return consume_identifier (c);
+                               }
+
+                       is_punct_label:
+                               current_location = new Location (ref_line, Col);
+                               if ((t = is_punct ((char)c, ref doread)) != Token.ERROR){
+                                       tokens_seen = true;
+                                       if (doread){
+                                               getChar ();
+                                       }
+                                       return t;
+                               }
+
+                               // white space
+                               if (c == '\n'){
+                                       any_token_seen |= tokens_seen;
+                                       tokens_seen = false;
+                                       comments_seen = false;
+                                       continue;
+                               }
+
+                               if (c >= '0' && c <= '9'){
+                                       tokens_seen = true;
+                                       return is_number (c);
+                               }
+
+                               if (c == '.'){
+                                       tokens_seen = true;
+                                       int peek = peekChar ();
+                                       if (peek >= '0' && peek <= '9')
+                                               return is_number (c);
+                                       return Token.DOT;
+                               }
+                               
+                               /* For now, ignore pre-processor commands */
+                               // FIXME: In C# the '#' is not limited to appear
+                               // on the first column.
+                               if (c == '#') {
+                                       // return NONE if we're not processing directives (during token peeks)
+                                       if (!process_directives)
+                                               return Token.NONE;
+
+                                       bool cont = true;
+                                       if (tokens_seen || comments_seen) {
+                                               error_details = "Preprocessor directives must appear as the first" +
+                                              " non-whitespace character on a line.";
+
+                                               Report.Error (1040, Location, error_details);
+
+                                               return Token.ERROR;
+                                       }
+                                       
+                               start_again:
+                                       
+                                       cont = handle_preprocessing_directive (cont);
+
+                                       if (cont){
+                                               continue;
+                                       }
+
+                                       bool skipping = false;
+                                       for (;(c = getChar ()) != -1;){
+                                               if (c == '\n'){
+                                                       skipping = false;
+                                               } else if (c == ' ' || c == '\t' || c == '\v' || c == '\r' || c == 0xa0)
+                                                       continue;
+                                               else if (c != '#')
+                                                       skipping = true;
+                                               if (c == '#' && !skipping)
+                                                       goto start_again;
+                                       }
+                                       any_token_seen |= tokens_seen;
+                                       tokens_seen = false;
+                                       if (c == -1)
+                                               Report.Error (1027, Location, "Expected `#endif' directive");
+                                       continue;
+                               }
+                               
+                               if (c == '"') 
+                                       return consume_string (false);
+
+                               if (c == '\''){
+                                       c = getChar ();
+                                       tokens_seen = true;
+                                       if (c == '\''){
+                                               error_details = "Empty character literal";
+                                               Report.Error (1011, Location, error_details);
+                                               return Token.ERROR;
+                                       }
+                                       if (c == '\r' || c == '\n') {
+                                               Report.Error (1010, Location, "Newline in constant");
+                                               return Token.ERROR;
+                                       }
+                                       c = escape (c);
+                                       if (c == -1)
+                                               return Token.ERROR;
+                                       val = new System.Char ();
+                                       val = (char) c;
+                                       c = getChar ();
+
+                                       if (c != '\''){
+                                               error_details = "Too many characters in character literal";
+                                               Report.Error (1012, Location, error_details);
+
+                                               // Try to recover, read until newline or next "'"
+                                               while ((c = getChar ()) != -1){
+                                                       if (c == '\n'){
+                                                               break;
+                                                       }
+                                                       else if (c == '\'')
+                                                               break;
+                                               }
+                                               return Token.ERROR;
+                                       }
+                                       return Token.LITERAL_CHARACTER;
+                               }
+                               
+                               if (c == '@') {
+                                       c = getChar ();
+                                       if (c == '"') {
+                                               tokens_seen = true;
+                                               return consume_string (true);
+                                       } else if (is_identifier_start_character ((char) c)){
+                                               return consume_identifier (c, true);
+                                       } else {
+                                               Report.Error (1646, Location, "Keyword, identifier, or string expected after verbatim specifier: @");
+                                       }
+                               }
+
+                               error_details = ((char)c).ToString ();
+                               
+                               return Token.ERROR;
+                       }
+
+                       return Token.EOF;
+               }
+
+               //
+               // Handles one line xml comment
+               //
+               private void handle_one_line_xml_comment ()
+               {
+                       int c;
+                       while ((c = peekChar ()) == ' ')
+                               getChar (); // skip heading whitespaces.
+                       while ((c = peekChar ()) != -1 && c != '\n' && c != '\r') {
+                               xml_comment_buffer.Append ((char) getChar ());
+                       }
+                       if (c == '\r' || c == '\n')
+                               xml_comment_buffer.Append (Environment.NewLine);
+               }
+
+               //
+               // Remove heading "*" in Javadoc-like xml documentation.
+               //
+               private void update_formatted_doc_comment (int current_comment_start)
+               {
+                       int length = xml_comment_buffer.Length - current_comment_start;
+                       string [] lines = xml_comment_buffer.ToString (
+                               current_comment_start,
+                               length).Replace ("\r", "").Split ('\n');
+                       
+                       // The first line starts with /**, thus it is not target
+                       // for the format check.
+                       for (int i = 1; i < lines.Length; i++) {
+                               string s = lines [i];
+                               int idx = s.IndexOf ('*');
+                               string head = null;
+                               if (idx < 0) {
+                                       if (i < lines.Length - 1)
+                                               return;
+                                       head = s;
+                               } else
+                                       head = s.Substring (0, idx);
+                               foreach (char c in head)
+                                       if (c != ' ')
+                                               return;
+                               lines [i] = s.Substring (idx + 1);
+                       }
+                       xml_comment_buffer.Remove (current_comment_start, length);
+                       xml_comment_buffer.Insert (current_comment_start, String.Join (Environment.NewLine, lines));
+               }
+
+               //
+               // Updates current comment location.
+               //
+               private void update_comment_location ()
+               {
+                       if (current_comment_location.IsNull) {
+                               // "-2" is for heading "//" or "/*"
+                               current_comment_location =
+                                       new Location (ref_line, col - 2);
+                       }
+               }
+
+               //
+               // Checks if there was incorrect doc comments and raise
+               // warnings.
+               //
+               public void check_incorrect_doc_comment ()
+               {
+                       if (xml_comment_buffer.Length > 0)
+                               warn_incorrect_doc_comment ();
+               }
+
+               //
+               // Raises a warning when tokenizer found incorrect doccomment
+               // markup.
+               //
+               private void warn_incorrect_doc_comment ()
+               {
+                       if (doc_state != XmlCommentState.Error) {
+                               doc_state = XmlCommentState.Error;
+                               // in csc, it is 'XML comment is not placed on 
+                               // a valid language element'. But that does not
+                               // make sense.
+                               Report.Warning (1587, 2, Location, "XML comment is not placed on a valid language element");
+                       }
+               }
+
+               //
+               // Consumes the saved xml comment lines (if any)
+               // as for current target member or type.
+               //
+               public string consume_doc_comment ()
+               {
+                       if (xml_comment_buffer.Length > 0) {
+                               string ret = xml_comment_buffer.ToString ();
+                               reset_doc_comment ();
+                               return ret;
+                       }
+                       return null;
+               }
+
+               void reset_doc_comment ()
+               {
+                       xml_comment_buffer.Length = 0;
+                       current_comment_location = Location.Null;
+               }
+
+               public void cleanup ()
+               {
+                       if (ifstack != null && ifstack.Count >= 1) {
+                               int state = (int) ifstack.Pop ();
+                               if ((state & REGION) != 0)
+                                       Report.Error (1038, Location, "#endregion directive expected");
+//                             else 
+//                                     Report.Error (1027, Location, "Expected `#endif' directive");
+                       }
+               }
+       }
+
+       //
+       // Indicates whether it accepts XML documentation or not.
+       //
+       public enum XmlCommentState {
+               // comment is allowed in this state.
+               Allowed,
+               // comment is not allowed in this state.
+               NotAllowed,
+               // once comments appeared when it is NotAllowed, then the
+               // state is changed to it, until the state is changed to
+               // .Allowed.
+               Error
+       }
+}
+
diff --git a/mcs/mcs/decl.cs b/mcs/mcs/decl.cs
new file mode 100644 (file)
index 0000000..0213c14
--- /dev/null
@@ -0,0 +1,2375 @@
+//
+// decl.cs: Declaration base class for structs, classes, enums and interfaces.
+//
+// Author: Miguel de Icaza (miguel@gnu.org)
+//         Marek Safar (marek.safar@seznam.cz)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+// (C) 2004 Novell, Inc
+//
+// TODO: Move the method verification stuff from the class.cs and interface.cs here
+//
+
+using System;
+using System.Text;
+using System.Collections;
+using System.Globalization;
+using System.Reflection.Emit;
+using System.Reflection;
+
+#if BOOTSTRAP_WITH_OLDLIB
+using XmlElement = System.Object;
+#else
+using System.Xml;
+#endif
+
+namespace Mono.CSharp {
+
+       public class MemberName {
+               public readonly string Name;
+               public readonly TypeArguments TypeArguments;
+
+               public readonly MemberName Left;
+               public readonly Location Location;
+
+               public static readonly MemberName Null = new MemberName ("");
+
+               bool is_double_colon;
+
+               private MemberName (MemberName left, string name, bool is_double_colon,
+                                   Location loc)
+               {
+                       this.Name = name;
+                       this.Location = loc;
+                       this.is_double_colon = is_double_colon;
+                       this.Left = left;
+               }
+
+               private MemberName (MemberName left, string name, bool is_double_colon,
+                                   TypeArguments args, Location loc)
+                       : this (left, name, is_double_colon, loc)
+               {
+                       this.TypeArguments = args;
+               }
+
+               public MemberName (string name)
+                       : this (name, Location.Null)
+               { }
+
+               public MemberName (string name, Location loc)
+                       : this (null, name, false, loc)
+               { }
+
+               public MemberName (string name, TypeArguments args, Location loc)
+                       : this (null, name, false, args, loc)
+               { }
+
+               public MemberName (MemberName left, string name)
+                       : this (left, name, left != null ? left.Location : Location.Null)
+               { }
+
+               public MemberName (MemberName left, string name, Location loc)
+                       : this (left, name, false, loc)
+               { }
+
+               public MemberName (MemberName left, string name, TypeArguments args, Location loc)
+                       : this (left, name, false, args, loc)
+               { }
+
+               public MemberName (string alias, string name, Location loc)
+                       : this (new MemberName (alias, loc), name, true, loc)
+               { }
+
+               public MemberName (MemberName left, MemberName right)
+                       : this (left, right, right.Location)
+               { }
+
+               public MemberName (MemberName left, MemberName right, Location loc)
+                       : this (null, right.Name, false, right.TypeArguments, loc)
+               {
+                       if (right.is_double_colon)
+                               throw new InternalErrorException ("Cannot append double_colon member name");
+                       this.Left = (right.Left == null) ? left : new MemberName (left, right.Left);
+               }
+
+               public string GetName ()
+               {
+                       return GetName (false);
+               }
+
+               public bool IsGeneric {
+                       get {
+                               if (TypeArguments != null)
+                                       return true;
+                               else if (Left != null)
+                                       return Left.IsGeneric;
+                               else
+                                       return false;
+                       }
+               }
+
+               public string GetName (bool is_generic)
+               {
+                       string name = is_generic ? Basename : Name;
+                       string connect = is_double_colon ? "::" : ".";
+                       if (Left != null)
+                               return Left.GetName (is_generic) + connect + name;
+                       else
+                               return name;
+               }
+
+               public string GetTypeName ()
+               {
+                       string connect = is_double_colon ? "::" : ".";
+                       if (Left != null)
+                               return Left.GetTypeName () + connect + MakeName (Name, TypeArguments);
+                       else
+                               return MakeName (Name, TypeArguments);
+               }
+
+               public Expression GetTypeExpression ()
+               {
+#if GMCS_SOURCE
+                       if (IsUnbound) {
+                               if (!CheckUnbound (Location))
+                                       return null;
+
+                               return new UnboundTypeExpression (this, Location);
+                       }
+#endif
+
+                       if (Left == null) {
+                               if (TypeArguments != null)
+                                       return new SimpleName (Basename, TypeArguments, Location);
+                               else
+                               return new SimpleName (Name, Location);
+                       }
+
+                       if (is_double_colon) {
+                               if (Left.Left != null)
+                                       throw new InternalErrorException ("The left side of a :: should be an identifier");
+                               return new QualifiedAliasMember (Left.Name, Name, Location);
+                       }
+
+                       Expression lexpr = Left.GetTypeExpression ();
+                       return new MemberAccess (lexpr, Name, TypeArguments, Location);
+               }
+
+               public MemberName Clone ()
+               {
+                       MemberName left_clone = Left == null ? null : Left.Clone ();
+                       return new MemberName (left_clone, Name, is_double_colon, TypeArguments, Location);
+               }
+
+               public string Basename {
+                       get {
+                               if (TypeArguments != null)
+                                       return MakeName (Name, TypeArguments);
+                               else
+                                       return Name;
+                       }
+               }
+
+               public string FullName {
+                       get {
+                               if (TypeArguments != null)
+                                       return Name + "<" + TypeArguments + ">";
+                               else
+                                       return Name;
+                       }
+               }
+
+               public string MethodName {
+                       get {
+                               string connect = is_double_colon ? "::" : ".";
+                               if (Left != null)
+                                       return Left.FullName + connect + Name;
+                               else
+                                       return Name;
+                       }
+               }
+
+               public override string ToString ()
+               {
+                       string connect = is_double_colon ? "::" : ".";
+                       if (Left != null)
+                               return Left.FullName + connect + FullName;
+                       else
+                               return FullName;
+               }
+
+               public override bool Equals (object other)
+               {
+                       return Equals (other as MemberName);
+               }
+
+               public bool Equals (MemberName other)
+               {
+                       if (this == other)
+                               return true;
+                       if (other == null || Name != other.Name)
+                               return false;
+                       if (is_double_colon != other.is_double_colon)
+                               return false;
+
+                       if ((TypeArguments != null) &&
+                           (other.TypeArguments == null || TypeArguments.Count != other.TypeArguments.Count))
+                               return false;
+
+                       if ((TypeArguments == null) && (other.TypeArguments != null))
+                               return false;
+
+                       if (Left == null)
+                               return other.Left == null;
+
+                       return Left.Equals (other.Left);
+               }
+
+               public override int GetHashCode ()
+               {
+                       int hash = Name.GetHashCode ();
+                       for (MemberName n = Left; n != null; n = n.Left)
+                               hash ^= n.Name.GetHashCode ();
+                       if (is_double_colon)
+                               hash ^= 0xbadc01d;
+
+                       if (TypeArguments != null)
+                               hash ^= TypeArguments.Count << 5;
+
+                       return hash & 0x7FFFFFFF;
+               }
+
+               public int CountTypeArguments {
+                       get {
+                               if (TypeArguments == null)
+                                       return 0;
+                               else
+                                       return TypeArguments.Count;
+                       }
+               }
+
+               public static string MakeName (string name, TypeArguments args)
+               {
+                       if (args == null)
+                               return name;
+                       else
+                               return name + "`" + args.Count;
+               }
+
+               public static string MakeName (string name, int count)
+               {
+                       return name + "`" + count;
+               }
+
+               protected bool IsUnbound {
+                       get {
+                               if ((Left != null) && Left.IsUnbound)
+                                       return true;
+                               else if (TypeArguments == null)
+                                       return false;
+                               else
+                                       return TypeArguments.IsUnbound;
+                       }
+               }
+
+               protected bool CheckUnbound (Location loc)
+               {
+                       if ((Left != null) && !Left.CheckUnbound (loc))
+                               return false;
+                       if ((TypeArguments != null) && !TypeArguments.IsUnbound) {
+                               Report.Error (1031, loc, "Type expected");
+                               return false;
+                       }
+
+                       return true;
+               }
+       }
+
+       /// <summary>
+       ///   Base representation for members.  This is used to keep track
+       ///   of Name, Location and Modifier flags, and handling Attributes.
+       /// </summary>
+       public abstract class MemberCore : Attributable, IResolveContext {
+               /// <summary>
+               ///   Public name
+               /// </summary>
+
+               protected string cached_name;
+               public string Name {
+                       get {
+                               if (cached_name == null)
+                                       cached_name = MemberName.GetName (!(this is GenericMethod) && !(this is Method));
+                               return cached_name;
+                       }
+               }
+
+                // Is not readonly because of IndexerName attribute
+               private MemberName member_name;
+               public MemberName MemberName {
+                       get { return member_name; }
+               }
+
+               /// <summary>
+               ///   Modifier flags that the user specified in the source code
+               /// </summary>
+               public int ModFlags;
+
+               public readonly DeclSpace Parent;
+
+               /// <summary>
+               ///   Location where this declaration happens
+               /// </summary>
+               public Location Location {
+                       get { return member_name.Location; }
+               }
+
+               /// <summary>
+               ///   XML documentation comment
+               /// </summary>
+               protected string comment;
+
+               /// <summary>
+               ///   Represents header string for documentation comment 
+               ///   for each member types.
+               /// </summary>
+               public abstract string DocCommentHeader { get; }
+
+               [Flags]
+               public enum Flags {
+                       Obsolete_Undetected = 1,                // Obsolete attribute has not been detected yet
+                       Obsolete = 1 << 1,                      // Type has obsolete attribute
+                       ClsCompliance_Undetected = 1 << 2,      // CLS Compliance has not been detected yet
+                       ClsCompliant = 1 << 3,                  // Type is CLS Compliant
+                       CloseTypeCreated = 1 << 4,              // Tracks whether we have Closed the type
+                       HasCompliantAttribute_Undetected = 1 << 5,      // Presence of CLSCompliantAttribute has not been detected
+                       HasClsCompliantAttribute = 1 << 6,                      // Type has CLSCompliantAttribute
+                       ClsCompliantAttributeTrue = 1 << 7,                     // Type has CLSCompliant (true)
+                       Excluded_Undetected = 1 << 8,           // Conditional attribute has not been detected yet
+                       Excluded = 1 << 9,                                      // Method is conditional
+                       TestMethodDuplication = 1 << 10,                // Test for duplication must be performed
+                       IsUsed = 1 << 11,
+                       IsAssigned = 1 << 12,                           // Field is assigned
+                       HasExplicitLayout       = 1 << 13
+               }
+
+               /// <summary>
+               ///   MemberCore flags at first detected then cached
+               /// </summary>
+               internal Flags caching_flags;
+
+               public MemberCore (DeclSpace parent, MemberName name, Attributes attrs)
+                       : base (attrs)
+               {
+                       this.Parent = parent;
+                       member_name = name;
+                       caching_flags = Flags.Obsolete_Undetected | Flags.ClsCompliance_Undetected | Flags.HasCompliantAttribute_Undetected | Flags.Excluded_Undetected;
+               }
+
+               protected virtual void SetMemberName (MemberName new_name)
+               {
+                       member_name = new_name;
+                       cached_name = null;
+               }
+
+               public abstract bool Define ();
+
+               public virtual string DocComment {
+                       get {
+                               return comment;
+                       }
+                       set {
+                               comment = value;
+                       }
+               }
+
+               // 
+               // Returns full member name for error message
+               //
+               public virtual string GetSignatureForError ()
+               {
+                       if (Parent == null || Parent.Parent == null)
+                               return member_name.ToString ();
+
+                       return String.Concat (Parent.GetSignatureForError (), '.', member_name.ToString ());
+               }
+
+               /// <summary>
+               /// Base Emit method. This is also entry point for CLS-Compliant verification.
+               /// </summary>
+               public virtual void Emit ()
+               {
+                       if (!RootContext.VerifyClsCompliance)
+                               return;
+
+                       VerifyClsCompliance ();
+               }
+
+               public virtual bool IsUsed {
+                       get { return (caching_flags & Flags.IsUsed) != 0; }
+               }
+
+               public void SetMemberIsUsed ()
+               {
+                       caching_flags |= Flags.IsUsed;
+               }
+
+               /// <summary>
+               /// Returns instance of ObsoleteAttribute for this MemberCore
+               /// </summary>
+               public virtual ObsoleteAttribute GetObsoleteAttribute ()
+               {
+                       // ((flags & (Flags.Obsolete_Undetected | Flags.Obsolete)) == 0) is slower, but why ?
+                       if ((caching_flags & Flags.Obsolete_Undetected) == 0 && (caching_flags & Flags.Obsolete) == 0) {
+                               return null;
+                       }
+
+                       caching_flags &= ~Flags.Obsolete_Undetected;
+
+                       if (OptAttributes == null)
+                               return null;
+
+                       Attribute obsolete_attr = OptAttributes.Search (
+                               TypeManager.obsolete_attribute_type);
+                       if (obsolete_attr == null)
+                               return null;
+
+                       ObsoleteAttribute obsolete = obsolete_attr.GetObsoleteAttribute ();
+                       if (obsolete == null)
+                               return null;
+
+                       caching_flags |= Flags.Obsolete;
+                       return obsolete;
+               }
+
+               /// <summary>
+               /// Checks for ObsoleteAttribute presence. It's used for testing of all non-types elements
+               /// </summary>
+               public virtual void CheckObsoleteness (Location loc)
+               {
+                       if (Parent != null)
+                               Parent.CheckObsoleteness (loc);
+
+                       ObsoleteAttribute oa = GetObsoleteAttribute ();
+                       if (oa == null) {
+                               return;
+                       }
+
+                       AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc);
+               }
+
+               /// <summary>
+               /// Analyze whether CLS-Compliant verification must be execute for this MemberCore.
+               /// </summary>
+               public override bool IsClsComplianceRequired ()
+               {
+                       if ((caching_flags & Flags.ClsCompliance_Undetected) == 0)
+                               return (caching_flags & Flags.ClsCompliant) != 0;
+
+                       if (GetClsCompliantAttributeValue () && IsExposedFromAssembly ()) {
+                               caching_flags &= ~Flags.ClsCompliance_Undetected;
+                               caching_flags |= Flags.ClsCompliant;
+                               return true;
+                       }
+
+                       caching_flags &= ~Flags.ClsCompliance_Undetected;
+                       return false;
+               }
+
+               /// <summary>
+               /// Returns true when MemberCore is exposed from assembly.
+               /// </summary>
+               public bool IsExposedFromAssembly ()
+               {
+                       if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0)
+                               return false;
+                       
+                       DeclSpace parentContainer = Parent;
+                       while (parentContainer != null && parentContainer.ModFlags != 0) {
+                               if ((parentContainer.ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0)
+                                       return false;
+                               parentContainer = parentContainer.Parent;
+                       }
+                       return true;
+               }
+
+               /// <summary>
+               /// Goes through class hierarchy and gets value of first found CLSCompliantAttribute.
+               /// If no is attribute exists then assembly CLSCompliantAttribute is returned.
+               /// </summary>
+               public virtual bool GetClsCompliantAttributeValue ()
+               {
+                       if ((caching_flags & Flags.HasCompliantAttribute_Undetected) == 0)
+                               return (caching_flags & Flags.ClsCompliantAttributeTrue) != 0;
+
+                       caching_flags &= ~Flags.HasCompliantAttribute_Undetected;
+
+                       if (OptAttributes != null) {
+                               Attribute cls_attribute = OptAttributes.Search (
+                                       TypeManager.cls_compliant_attribute_type);
+                               if (cls_attribute != null) {
+                                       caching_flags |= Flags.HasClsCompliantAttribute;
+                                       bool value = cls_attribute.GetClsCompliantAttributeValue ();
+                                       if (value)
+                                               caching_flags |= Flags.ClsCompliantAttributeTrue;
+                                       return value;
+                               }
+                       }
+
+                       if (Parent.GetClsCompliantAttributeValue ()) {
+                               caching_flags |= Flags.ClsCompliantAttributeTrue;
+                               return true;
+                       }
+                       return false;
+               }
+
+               /// <summary>
+               /// Returns true if MemberCore is explicitly marked with CLSCompliantAttribute
+               /// </summary>
+               protected bool HasClsCompliantAttribute {
+                       get {
+                               return (caching_flags & Flags.HasClsCompliantAttribute) != 0;
+                       }
+               }
+
+               /// <summary>
+               /// It helps to handle error 102 & 111 detection
+               /// </summary>
+               public virtual bool MarkForDuplicationCheck ()
+               {
+                       return false;
+               }
+
+               /// <summary>
+               /// The main virtual method for CLS-Compliant verifications.
+               /// The method returns true if member is CLS-Compliant and false if member is not
+               /// CLS-Compliant which means that CLS-Compliant tests are not necessary. A descendants override it
+               /// and add their extra verifications.
+               /// </summary>
+               protected virtual bool VerifyClsCompliance ()
+               {
+                       if (!IsClsComplianceRequired ()) {
+                               if (HasClsCompliantAttribute && RootContext.WarningLevel >= 2) {
+                                       if (!IsExposedFromAssembly ())
+                                               Report.Warning (3019, 2, Location, "CLS compliance checking will not be performed on `{0}' because it is not visible from outside this assembly", GetSignatureForError ());
+                                       if (!CodeGen.Assembly.IsClsCompliant)
+                                               Report.Warning (3021, 2, Location, "`{0}' does not need a CLSCompliant attribute because the assembly is not marked as CLS-compliant", GetSignatureForError ());
+                               }
+                               return false;
+                       }
+
+                       if (HasClsCompliantAttribute) {
+                               if (CodeGen.Assembly.ClsCompliantAttribute == null && !CodeGen.Assembly.IsClsCompliant) {
+                                       Report.Error (3014, Location,
+                                               "`{0}' cannot be marked as CLS-compliant because the assembly is not marked as CLS-compliant",
+                                               GetSignatureForError ());
+                                       return false;
+                               }
+
+                               if (!Parent.IsClsComplianceRequired ()) {
+                                       Report.Warning (3018, 1, Location, "`{0}' cannot be marked as CLS-compliant because it is a member of non CLS-compliant type `{1}'", 
+                                               GetSignatureForError (), Parent.GetSignatureForError ());
+                                       return false;
+                               }
+                       }
+
+                       if (member_name.Name [0] == '_') {
+                               Report.Error (3008, Location, "Identifier `{0}' is not CLS-compliant", GetSignatureForError () );
+                       }
+                       return true;
+               }
+
+               //
+               // Raised (and passed an XmlElement that contains the comment)
+               // when GenerateDocComment is writing documentation expectedly.
+               //
+               internal virtual void OnGenerateDocComment (XmlElement intermediateNode)
+               {
+               }
+
+               //
+               // Returns a string that represents the signature for this 
+               // member which should be used in XML documentation.
+               //
+               public virtual string GetDocCommentName (DeclSpace ds)
+               {
+                       if (ds == null || this is DeclSpace)
+                               return DocCommentHeader + Name;
+                       else
+                               return String.Concat (DocCommentHeader, ds.Name, ".", Name);
+               }
+
+               //
+               // Generates xml doc comments (if any), and if required,
+               // handle warning report.
+               //
+               internal virtual void GenerateDocComment (DeclSpace ds)
+               {
+                       DocUtil.GenerateDocComment (this, ds);
+               }
+
+               public override IResolveContext ResolveContext {
+                       get { return this; }
+               }
+
+               #region IResolveContext Members
+
+               public DeclSpace DeclContainer {
+                       get { return Parent; }
+               }
+
+               public virtual DeclSpace GenericDeclContainer {
+                       get { return DeclContainer; }
+               }
+
+               public bool IsInObsoleteScope {
+                       get {
+                               if (GetObsoleteAttribute () != null)
+                                       return true;
+
+                               return Parent == null ? false : Parent.IsInObsoleteScope;
+                       }
+               }
+
+               public bool IsInUnsafeScope {
+                       get {
+                               if ((ModFlags & Modifiers.UNSAFE) != 0)
+                                       return true;
+
+                               return Parent == null ? false : Parent.IsInUnsafeScope;
+                       }
+               }
+
+               #endregion
+       }
+
+       /// <summary>
+       ///   Base class for structs, classes, enumerations and interfaces.  
+       /// </summary>
+       /// <remarks>
+       ///   They all create new declaration spaces.  This
+       ///   provides the common foundation for managing those name
+       ///   spaces.
+       /// </remarks>
+       public abstract class DeclSpace : MemberCore {
+               /// <summary>
+               ///   This points to the actual definition that is being
+               ///   created with System.Reflection.Emit
+               /// </summary>
+               public TypeBuilder TypeBuilder;
+
+               /// <summary>
+               ///   If we are a generic type, this is the type we are
+               ///   currently defining.  We need to lookup members on this
+               ///   instead of the TypeBuilder.
+               /// </summary>
+               public Type CurrentType;
+
+               //
+               // This is the namespace in which this typecontainer
+               // was declared.  We use this to resolve names.
+               //
+               public NamespaceEntry NamespaceEntry;
+
+               private Hashtable Cache = new Hashtable ();
+               
+               public readonly string Basename;
+               
+               protected Hashtable defined_names;
+
+               public TypeContainer PartialContainer;          
+
+               readonly bool is_generic;
+               readonly int count_type_params;
+               readonly int count_current_type_params;
+
+               //
+               // Whether we are Generic
+               //
+               public bool IsGeneric {
+                       get {
+                               if (is_generic)
+                                       return true;
+                               else if (Parent != null)
+                                       return Parent.IsGeneric;
+                               else
+                                       return false;
+                       }
+               }
+
+               static string[] attribute_targets = new string [] { "type" };
+
+               public DeclSpace (NamespaceEntry ns, DeclSpace parent, MemberName name,
+                                 Attributes attrs)
+                       : base (parent, name, attrs)
+               {
+                       NamespaceEntry = ns;
+                       Basename = name.Basename;
+                       defined_names = new Hashtable ();
+                       PartialContainer = null;
+                       if (name.TypeArguments != null) {
+                               is_generic = true;
+                               count_type_params = count_current_type_params = name.TypeArguments.Count;
+                       }
+                       if (parent != null)
+                               count_type_params += parent.count_type_params;
+               }
+
+               public override DeclSpace GenericDeclContainer {
+                       get { return this; }
+               }
+
+               /// <summary>
+               /// Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
+               /// </summary>
+               protected virtual bool AddToContainer (MemberCore symbol, string name)
+               {
+                       MemberCore mc = (MemberCore) defined_names [name];
+
+                       if (mc == null) {
+                               defined_names.Add (name, symbol);
+                               return true;
+                       }
+
+                       if (symbol.MarkForDuplicationCheck () && mc.MarkForDuplicationCheck ())
+                               return true;
+
+                       Report.SymbolRelatedToPreviousError (mc);
+                       if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
+                               Error_MissingPartialModifier (symbol);
+                               return false;
+                       }
+
+                       if (this is RootTypes) {
+                               Report.Error (101, symbol.Location, 
+                                       "The namespace `{0}' already contains a definition for `{1}'",
+                                       ((DeclSpace)symbol).NamespaceEntry.GetSignatureForError (), symbol.MemberName.Name);
+                       } else if (symbol is TypeParameter) {
+                               Report.Error (692, symbol.Location,
+                                             "Duplicate type parameter `{0}'", name);
+                       } else {
+                               Report.Error (102, symbol.Location,
+                                             "The type `{0}' already contains a definition for `{1}'",
+                                             GetSignatureForError (), symbol.MemberName.Name);
+                       }
+
+                       return false;
+               }
+
+               /// <summary>
+               ///   Returns the MemberCore associated with a given name in the declaration
+               ///   space. It doesn't return method based symbols !!
+               /// </summary>
+               /// 
+               public MemberCore GetDefinition (string name)
+               {
+                       return (MemberCore)defined_names [name];
+               }
+               
+               // 
+               // root_types contains all the types.  All TopLevel types
+               // hence have a parent that points to `root_types', that is
+               // why there is a non-obvious test down here.
+               //
+               public bool IsTopLevel {
+                       get { return (Parent != null && Parent.Parent == null); }
+               }
+
+               public virtual void CloseType ()
+               {
+                       if ((caching_flags & Flags.CloseTypeCreated) == 0){
+                               try {
+                                       TypeBuilder.CreateType ();
+                               } catch {
+                                       //
+                                       // The try/catch is needed because
+                                       // nested enumerations fail to load when they
+                                       // are defined.
+                                       //
+                                       // Even if this is the right order (enumerations
+                                       // declared after types).
+                                       //
+                                       // Note that this still creates the type and
+                                       // it is possible to save it
+                               }
+                               caching_flags |= Flags.CloseTypeCreated;
+                       }
+               }
+
+               protected virtual TypeAttributes TypeAttr {
+                       get { return CodeGen.Module.DefaultCharSetType; }
+               }
+
+               /// <remarks>
+               ///  Should be overriten by the appropriate declaration space
+               /// </remarks>
+               public abstract TypeBuilder DefineType ();
+               
+               /// <summary>
+               ///   Define all members, but don't apply any attributes or do anything which may
+               ///   access not-yet-defined classes.  This method also creates the MemberCache.
+               /// </summary>
+               public virtual bool DefineMembers ()
+               {
+                       if (((ModFlags & Modifiers.NEW) != 0) && IsTopLevel) {
+                               Report.Error (1530, Location, "Keyword `new' is not allowed on namespace elements");
+                               return false;
+                       }
+                       return true;
+               }
+
+               protected void Error_MissingPartialModifier (MemberCore type)
+               {
+                       Report.Error (260, type.Location,
+                               "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
+                               type.GetSignatureForError ());
+               }
+
+               public override string GetSignatureForError ()
+               {       
+                       if (IsGeneric) {
+                               return SimpleName.RemoveGenericArity (Name) + TypeParameter.GetSignatureForError (CurrentTypeParameters);
+                       }
+                       // Parent.GetSignatureForError
+                       return Name;
+               }
+               
+               public bool CheckAccessLevel (Type check_type)
+               {
+                       TypeBuilder tb;
+                       if (this is GenericMethod)
+                               tb = Parent.TypeBuilder;
+                       else
+                               tb = TypeBuilder;
+
+                       check_type = TypeManager.DropGenericTypeArguments (check_type);
+                       if (check_type == tb)
+                               return true;
+                       
+                       if (TypeBuilder == null)
+                               // FIXME: TypeBuilder will be null when invoked by Class.GetNormalBases().
+                               //        However, this is invoked again later -- so safe to return true.
+                               //        May also be null when resolving top-level attributes.
+                               return true;
+
+                       if (TypeManager.IsGenericParameter (check_type))
+                               return true; // FIXME
+                       
+                       TypeAttributes check_attr = check_type.Attributes & TypeAttributes.VisibilityMask;
+
+                       //
+                       // Broken Microsoft runtime, return public for arrays, no matter what 
+                       // the accessibility is for their underlying class, and they return 
+                       // NonPublic visibility for pointers
+                       //
+                       if (check_type.IsArray || check_type.IsPointer)
+                               return CheckAccessLevel (TypeManager.GetElementType (check_type));
+
+                       switch (check_attr){
+                       case TypeAttributes.Public:
+                               return true;
+
+                       case TypeAttributes.NotPublic:
+
+                               if (TypeBuilder == null)
+                                       // FIXME: TypeBuilder will be null when invoked by Class.GetNormalBases().
+                                       //        However, this is invoked again later -- so safe to return true.
+                                       //        May also be null when resolving top-level attributes.
+                                       return true;
+                               //
+                               // This test should probably use the declaringtype.
+                               //
+                               return check_type.Assembly == TypeBuilder.Assembly ||
+                                       TypeManager.IsFriendAssembly (check_type.Assembly);
+                               
+                       case TypeAttributes.NestedPublic:
+                               return true;
+
+                       case TypeAttributes.NestedPrivate:
+                               return NestedAccessible (tb, check_type);
+
+                       case TypeAttributes.NestedFamily:
+                               //
+                               // Only accessible to methods in current type or any subtypes
+                               //
+                               return FamilyAccessible (tb, check_type);
+
+                       case TypeAttributes.NestedFamANDAssem:
+                               return ((check_type.Assembly == tb.Assembly) || 
+                                               TypeManager.IsFriendAssembly (check_type.Assembly)) && 
+                                       FamilyAccessible (tb, check_type);
+
+                       case TypeAttributes.NestedFamORAssem:
+                               return (check_type.Assembly == tb.Assembly) ||
+                                       FamilyAccessible (tb, check_type) ||
+                                       TypeManager.IsFriendAssembly (check_type.Assembly);
+
+                       case TypeAttributes.NestedAssembly:
+                               return check_type.Assembly == tb.Assembly ||
+                                       TypeManager.IsFriendAssembly (check_type.Assembly);
+                       }
+
+                       Console.WriteLine ("HERE: " + check_attr);
+                       return false;
+
+               }
+
+               protected bool NestedAccessible (Type tb, Type check_type)
+               {
+                       Type declaring = check_type.DeclaringType;
+                       return TypeBuilder == declaring ||
+                               TypeManager.IsNestedChildOf (TypeBuilder, declaring);
+               }
+
+               protected bool FamilyAccessible (Type tb, Type check_type)
+               {
+                       Type declaring = check_type.DeclaringType;
+                       return TypeManager.IsNestedFamilyAccessible (TypeBuilder, declaring);
+               }
+
+               // Access level of a type.
+               const int X = 1;
+               enum AccessLevel { // Each column represents `is this scope larger or equal to Blah scope'
+                       // Public    Assembly   Protected
+                       Protected           = (0 << 0) | (0 << 1) | (X << 2),
+                       Public              = (X << 0) | (X << 1) | (X << 2),
+                       Private             = (0 << 0) | (0 << 1) | (0 << 2),
+                       Internal            = (0 << 0) | (X << 1) | (0 << 2),
+                       ProtectedOrInternal = (0 << 0) | (X << 1) | (X << 2),
+               }
+               
+               static AccessLevel GetAccessLevelFromModifiers (int flags)
+               {
+                       if ((flags & Modifiers.INTERNAL) != 0) {
+                               
+                               if ((flags & Modifiers.PROTECTED) != 0)
+                                       return AccessLevel.ProtectedOrInternal;
+                               else
+                                       return AccessLevel.Internal;
+                               
+                       } else if ((flags & Modifiers.PROTECTED) != 0)
+                               return AccessLevel.Protected;
+                       else if ((flags & Modifiers.PRIVATE) != 0)
+                               return AccessLevel.Private;
+                       else
+                               return AccessLevel.Public;
+               }
+
+               // What is the effective access level of this?
+               // TODO: Cache this?
+               AccessLevel EffectiveAccessLevel {
+                       get {
+                               AccessLevel myAccess = GetAccessLevelFromModifiers (ModFlags);
+                               if (!IsTopLevel && (Parent != null))
+                                       return myAccess & Parent.EffectiveAccessLevel;
+                               return myAccess;
+                       }
+               }
+
+               // Return the access level for type `t'
+               static AccessLevel TypeEffectiveAccessLevel (Type t)
+               {
+                       if (t.IsPublic)
+                               return AccessLevel.Public;
+                       if (t.IsNestedPrivate)
+                               return AccessLevel.Private;
+                       if (t.IsNotPublic)
+                               return AccessLevel.Internal;
+                       
+                       // By now, it must be nested
+                       AccessLevel parentLevel = TypeEffectiveAccessLevel (t.DeclaringType);
+                       
+                       if (t.IsNestedPublic)
+                               return parentLevel;
+                       if (t.IsNestedAssembly)
+                               return parentLevel & AccessLevel.Internal;
+                       if (t.IsNestedFamily)
+                               return parentLevel & AccessLevel.Protected;
+                       if (t.IsNestedFamORAssem)
+                               return parentLevel & AccessLevel.ProtectedOrInternal;
+                       if (t.IsNestedFamANDAssem)
+                               throw new NotImplementedException ("NestedFamANDAssem not implemented, cant make this kind of type from c# anyways");
+                       
+                       // nested private is taken care of
+                       
+                       throw new Exception ("I give up, what are you?");
+               }
+
+               //
+               // This answers `is the type P, as accessible as a member M which has the
+               // accessability @flags which is declared as a nested member of the type T, this declspace'
+               //
+               public bool AsAccessible (Type p, int flags)
+               {
+                       if (TypeManager.IsGenericParameter (p))
+                               return true; // FIXME
+
+                       //
+                       // 1) if M is private, its accessability is the same as this declspace.
+                       // we already know that P is accessible to T before this method, so we
+                       // may return true.
+                       //
+                       
+                       if ((flags & Modifiers.PRIVATE) != 0)
+                               return true;
+                       
+                       while (p.IsArray || p.IsPointer || p.IsByRef)
+                               p = TypeManager.GetElementType (p);
+                       
+                       AccessLevel pAccess = TypeEffectiveAccessLevel (p);
+                       AccessLevel mAccess = this.EffectiveAccessLevel &
+                               GetAccessLevelFromModifiers (flags);
+                       
+                       // for every place from which we can access M, we must
+                       // be able to access P as well. So, we want
+                       // For every bit in M and P, M_i -> P_1 == true
+                       // or, ~ (M -> P) == 0 <-> ~ ( ~M | P) == 0
+                       
+                       return ~ (~ mAccess | pAccess) == 0;
+               }
+
+               private Type LookupNestedTypeInHierarchy (string name)
+               {
+                       // if the member cache has been created, lets use it.
+                       // the member cache is MUCH faster.
+                       if (MemberCache != null)
+                               return MemberCache.FindNestedType (name);
+
+                       // no member cache. Do it the hard way -- reflection
+                       Type t = null;
+                       for (Type current_type = TypeBuilder;
+                            current_type != null && current_type != TypeManager.object_type;
+                            current_type = current_type.BaseType) {
+                               current_type = TypeManager.DropGenericTypeArguments (current_type);
+                               if (current_type is TypeBuilder) {
+                                       TypeContainer tc = current_type == TypeBuilder
+                                               ? PartialContainer
+                                               : TypeManager.LookupTypeContainer (current_type);
+                                       if (tc != null)
+                                               t = tc.FindNestedType (name);
+                               } else {
+                                       t = TypeManager.GetNestedType (current_type, name);
+                               }
+
+                               if (t != null && CheckAccessLevel (t))
+                                       return t;
+                       }
+
+                       return null;
+               }
+
+               //
+               // Public function used to locate types.
+               //
+               // Set 'ignore_cs0104' to true if you want to ignore cs0104 errors.
+               //
+               // Returns: Type or null if they type can not be found.
+               //
+               public FullNamedExpression LookupType (string name, Location loc, bool ignore_cs0104)
+               {
+                       if (Cache.Contains (name))
+                               return (FullNamedExpression) Cache [name];
+
+                       FullNamedExpression e;
+                       Type t = LookupNestedTypeInHierarchy (name);
+                       if (t != null)
+                               e = new TypeExpression (t, Location.Null);
+                       else if (Parent != null)
+                               e = Parent.LookupType (name, loc, ignore_cs0104);
+                       else
+                               e = NamespaceEntry.LookupNamespaceOrType (this, name, loc, ignore_cs0104);
+
+                       Cache [name] = e;
+                       return e;
+               }
+
+               /// <remarks>
+               ///   This function is broken and not what you're looking for.  It should only
+               ///   be used while the type is still being created since it doesn't use the cache
+               ///   and relies on the filter doing the member name check.
+               /// </remarks>
+               public abstract MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+                                                       MemberFilter filter, object criteria);
+
+               /// <remarks>
+               ///   If we have a MemberCache, return it.  This property may return null if the
+               ///   class doesn't have a member cache or while it's still being created.
+               /// </remarks>
+               public abstract MemberCache MemberCache {
+                       get;
+               }
+
+               public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+               {
+                       if (a.Type == TypeManager.required_attr_type) {
+                               Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
+                               return;
+                       }
+                       TypeBuilder.SetCustomAttribute (cb);
+               }
+
+               //
+               // Extensions for generics
+               //
+               TypeParameter[] type_params;
+               TypeParameter[] type_param_list;
+
+               protected string GetInstantiationName ()
+               {
+                       StringBuilder sb = new StringBuilder (Name);
+                       sb.Append ("<");
+                       for (int i = 0; i < type_param_list.Length; i++) {
+                               if (i > 0)
+                                       sb.Append (",");
+                               sb.Append (type_param_list [i].Name);
+                       }
+                       sb.Append (">");
+                       return sb.ToString ();
+               }
+
+               bool check_type_parameter (ArrayList list, int start, string name)
+               {
+                       for (int i = 0; i < start; i++) {
+                               TypeParameter param = (TypeParameter) list [i];
+
+                               if (param.Name != name)
+                                       continue;
+
+                               Report.SymbolRelatedToPreviousError (Parent);
+                               // TODO: Location is wrong (parent instead of child)
+                               Report.Warning (693, 3, Location,
+                                       "Type parameter `{0}' has the same name as the type parameter from outer type `{1}'",
+                                       name, Parent.GetSignatureForError ());
+
+                               return false;
+                       }
+
+                       return true;
+               }
+
+               TypeParameter[] initialize_type_params ()
+               {
+                       if (type_param_list != null)
+                               return type_param_list;
+
+                       DeclSpace the_parent = Parent;
+                       if (this is GenericMethod)
+                               the_parent = null;
+
+                       int start = 0;
+                       TypeParameter[] parent_params = null;
+                       if ((the_parent != null) && the_parent.IsGeneric) {
+                               parent_params = the_parent.initialize_type_params ();
+                               start = parent_params != null ? parent_params.Length : 0;
+                       }
+
+                       ArrayList list = new ArrayList ();
+                       if (parent_params != null)
+                               list.AddRange (parent_params);
+
+                       int count = type_params != null ? type_params.Length : 0;
+                       for (int i = 0; i < count; i++) {
+                               TypeParameter param = type_params [i];
+                               check_type_parameter (list, start, param.Name);
+                               list.Add (param);
+                       }
+
+                       type_param_list = new TypeParameter [list.Count];
+                       list.CopyTo (type_param_list, 0);
+                       return type_param_list;
+               }
+
+               public virtual void SetParameterInfo (ArrayList constraints_list)
+               {
+                       if (!is_generic) {
+                               if (constraints_list != null) {
+                                       Report.Error (
+                                               80, Location, "Constraints are not allowed " +
+                                               "on non-generic declarations");
+                               }
+
+                               return;
+                       }
+
+                       TypeParameterName[] names = MemberName.TypeArguments.GetDeclarations ();
+                       type_params = new TypeParameter [names.Length];
+
+                       //
+                       // Register all the names
+                       //
+                       for (int i = 0; i < type_params.Length; i++) {
+                               TypeParameterName name = names [i];
+
+                               Constraints constraints = null;
+                               if (constraints_list != null) {
+                                       int total = constraints_list.Count;
+                                       for (int ii = 0; ii < total; ++ii) {
+                                               Constraints constraints_at = (Constraints)constraints_list[ii];
+                                               // TODO: it is used by iterators only
+                                               if (constraints_at == null) {
+                                                       constraints_list.RemoveAt (ii);
+                                                       --total;
+                                                       continue;
+                                               }
+                                               if (constraints_at.TypeParameter == name.Name) {
+                                                       constraints = constraints_at;
+                                                       constraints_list.RemoveAt(ii);
+                                                       break;
+                                               }
+                                       }
+                               }
+
+                               type_params [i] = new TypeParameter (
+                                       Parent, this, name.Name, constraints, name.OptAttributes,
+                                       Location);
+
+                               AddToContainer (type_params [i], name.Name);
+                       }
+
+                       if (constraints_list != null && constraints_list.Count > 0) {
+                               foreach (Constraints constraint in constraints_list) {
+                                       Report.Error(699, constraint.Location, "`{0}': A constraint references nonexistent type parameter `{1}'", 
+                                               GetSignatureForError (), constraint.TypeParameter);
+                               }
+                       }
+               }
+
+               public TypeParameter[] TypeParameters {
+                       get {
+                               if (!IsGeneric)
+                                       throw new InvalidOperationException ();
+                               if (type_param_list == null)
+                                       initialize_type_params ();
+
+                               return type_param_list;
+                       }
+               }
+
+               public TypeParameter[] CurrentTypeParameters {
+                       get {
+                               if (!IsGeneric)
+                                       throw new InvalidOperationException ();
+                               if (type_params != null)
+                                       return type_params;
+                               else
+                                       return new TypeParameter [0];
+                       }
+               }
+
+               public int CountTypeParameters {
+                       get {
+                               return count_type_params;
+                       }
+               }
+
+               public int CountCurrentTypeParameters {
+                       get {
+                               return count_current_type_params;
+                       }
+               }
+
+               public TypeParameterExpr LookupGeneric (string name, Location loc)
+               {
+                       if (!IsGeneric)
+                               return null;
+
+                       TypeParameter [] current_params;
+                       if (this is TypeContainer)
+                               current_params = PartialContainer.CurrentTypeParameters;
+                       else
+                               current_params = CurrentTypeParameters;
+
+                       foreach (TypeParameter type_param in current_params) {
+                               if (type_param.Name == name)
+                                       return new TypeParameterExpr (type_param, loc);
+                       }
+
+                       if (Parent != null)
+                               return Parent.LookupGeneric (name, loc);
+
+                       return null;
+               }
+
+               public override string[] ValidAttributeTargets {
+                       get { return attribute_targets; }
+               }
+
+               protected override bool VerifyClsCompliance ()
+               {
+                       if (!base.VerifyClsCompliance ()) {
+                               return false;
+                       }
+
+                       if (type_params != null) {
+                               foreach (TypeParameter tp in type_params) {
+                                       if (tp.Constraints == null)
+                                               continue;
+
+                                       tp.Constraints.VerifyClsCompliance ();
+                               }
+                       }
+
+                       IDictionary cache = TypeManager.AllClsTopLevelTypes;
+                       string lcase = Name.ToLower (System.Globalization.CultureInfo.InvariantCulture);
+                       if (!cache.Contains (lcase)) {
+                               cache.Add (lcase, this);
+                               return true;
+                       }
+
+                       object val = cache [lcase];
+                       if (val == null) {
+                               Type t = AttributeTester.GetImportedIgnoreCaseClsType (lcase);
+                               if (t == null)
+                                       return true;
+                               Report.SymbolRelatedToPreviousError (t);
+                       }
+                       else {
+                               Report.SymbolRelatedToPreviousError ((DeclSpace)val);
+                       }
+#if GMCS_SOURCE
+                       Report.Warning (3005, 1, Location, "Identifier `{0}' differing only in case is not CLS-compliant", GetSignatureForError ());
+#else
+                       Report.Error (3005, Location, "Identifier `{0}' differing only in case is not CLS-compliant", GetSignatureForError ());
+#endif
+                       return true;
+               }
+       }
+
+       /// <summary>
+       ///   This is a readonly list of MemberInfo's.      
+       /// </summary>
+       public class MemberList : IList {
+               public readonly IList List;
+               int count;
+
+               /// <summary>
+               ///   Create a new MemberList from the given IList.
+               /// </summary>
+               public MemberList (IList list)
+               {
+                       if (list != null)
+                               this.List = list;
+                       else
+                               this.List = new ArrayList ();
+                       count = List.Count;
+               }
+
+               /// <summary>
+               ///   Concatenate the ILists `first' and `second' to a new MemberList.
+               /// </summary>
+               public MemberList (IList first, IList second)
+               {
+                       ArrayList list = new ArrayList ();
+                       list.AddRange (first);
+                       list.AddRange (second);
+                       count = list.Count;
+                       List = list;
+               }
+
+               public static readonly MemberList Empty = new MemberList (new ArrayList ());
+
+               /// <summary>
+               ///   Cast the MemberList into a MemberInfo[] array.
+               /// </summary>
+               /// <remarks>
+               ///   This is an expensive operation, only use it if it's really necessary.
+               /// </remarks>
+               public static explicit operator MemberInfo [] (MemberList list)
+               {
+                       Timer.StartTimer (TimerType.MiscTimer);
+                       MemberInfo [] result = new MemberInfo [list.Count];
+                       list.CopyTo (result, 0);
+                       Timer.StopTimer (TimerType.MiscTimer);
+                       return result;
+               }
+
+               // ICollection
+
+               public int Count {
+                       get {
+                               return count;
+                       }
+               }
+
+               public bool IsSynchronized {
+                       get {
+                               return List.IsSynchronized;
+                       }
+               }
+
+               public object SyncRoot {
+                       get {
+                               return List.SyncRoot;
+                       }
+               }
+
+               public void CopyTo (Array array, int index)
+               {
+                       List.CopyTo (array, index);
+               }
+
+               // IEnumerable
+
+               public IEnumerator GetEnumerator ()
+               {
+                       return List.GetEnumerator ();
+               }
+
+               // IList
+
+               public bool IsFixedSize {
+                       get {
+                               return true;
+                       }
+               }
+
+               public bool IsReadOnly {
+                       get {
+                               return true;
+                       }
+               }
+
+               object IList.this [int index] {
+                       get {
+                               return List [index];
+                       }
+
+                       set {
+                               throw new NotSupportedException ();
+                       }
+               }
+
+               // FIXME: try to find out whether we can avoid the cast in this indexer.
+               public MemberInfo this [int index] {
+                       get {
+                               return (MemberInfo) List [index];
+                       }
+               }
+
+               public int Add (object value)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               public void Clear ()
+               {
+                       throw new NotSupportedException ();
+               }
+
+               public bool Contains (object value)
+               {
+                       return List.Contains (value);
+               }
+
+               public int IndexOf (object value)
+               {
+                       return List.IndexOf (value);
+               }
+
+               public void Insert (int index, object value)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               public void Remove (object value)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               public void RemoveAt (int index)
+               {
+                       throw new NotSupportedException ();
+               }
+       }
+
+       /// <summary>
+       ///   This interface is used to get all members of a class when creating the
+       ///   member cache.  It must be implemented by all DeclSpace derivatives which
+       ///   want to support the member cache and by TypeHandle to get caching of
+       ///   non-dynamic types.
+       /// </summary>
+       public interface IMemberContainer {
+               /// <summary>
+               ///   The name of the IMemberContainer.  This is only used for
+               ///   debugging purposes.
+               /// </summary>
+               string Name {
+                       get;
+               }
+
+               /// <summary>
+               ///   The type of this IMemberContainer.
+               /// </summary>
+               Type Type {
+                       get;
+               }
+
+               /// <summary>
+               ///   Returns the IMemberContainer of the base class or null if this
+               ///   is an interface or TypeManger.object_type.
+               ///   This is used when creating the member cache for a class to get all
+               ///   members from the base class.
+               /// </summary>
+               MemberCache BaseCache {
+                       get;
+               }
+
+               /// <summary>
+               ///   Whether this is an interface.
+               /// </summary>
+               bool IsInterface {
+                       get;
+               }
+
+               /// <summary>
+               ///   Returns all members of this class with the corresponding MemberTypes
+               ///   and BindingFlags.
+               /// </summary>
+               /// <remarks>
+               ///   When implementing this method, make sure not to return any inherited
+               ///   members and check the MemberTypes and BindingFlags properly.
+               ///   Unfortunately, System.Reflection is lame and doesn't provide a way to
+               ///   get the BindingFlags (static/non-static,public/non-public) in the
+               ///   MemberInfo class, but the cache needs this information.  That's why
+               ///   this method is called multiple times with different BindingFlags.
+               /// </remarks>
+               MemberList GetMembers (MemberTypes mt, BindingFlags bf);
+
+               /// <summary>
+               ///   Return the container's member cache.
+               /// </summary>
+               MemberCache MemberCache {
+                       get;
+               }
+       }
+
+       /// <summary>
+       ///   The MemberCache is used by dynamic and non-dynamic types to speed up
+       ///   member lookups.  It has a member name based hash table; it maps each member
+       ///   name to a list of CacheEntry objects.  Each CacheEntry contains a MemberInfo
+       ///   and the BindingFlags that were initially used to get it.  The cache contains
+       ///   all members of the current class and all inherited members.  If this cache is
+       ///   for an interface types, it also contains all inherited members.
+       ///
+       ///   There are two ways to get a MemberCache:
+       ///   * if this is a dynamic type, lookup the corresponding DeclSpace and then
+       ///     use the DeclSpace.MemberCache property.
+       ///   * if this not a dynamic type, call TypeHandle.GetTypeHandle() to get a
+       ///     TypeHandle instance for the type and then use TypeHandle.MemberCache.
+       /// </summary>
+       public class MemberCache {
+               public readonly IMemberContainer Container;
+               protected Hashtable member_hash;
+               protected Hashtable method_hash;
+
+               /// <summary>
+               ///   Create a new MemberCache for the given IMemberContainer `container'.
+               /// </summary>
+               public MemberCache (IMemberContainer container)
+               {
+                       this.Container = container;
+
+                       Timer.IncrementCounter (CounterType.MemberCache);
+                       Timer.StartTimer (TimerType.CacheInit);
+
+                       // If we have a base class (we have a base class unless we're
+                       // TypeManager.object_type), we deep-copy its MemberCache here.
+                       if (Container.BaseCache != null)
+                               member_hash = SetupCache (Container.BaseCache);
+                       else
+                               member_hash = new Hashtable ();
+
+                       // If this is neither a dynamic type nor an interface, create a special
+                       // method cache with all declared and inherited methods.
+                       Type type = container.Type;
+                       if (!(type is TypeBuilder) && !type.IsInterface &&
+                           // !(type.IsGenericType && (type.GetGenericTypeDefinition () is TypeBuilder)) &&
+                           !TypeManager.IsGenericType (type) &&
+                           (Container.BaseCache == null || Container.BaseCache.method_hash != null)) {
+                               method_hash = new Hashtable ();
+                               AddMethods (type);
+                       }
+
+                       // Add all members from the current class.
+                       AddMembers (Container);
+
+                       Timer.StopTimer (TimerType.CacheInit);
+               }
+
+               public MemberCache (Type[] ifaces)
+               {
+                       //
+                       // The members of this cache all belong to other caches.  
+                       // So, 'Container' will not be used.
+                       //
+                       this.Container = null;
+
+                       member_hash = new Hashtable ();
+                       if (ifaces == null)
+                               return;
+
+                       foreach (Type itype in ifaces)
+                               AddCacheContents (TypeManager.LookupMemberCache (itype));
+               }
+
+               /// <summary>
+               ///   Bootstrap this member cache by doing a deep-copy of our base.
+               /// </summary>
+               static Hashtable SetupCache (MemberCache base_class)
+               {
+                       Hashtable hash = new Hashtable ();
+
+                       if (base_class == null)
+                               return hash;
+
+                       IDictionaryEnumerator it = base_class.member_hash.GetEnumerator ();
+                       while (it.MoveNext ()) {
+                               hash [it.Key] = ((ArrayList) it.Value).Clone ();
+                        }
+                                
+                       return hash;
+               }
+
+               /// <summary>
+               ///   Add the contents of `cache' to the member_hash.
+               /// </summary>
+               void AddCacheContents (MemberCache cache)
+               {
+                       IDictionaryEnumerator it = cache.member_hash.GetEnumerator ();
+                       while (it.MoveNext ()) {
+                               ArrayList list = (ArrayList) member_hash [it.Key];
+                               if (list == null)
+                                       member_hash [it.Key] = list = new ArrayList ();
+
+                               ArrayList entries = (ArrayList) it.Value;
+                               for (int i = entries.Count-1; i >= 0; i--) {
+                                       CacheEntry entry = (CacheEntry) entries [i];
+
+                                       if (entry.Container != cache.Container)
+                                               break;
+                                       list.Add (entry);
+                               }
+                       }
+               }
+
+               /// <summary>
+               ///   Add all members from class `container' to the cache.
+               /// </summary>
+               void AddMembers (IMemberContainer container)
+               {
+                       // We need to call AddMembers() with a single member type at a time
+                       // to get the member type part of CacheEntry.EntryType right.
+                       if (!container.IsInterface) {
+                               AddMembers (MemberTypes.Constructor, container);
+                               AddMembers (MemberTypes.Field, container);
+                       }
+                       AddMembers (MemberTypes.Method, container);
+                       AddMembers (MemberTypes.Property, container);
+                       AddMembers (MemberTypes.Event, container);
+                       // Nested types are returned by both Static and Instance searches.
+                       AddMembers (MemberTypes.NestedType,
+                                   BindingFlags.Static | BindingFlags.Public, container);
+                       AddMembers (MemberTypes.NestedType,
+                                   BindingFlags.Static | BindingFlags.NonPublic, container);
+               }
+
+               void AddMembers (MemberTypes mt, IMemberContainer container)
+               {
+                       AddMembers (mt, BindingFlags.Static | BindingFlags.Public, container);
+                       AddMembers (mt, BindingFlags.Static | BindingFlags.NonPublic, container);
+                       AddMembers (mt, BindingFlags.Instance | BindingFlags.Public, container);
+                       AddMembers (mt, BindingFlags.Instance | BindingFlags.NonPublic, container);
+               }
+
+               /// <summary>
+               ///   Add all members from class `container' with the requested MemberTypes and
+               ///   BindingFlags to the cache.  This method is called multiple times with different
+               ///   MemberTypes and BindingFlags.
+               /// </summary>
+               void AddMembers (MemberTypes mt, BindingFlags bf, IMemberContainer container)
+               {
+                       MemberList members = container.GetMembers (mt, bf);
+
+                       foreach (MemberInfo member in members) {
+                               string name = member.Name;
+
+                               int pos = name.IndexOf ('<');
+                               if (pos > 0)
+                                       name = name.Substring (0, pos);
+
+                               // We use a name-based hash table of ArrayList's.
+                               ArrayList list = (ArrayList) member_hash [name];
+                               if (list == null) {
+                                       list = new ArrayList ();
+                                       member_hash.Add (name, list);
+                               }
+
+                               // When this method is called for the current class, the list will
+                               // already contain all inherited members from our base classes.
+                               // We cannot add new members in front of the list since this'd be an
+                               // expensive operation, that's why the list is sorted in reverse order
+                               // (ie. members from the current class are coming last).
+                               list.Add (new CacheEntry (container, member, mt, bf));
+                       }
+               }
+
+               /// <summary>
+               ///   Add all declared and inherited methods from class `type' to the method cache.
+               /// </summary>
+               void AddMethods (Type type)
+               {
+                       AddMethods (BindingFlags.Static | BindingFlags.Public |
+                                   BindingFlags.FlattenHierarchy, type);
+                       AddMethods (BindingFlags.Static | BindingFlags.NonPublic |
+                                   BindingFlags.FlattenHierarchy, type);
+                       AddMethods (BindingFlags.Instance | BindingFlags.Public, type);
+                       AddMethods (BindingFlags.Instance | BindingFlags.NonPublic, type);
+               }
+
+               static ArrayList overrides = new ArrayList ();
+
+               void AddMethods (BindingFlags bf, Type type)
+               {
+                       MethodBase [] members = type.GetMethods (bf);
+
+                        Array.Reverse (members);
+
+                       foreach (MethodBase member in members) {
+                               string name = member.Name;
+
+                               // We use a name-based hash table of ArrayList's.
+                               ArrayList list = (ArrayList) method_hash [name];
+                               if (list == null) {
+                                       list = new ArrayList ();
+                                       method_hash.Add (name, list);
+                               }
+
+                               MethodInfo curr = (MethodInfo) member;
+                               while (curr.IsVirtual && (curr.Attributes & MethodAttributes.NewSlot) == 0) {
+                                       MethodInfo base_method = curr.GetBaseDefinition ();
+
+                                       if (base_method == curr)
+                                               // Not every virtual function needs to have a NewSlot flag.
+                                               break;
+
+                                       overrides.Add (curr);
+                                       list.Add (new CacheEntry (null, base_method, MemberTypes.Method, bf));
+                                       curr = base_method;
+                               }
+
+                               if (overrides.Count > 0) {
+                                       for (int i = 0; i < overrides.Count; ++i)
+                                               TypeManager.RegisterOverride ((MethodBase) overrides [i], curr);
+                                       overrides.Clear ();
+                               }
+
+                               // Unfortunately, the elements returned by Type.GetMethods() aren't
+                               // sorted so we need to do this check for every member.
+                               BindingFlags new_bf = bf;
+                               if (member.DeclaringType == type)
+                                       new_bf |= BindingFlags.DeclaredOnly;
+
+                               list.Add (new CacheEntry (Container, member, MemberTypes.Method, new_bf));
+                       }
+               }
+
+               /// <summary>
+               ///   Compute and return a appropriate `EntryType' magic number for the given
+               ///   MemberTypes and BindingFlags.
+               /// </summary>
+               protected static EntryType GetEntryType (MemberTypes mt, BindingFlags bf)
+               {
+                       EntryType type = EntryType.None;
+
+                       if ((mt & MemberTypes.Constructor) != 0)
+                               type |= EntryType.Constructor;
+                       if ((mt & MemberTypes.Event) != 0)
+                               type |= EntryType.Event;
+                       if ((mt & MemberTypes.Field) != 0)
+                               type |= EntryType.Field;
+                       if ((mt & MemberTypes.Method) != 0)
+                               type |= EntryType.Method;
+                       if ((mt & MemberTypes.Property) != 0)
+                               type |= EntryType.Property;
+                       // Nested types are returned by static and instance searches.
+                       if ((mt & MemberTypes.NestedType) != 0)
+                               type |= EntryType.NestedType | EntryType.Static | EntryType.Instance;
+
+                       if ((bf & BindingFlags.Instance) != 0)
+                               type |= EntryType.Instance;
+                       if ((bf & BindingFlags.Static) != 0)
+                               type |= EntryType.Static;
+                       if ((bf & BindingFlags.Public) != 0)
+                               type |= EntryType.Public;
+                       if ((bf & BindingFlags.NonPublic) != 0)
+                               type |= EntryType.NonPublic;
+                       if ((bf & BindingFlags.DeclaredOnly) != 0)
+                               type |= EntryType.Declared;
+
+                       return type;
+               }
+
+               /// <summary>
+               ///   The `MemberTypes' enumeration type is a [Flags] type which means that it may
+               ///   denote multiple member types.  Returns true if the given flags value denotes a
+               ///   single member types.
+               /// </summary>
+               public static bool IsSingleMemberType (MemberTypes mt)
+               {
+                       switch (mt) {
+                       case MemberTypes.Constructor:
+                       case MemberTypes.Event:
+                       case MemberTypes.Field:
+                       case MemberTypes.Method:
+                       case MemberTypes.Property:
+                       case MemberTypes.NestedType:
+                               return true;
+
+                       default:
+                               return false;
+                       }
+               }
+
+               /// <summary>
+               ///   We encode the MemberTypes and BindingFlags of each members in a "magic"
+               ///   number to speed up the searching process.
+               /// </summary>
+               [Flags]
+               protected enum EntryType {
+                       None            = 0x000,
+
+                       Instance        = 0x001,
+                       Static          = 0x002,
+                       MaskStatic      = Instance|Static,
+
+                       Public          = 0x004,
+                       NonPublic       = 0x008,
+                       MaskProtection  = Public|NonPublic,
+
+                       Declared        = 0x010,
+
+                       Constructor     = 0x020,
+                       Event           = 0x040,
+                       Field           = 0x080,
+                       Method          = 0x100,
+                       Property        = 0x200,
+                       NestedType      = 0x400,
+
+                       MaskType        = Constructor|Event|Field|Method|Property|NestedType
+               }
+
+               protected class CacheEntry {
+                       public readonly IMemberContainer Container;
+                       public readonly EntryType EntryType;
+                       public readonly MemberInfo Member;
+
+                       public CacheEntry (IMemberContainer container, MemberInfo member,
+                                          MemberTypes mt, BindingFlags bf)
+                       {
+                               this.Container = container;
+                               this.Member = member;
+                               this.EntryType = GetEntryType (mt, bf);
+                       }
+
+                       public override string ToString ()
+                       {
+                               return String.Format ("CacheEntry ({0}:{1}:{2})", Container.Name,
+                                                     EntryType, Member);
+                       }
+               }
+
+               /// <summary>
+               ///   This is called each time we're walking up one level in the class hierarchy
+               ///   and checks whether we can abort the search since we've already found what
+               ///   we were looking for.
+               /// </summary>
+               protected bool DoneSearching (ArrayList list)
+               {
+                       //
+                       // We've found exactly one member in the current class and it's not
+                       // a method or constructor.
+                       //
+                       if (list.Count == 1 && !(list [0] is MethodBase))
+                               return true;
+
+                       //
+                       // Multiple properties: we query those just to find out the indexer
+                       // name
+                       //
+                       if ((list.Count > 0) && (list [0] is PropertyInfo))
+                               return true;
+
+                       return false;
+               }
+
+               /// <summary>
+               ///   Looks up members with name `name'.  If you provide an optional
+               ///   filter function, it'll only be called with members matching the
+               ///   requested member name.
+               ///
+               ///   This method will try to use the cache to do the lookup if possible.
+               ///
+               ///   Unlike other FindMembers implementations, this method will always
+               ///   check all inherited members - even when called on an interface type.
+               ///
+               ///   If you know that you're only looking for methods, you should use
+               ///   MemberTypes.Method alone since this speeds up the lookup a bit.
+               ///   When doing a method-only search, it'll try to use a special method
+               ///   cache (unless it's a dynamic type or an interface) and the returned
+               ///   MemberInfo's will have the correct ReflectedType for inherited methods.
+               ///   The lookup process will automatically restart itself in method-only
+               ///   search mode if it discovers that it's about to return methods.
+               /// </summary>
+               ArrayList global = new ArrayList ();
+               bool using_global = false;
+               
+               static MemberInfo [] emptyMemberInfo = new MemberInfo [0];
+               
+               public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf, string name,
+                                                 MemberFilter filter, object criteria)
+               {
+                       if (using_global)
+                               throw new Exception ();
+                       
+                       bool declared_only = (bf & BindingFlags.DeclaredOnly) != 0;
+                       bool method_search = mt == MemberTypes.Method;
+                       // If we have a method cache and we aren't already doing a method-only search,
+                       // then we restart a method search if the first match is a method.
+                       bool do_method_search = !method_search && (method_hash != null);
+
+                       ArrayList applicable;
+
+                       // If this is a method-only search, we try to use the method cache if
+                       // possible; a lookup in the method cache will return a MemberInfo with
+                       // the correct ReflectedType for inherited methods.
+                       
+                       if (method_search && (method_hash != null))
+                               applicable = (ArrayList) method_hash [name];
+                       else
+                               applicable = (ArrayList) member_hash [name];
+
+                       if (applicable == null)
+                               return emptyMemberInfo;
+
+                       //
+                       // 32  slots gives 53 rss/54 size
+                       // 2/4 slots gives 55 rss
+                       //
+                       // Strange: from 25,000 calls, only 1,800
+                       // are above 2.  Why does this impact it?
+                       //
+                       global.Clear ();
+                       using_global = true;
+
+                       Timer.StartTimer (TimerType.CachedLookup);
+
+                       EntryType type = GetEntryType (mt, bf);
+
+                       IMemberContainer current = Container;
+
+                       bool do_interface_search = current.IsInterface;
+
+                       // `applicable' is a list of all members with the given member name `name'
+                       // in the current class and all its base classes.  The list is sorted in
+                       // reverse order due to the way how the cache is initialy created (to speed
+                       // things up, we're doing a deep-copy of our base).
+
+                       for (int i = applicable.Count-1; i >= 0; i--) {
+                               CacheEntry entry = (CacheEntry) applicable [i];
+
+                               // This happens each time we're walking one level up in the class
+                               // hierarchy.  If we're doing a DeclaredOnly search, we must abort
+                               // the first time this happens (this may already happen in the first
+                               // iteration of this loop if there are no members with the name we're
+                               // looking for in the current class).
+                               if (entry.Container != current) {
+                                       if (declared_only)
+                                               break;
+
+                                       if (!do_interface_search && DoneSearching (global))
+                                               break;
+
+                                       current = entry.Container;
+                               }
+
+                               // Is the member of the correct type ?
+                               if ((entry.EntryType & type & EntryType.MaskType) == 0)
+                                       continue;
+
+                               // Is the member static/non-static ?
+                               if ((entry.EntryType & type & EntryType.MaskStatic) == 0)
+                                       continue;
+
+                               // Apply the filter to it.
+                               if (filter (entry.Member, criteria)) {
+                                       if ((entry.EntryType & EntryType.MaskType) != EntryType.Method) {
+                                               do_method_search = false;
+                                       }
+                                       
+                                       // Because interfaces support multiple inheritance we have to be sure that
+                                       // base member is from same interface, so only top level member will be returned
+                                       if (do_interface_search && global.Count > 0) {
+                                               bool member_already_exists = false;
+
+                                               foreach (MemberInfo mi in global) {
+                                                       if (mi is MethodBase)
+                                                               continue;
+
+                                                       if (IsInterfaceBaseInterface (TypeManager.GetInterfaces (mi.DeclaringType), entry.Member.DeclaringType)) {
+                                                               member_already_exists = true;
+                                                               break;
+                                                       }
+                                               }
+                                               if (member_already_exists)
+                                                       continue;
+                                       }
+
+                                       global.Add (entry.Member);
+                               }
+                       }
+
+                       Timer.StopTimer (TimerType.CachedLookup);
+
+                       // If we have a method cache and we aren't already doing a method-only
+                       // search, we restart in method-only search mode if the first match is
+                       // a method.  This ensures that we return a MemberInfo with the correct
+                       // ReflectedType for inherited methods.
+                       if (do_method_search && (global.Count > 0)){
+                               using_global = false;
+
+                               return FindMembers (MemberTypes.Method, bf, name, filter, criteria);
+                       }
+
+                       using_global = false;
+                       MemberInfo [] copy = new MemberInfo [global.Count];
+                       global.CopyTo (copy);
+                       return copy;
+               }
+
+               /// <summary>
+               /// Returns true if iterface exists in any base interfaces (ifaces)
+               /// </summary>
+               static bool IsInterfaceBaseInterface (Type[] ifaces, Type ifaceToFind)
+               {
+                       foreach (Type iface in ifaces) {
+                               if (iface == ifaceToFind)
+                                       return true;
+
+                               Type[] base_ifaces = TypeManager.GetInterfaces (iface);
+                               if (base_ifaces.Length > 0 && IsInterfaceBaseInterface (base_ifaces, ifaceToFind))
+                                       return true;
+                       }
+                       return false;
+               }
+               
+               // find the nested type @name in @this.
+               public Type FindNestedType (string name)
+               {
+                       ArrayList applicable = (ArrayList) member_hash [name];
+                       if (applicable == null)
+                               return null;
+                       
+                       for (int i = applicable.Count-1; i >= 0; i--) {
+                               CacheEntry entry = (CacheEntry) applicable [i];
+                               if ((entry.EntryType & EntryType.NestedType & EntryType.MaskType) != 0)
+                                       return (Type) entry.Member;
+                       }
+                       
+                       return null;
+               }
+               
+               //
+               // This finds the method or property for us to override. invocationType is the type where
+               // the override is going to be declared, name is the name of the method/property, and
+               // paramTypes is the parameters, if any to the method or property
+               //
+               // Because the MemberCache holds members from this class and all the base classes,
+               // we can avoid tons of reflection stuff.
+               //
+               public MemberInfo FindMemberToOverride (Type invocationType, string name, Type [] paramTypes, GenericMethod genericMethod, bool is_property)
+               {
+                       ArrayList applicable;
+                       if (method_hash != null && !is_property)
+                               applicable = (ArrayList) method_hash [name];
+                       else
+                               applicable = (ArrayList) member_hash [name];
+                       
+                       if (applicable == null)
+                               return null;
+                       //
+                       // Walk the chain of methods, starting from the top.
+                       //
+                       for (int i = applicable.Count - 1; i >= 0; i--) {
+                               CacheEntry entry = (CacheEntry) applicable [i];
+                               
+                               if ((entry.EntryType & (is_property ? (EntryType.Property | EntryType.Field) : EntryType.Method)) == 0)
+                                       continue;
+
+                               PropertyInfo pi = null;
+                               MethodInfo mi = null;
+                               FieldInfo fi = null;
+                               Type [] cmpAttrs = null;
+                               
+                               if (is_property) {
+                                       if ((entry.EntryType & EntryType.Field) != 0) {
+                                               fi = (FieldInfo)entry.Member;
+
+                                               // TODO: For this case we ignore member type
+                                               //fb = TypeManager.GetField (fi);
+                                               //cmpAttrs = new Type[] { fb.MemberType };
+                                       } else {
+                                               pi = (PropertyInfo) entry.Member;
+                                               cmpAttrs = TypeManager.GetArgumentTypes (pi);
+                                       }
+                               } else {
+                                       mi = (MethodInfo) entry.Member;
+                                       cmpAttrs = TypeManager.GetParameterData (mi).Types;
+                               }
+
+                               if (fi != null) {
+                                       // TODO: Almost duplicate !
+                                       // Check visibility
+                                       switch (fi.Attributes & FieldAttributes.FieldAccessMask) {
+                                       case FieldAttributes.PrivateScope:
+                                               continue;
+                                       case FieldAttributes.Private:
+                                               //
+                                               // A private method is Ok if we are a nested subtype.
+                                               // The spec actually is not very clear about this, see bug 52458.
+                                               //
+                                               if (!invocationType.Equals (entry.Container.Type) &&
+                                                   !TypeManager.IsNestedChildOf (invocationType, entry.Container.Type))
+                                                       continue;
+                                               break;
+                                       case FieldAttributes.FamANDAssem:
+                                       case FieldAttributes.Assembly:
+                                               //
+                                               // Check for assembly methods
+                                               //
+                                               if (mi.DeclaringType.Assembly != CodeGen.Assembly.Builder)
+                                                       continue;
+                                               break;
+                                       }
+                                       return entry.Member;
+                               }
+
+                               //
+                               // Check the arguments
+                               //
+                               if (cmpAttrs.Length != paramTypes.Length)
+                                       continue;
+       
+                               int j;
+                               for (j = 0; j < cmpAttrs.Length; ++j)
+                                       if (!TypeManager.IsEqual (paramTypes [j], cmpAttrs [j]))
+                                               break;
+                               if (j < cmpAttrs.Length)
+                                       continue;
+
+                               //
+                               // check generic arguments for methods
+                               //
+                               if (mi != null) {
+                                       Type [] cmpGenArgs = TypeManager.GetGenericArguments (mi);
+                                       if (genericMethod == null && cmpGenArgs.Length != 0)
+                                               continue;
+                                       if (genericMethod != null && cmpGenArgs.Length != genericMethod.TypeParameters.Length)
+                                               continue;
+                               }
+
+                               //
+                               // get one of the methods because this has the visibility info.
+                               //
+                               if (is_property) {
+                                       mi = pi.GetGetMethod (true);
+                                       if (mi == null)
+                                               mi = pi.GetSetMethod (true);
+                               }
+                               
+                               //
+                               // Check visibility
+                               //
+                               switch (mi.Attributes & MethodAttributes.MemberAccessMask) {
+                               case MethodAttributes.PrivateScope:
+                                       continue;
+                               case MethodAttributes.Private:
+                                       //
+                                       // A private method is Ok if we are a nested subtype.
+                                       // The spec actually is not very clear about this, see bug 52458.
+                                       //
+                                       if (!invocationType.Equals (entry.Container.Type) &&
+                                           !TypeManager.IsNestedChildOf (invocationType, entry.Container.Type))
+                                               continue;
+                                       break;
+                               case MethodAttributes.FamANDAssem:
+                               case MethodAttributes.Assembly:
+                                       //
+                                       // Check for assembly methods
+                                       //
+                                       if (mi.DeclaringType.Assembly != CodeGen.Assembly.Builder)
+                                               continue;
+                                       break;
+                               }
+                               return entry.Member;
+                       }
+                       
+                       return null;
+               }
+
+               /// <summary>
+               /// The method is looking for conflict with inherited symbols (errors CS0108, CS0109).
+               /// We handle two cases. The first is for types without parameters (events, field, properties).
+               /// The second are methods, indexers and this is why ignore_complex_types is here.
+               /// The latest param is temporary hack. See DoDefineMembers method for more info.
+               /// </summary>
+               public MemberInfo FindMemberWithSameName (string name, bool ignore_complex_types, MemberInfo ignore_member)
+               {
+                       ArrayList applicable = null;
+                       if (method_hash != null)
+                               applicable = (ArrayList) method_hash [name];
+                       if (applicable != null) {
+                               for (int i = applicable.Count - 1; i >= 0; i--) {
+                                       CacheEntry entry = (CacheEntry) applicable [i];
+                                       if ((entry.EntryType & EntryType.Public) != 0)
+                                               return entry.Member;
+                               }
+                       }
+                       if (member_hash == null)
+                               return null;
+                       applicable = (ArrayList) member_hash [name];
+                       
+                       if (applicable != null) {
+                               for (int i = applicable.Count - 1; i >= 0; i--) {
+                                       CacheEntry entry = (CacheEntry) applicable [i];
+                                       if ((entry.EntryType & EntryType.Public) != 0 & entry.Member != ignore_member) {
+                                               if (ignore_complex_types) {
+                                                       if ((entry.EntryType & EntryType.Method) != 0)
+                                                               continue;
+                                                       // Does exist easier way how to detect indexer ?
+                                                       if ((entry.EntryType & EntryType.Property) != 0) {
+                                                               Type[] arg_types = TypeManager.GetArgumentTypes ((PropertyInfo)entry.Member);
+                                                               if (arg_types.Length > 0)
+                                                                       continue;
+                                                       }
+                                               }
+                                               return entry.Member;
+                                       }
+                               }
+                       }
+                       return null;
+               }
+
+               Hashtable locase_table;
+               /// <summary>
+               /// Builds low-case table for CLS Compliance test
+               /// </summary>
+               public Hashtable GetPublicMembers ()
+               {
+                       if (locase_table != null)
+                               return locase_table;
+                       locase_table = new Hashtable ();
+                       foreach (DictionaryEntry entry in member_hash) {
+                               ArrayList members = (ArrayList)entry.Value;
+                               for (int ii = 0; ii < members.Count; ++ii) {
+                                       CacheEntry member_entry = (CacheEntry) members [ii];
+                                       if ((member_entry.EntryType & EntryType.Public) == 0)
+                                               continue;
+                                       // TODO: Does anyone know easier way how to detect that member is internal ?
+                                       switch (member_entry.EntryType & EntryType.MaskType) {
+                                               case EntryType.Constructor:
+                                                       continue;
+                                               case EntryType.Field:
+                                                       if ((((FieldInfo)member_entry.Member).Attributes & (FieldAttributes.Assembly | FieldAttributes.Public)) == FieldAttributes.Assembly)
+                                                               continue;
+                                                       break;
+                                               case EntryType.Method:
+                                                       if ((((MethodInfo)member_entry.Member).Attributes & (MethodAttributes.Assembly | MethodAttributes.Public)) == MethodAttributes.Assembly)
+                                                               continue;
+                                                       break;
+                                               case EntryType.Property:
+                                                       PropertyInfo pi = (PropertyInfo)member_entry.Member;
+                                                       if (pi.GetSetMethod () == null && pi.GetGetMethod () == null)
+                                                               continue;
+                                                       break;
+                                               case EntryType.Event:
+                                                       EventInfo ei = (EventInfo)member_entry.Member;
+                                                       MethodInfo mi = ei.GetAddMethod ();
+                                                       if ((mi.Attributes & (MethodAttributes.Assembly | MethodAttributes.Public)) == MethodAttributes.Assembly)
+                                                               continue;
+                                                       break;
+                                       }
+                                       string lcase = ((string)entry.Key).ToLower (System.Globalization.CultureInfo.InvariantCulture);
+                                       locase_table [lcase] = member_entry.Member;
+                                       break;
+                               }
+                       }
+                       return locase_table;
+               }
+               public Hashtable Members {
+                       get {
+                               return member_hash;
+                       }
+               }
+               /// <summary>
+               /// Cls compliance check whether methods or constructors parameters differing only in ref or out, or in array rank
+               /// </summary>
+               /// 
+               // TODO: refactor as method is always 'this'
+               public static void VerifyClsParameterConflict (ArrayList al, MethodCore method, MemberInfo this_builder)
+               {
+                       EntryType tested_type = (method is Constructor ? EntryType.Constructor : EntryType.Method) | EntryType.Public;
+                       for (int i = 0; i < al.Count; ++i) {
+                               MemberCache.CacheEntry entry = (MemberCache.CacheEntry) al [i];
+               
+                               // skip itself
+                               if (entry.Member == this_builder)
+                                       continue;
+               
+                               if ((entry.EntryType & tested_type) != tested_type)
+                                       continue;
+               
+                               MethodBase method_to_compare = (MethodBase)entry.Member;
+                               AttributeTester.Result result = AttributeTester.AreOverloadedMethodParamsClsCompliant (
+                                       method.ParameterTypes, TypeManager.GetParameterData (method_to_compare).Types);
+
+                               if (result == AttributeTester.Result.Ok)
+                                       continue;
+
+                               IMethodData md = TypeManager.GetMethod (method_to_compare);
+
+                               // TODO: now we are ignoring CLSCompliance(false) on method from other assembly which is buggy.
+                               // However it is exactly what csc does.
+                               if (md != null && !md.IsClsComplianceRequired ())
+                                       continue;
+               
+                               Report.SymbolRelatedToPreviousError (entry.Member);
+                               switch (result) {
+                                       case AttributeTester.Result.RefOutArrayError:
+                                               Report.Error (3006, method.Location, "Overloaded method `{0}' differing only in ref or out, or in array rank, is not CLS-compliant", method.GetSignatureForError ());
+                                               continue;
+                                       case AttributeTester.Result.ArrayArrayError:
+                                               Report.Error (3007, method.Location, "Overloaded method `{0}' differing only by unnamed array types is not CLS-compliant", method.GetSignatureForError ());
+                                               continue;
+                               }
+
+                               throw new NotImplementedException (result.ToString ());
+                       }
+               }
+       }
+}
diff --git a/mcs/mcs/delegate.cs b/mcs/mcs/delegate.cs
new file mode 100644 (file)
index 0000000..0c55213
--- /dev/null
@@ -0,0 +1,972 @@
+//
+// delegate.cs: Delegate Handler
+//
+// Authors:
+//     Ravi Pratap (ravi@ximian.com)
+//     Miguel de Icaza (miguel@ximian.com)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+//
+//
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Text;
+
+namespace Mono.CSharp {
+
+       /// <summary>
+       ///   Holds Delegates
+       /// </summary>
+       public class Delegate : DeclSpace {
+               public Expression ReturnType;
+               public Parameters      Parameters;
+
+               public ConstructorBuilder ConstructorBuilder;
+               public MethodBuilder      InvokeBuilder;
+               public MethodBuilder      BeginInvokeBuilder;
+               public MethodBuilder      EndInvokeBuilder;
+               
+               Type ret_type;
+
+               static string[] attribute_targets = new string [] { "type", "return" };
+               
+               Expression instance_expr;
+               MethodBase delegate_method;
+               ReturnParameter return_attributes;
+       
+               const int AllowedModifiers =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.UNSAFE |
+                       Modifiers.PRIVATE;
+
+               public Delegate (NamespaceEntry ns, DeclSpace parent, Expression type,
+                                int mod_flags, MemberName name, Parameters param_list,
+                                Attributes attrs)
+                       : base (ns, parent, name, attrs)
+
+               {
+                       this.ReturnType = type;
+                       ModFlags        = Modifiers.Check (AllowedModifiers, mod_flags,
+                                                          IsTopLevel ? Modifiers.INTERNAL :
+                                                          Modifiers.PRIVATE, name.Location);
+                       Parameters      = param_list;
+               }
+
+               public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
+               {
+                       if (a.Target == AttributeTargets.ReturnValue) {
+                               if (return_attributes == null)
+                                       return_attributes = new ReturnParameter (InvokeBuilder, Location);
+
+                               return_attributes.ApplyAttributeBuilder (a, cb);
+                               return;
+                       }
+
+                       base.ApplyAttributeBuilder (a, cb);
+               }
+
+               public override TypeBuilder DefineType ()
+               {
+                       if (TypeBuilder != null)
+                               return TypeBuilder;
+
+                       if (TypeManager.multicast_delegate_type == null && !RootContext.StdLib) {
+                               Namespace system = RootNamespace.Global.GetNamespace ("System", true);
+                               TypeExpr expr = system.Lookup (this, "MulticastDelegate", Location) as TypeExpr;
+                               TypeManager.multicast_delegate_type = expr.Type;
+                       }
+
+                       if (TypeManager.multicast_delegate_type == null)
+                               Report.Error (-100, Location, "Internal error: delegate used before " +
+                                             "System.MulticastDelegate is resolved.  This can only " +
+                                             "happen during corlib compilation, when using a delegate " +
+                                             "in any of the `core' classes.  See bug #72015 for details.");
+
+                       if (IsTopLevel) {
+                               if (TypeManager.NamespaceClash (Name, Location))
+                                       return null;
+                               
+                               ModuleBuilder builder = CodeGen.Module.Builder;
+
+                               TypeBuilder = builder.DefineType (
+                                       Name, TypeAttr, TypeManager.multicast_delegate_type);
+                       } else {
+                               TypeBuilder builder = Parent.TypeBuilder;
+
+                               string name = Name.Substring (1 + Name.LastIndexOf ('.'));
+                               TypeBuilder = builder.DefineNestedType (
+                                       name, TypeAttr, TypeManager.multicast_delegate_type);
+                       }
+
+                       TypeManager.AddUserType (this);
+
+#if GMCS_SOURCE
+                       if (IsGeneric) {
+                               string[] param_names = new string [TypeParameters.Length];
+                               for (int i = 0; i < TypeParameters.Length; i++)
+                                       param_names [i] = TypeParameters [i].Name;
+
+                               GenericTypeParameterBuilder[] gen_params;
+                               gen_params = TypeBuilder.DefineGenericParameters (param_names);
+
+                               int offset = CountTypeParameters - CurrentTypeParameters.Length;
+                               for (int i = offset; i < gen_params.Length; i++)
+                                       CurrentTypeParameters [i - offset].Define (gen_params [i]);
+
+                               foreach (TypeParameter type_param in CurrentTypeParameters) {
+                                       if (!type_param.Resolve (this))
+                                               return null;
+                               }
+
+                               Expression current = new SimpleName (
+                                       MemberName.Basename, TypeParameters, Location);
+                               current = current.ResolveAsTypeTerminal (this, false);
+                               if (current == null)
+                                       return null;
+
+                               CurrentType = current.Type;
+                       }
+#endif
+
+                       return TypeBuilder;
+               }
+
+               public override bool Define ()
+               {
+#if GMCS_SOURCE
+                       if (IsGeneric) {
+                               foreach (TypeParameter type_param in TypeParameters) {
+                                       if (!type_param.Resolve (this))
+                                               return false;
+                               }
+
+                               foreach (TypeParameter type_param in TypeParameters) {
+                                       if (!type_param.DefineType (this))
+                                               return false;
+                               }
+
+                               foreach (TypeParameter type_param in TypeParameters) {
+                                       if (!type_param.CheckDependencies ())
+                                               return false;
+                               }
+                       }
+#endif
+
+                       // FIXME: POSSIBLY make this static, as it is always constant
+                       //
+                       Type [] const_arg_types = new Type [2];
+                       const_arg_types [0] = TypeManager.object_type;
+                       const_arg_types [1] = TypeManager.intptr_type;
+
+                       const MethodAttributes ctor_mattr = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName |
+                               MethodAttributes.HideBySig | MethodAttributes.Public;
+
+                       ConstructorBuilder = TypeBuilder.DefineConstructor (ctor_mattr,
+                                                                           CallingConventions.Standard,
+                                                                           const_arg_types);
+
+                       ConstructorBuilder.DefineParameter (1, ParameterAttributes.None, "object");
+                       ConstructorBuilder.DefineParameter (2, ParameterAttributes.None, "method");
+                       //
+                       // HACK because System.Reflection.Emit is lame
+                       //
+                       Parameter [] fixed_pars = new Parameter [2];
+                       fixed_pars [0] = new Parameter (TypeManager.object_type, "object",
+                                                       Parameter.Modifier.NONE, null, Location);
+                       fixed_pars [1] = new Parameter (TypeManager.intptr_type, "method", 
+                                                       Parameter.Modifier.NONE, null, Location);
+                       Parameters const_parameters = new Parameters (fixed_pars);
+                       const_parameters.Resolve (null);
+                       
+                       TypeManager.RegisterMethod (ConstructorBuilder, const_parameters);
+                               
+                       
+                       ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
+
+                       //
+                       // Here the various methods like Invoke, BeginInvoke etc are defined
+                       //
+                       // First, call the `out of band' special method for
+                       // defining recursively any types we need:
+                       
+                       if (!Parameters.Resolve (this))
+                               return false;
+
+                       //
+                       // Invoke method
+                       //
+
+                       // Check accessibility
+                       foreach (Type partype in Parameters.Types){
+                               if (!Parent.AsAccessible (partype, ModFlags)) {
+                                       Report.Error (59, Location,
+                                                     "Inconsistent accessibility: parameter type `" +
+                                                     TypeManager.CSharpName (partype) + "' is less " +
+                                                     "accessible than delegate `" + Name + "'");
+                                       return false;
+                               }
+                       }
+                       
+                       ReturnType = ReturnType.ResolveAsTypeTerminal (this, false);
+                       if (ReturnType == null)
+                               return false;
+
+                       ret_type = ReturnType.Type;
+            
+                       if (!Parent.AsAccessible (ret_type, ModFlags)) {
+                               Report.Error (58, Location,
+                                             "Inconsistent accessibility: return type `" +
+                                             TypeManager.CSharpName (ret_type) + "' is less " +
+                                             "accessible than delegate `" + Name + "'");
+                               return false;
+                       }
+
+                       if (RootContext.StdLib && (ret_type == TypeManager.arg_iterator_type || ret_type == TypeManager.typed_reference_type)) {
+                               Method.Error1599 (Location, ret_type);
+                               return false;
+                       }
+
+                       //
+                       // We don't have to check any others because they are all
+                       // guaranteed to be accessible - they are standard types.
+                       //
+                       
+                       CallingConventions cc = Parameters.CallingConvention;
+
+                       const MethodAttributes mattr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.NewSlot;
+
+                       InvokeBuilder = TypeBuilder.DefineMethod ("Invoke", 
+                                                                 mattr,                     
+                                                                 cc,
+                                                                 ret_type,                  
+                                                                 Parameters.Types);
+                       
+                       InvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
+
+                       TypeManager.RegisterMethod (InvokeBuilder, Parameters);
+
+                       //
+                       // BeginInvoke
+                       //
+                       
+                       Parameters async_parameters = Parameters.MergeGenerated (Parameters, 
+                               new Parameter (TypeManager.asynccallback_type, "callback", Parameter.Modifier.NONE, null, Location),
+                               new Parameter (TypeManager.object_type, "object", Parameter.Modifier.NONE, null, Location));
+                       
+                       BeginInvokeBuilder = TypeBuilder.DefineMethod ("BeginInvoke",
+                               mattr, cc, TypeManager.iasyncresult_type, async_parameters.Types);
+
+                       BeginInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
+                       async_parameters.ApplyAttributes (BeginInvokeBuilder);
+                       TypeManager.RegisterMethod (BeginInvokeBuilder, async_parameters);
+
+                       //
+                       // EndInvoke is a bit more interesting, all the parameters labeled as
+                       // out or ref have to be duplicated here.
+                       //
+
+                       //
+                       // Define parameters, and count out/ref parameters
+                       //
+                       Parameters end_parameters;
+                       int out_params = 0;
+
+                       foreach (Parameter p in Parameters.FixedParameters) {
+                               if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0)
+                                       ++out_params;
+                       }
+
+                       if (out_params > 0) {
+                               Type [] end_param_types = new Type [out_params];
+                               Parameter [] end_params = new Parameter [out_params ];
+
+                               int param = 0; 
+                               for (int i = 0; i < Parameters.FixedParameters.Length; ++i) {
+                                       Parameter p = Parameters.FixedParameters [i];
+                                       if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0)
+                                               continue;
+
+                                       end_param_types [param] = p.ExternalType();
+                                       end_params [param] = p;
+                                       ++param;
+                               }
+                               end_parameters = new Parameters (end_params, end_param_types);
+                       }
+                       else {
+                               end_parameters = Parameters.EmptyReadOnlyParameters;
+                       }
+
+                       end_parameters = Parameters.MergeGenerated (end_parameters,
+                               new Parameter (TypeManager.iasyncresult_type, "result", Parameter.Modifier.NONE, null, Location));
+                       
+                       //
+                       // Create method, define parameters, register parameters with type system
+                       //
+                       EndInvokeBuilder = TypeBuilder.DefineMethod ("EndInvoke", mattr, cc, ret_type, end_parameters.Types);
+                       EndInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
+
+                       end_parameters.ApplyAttributes (EndInvokeBuilder);
+                       TypeManager.RegisterMethod (EndInvokeBuilder, end_parameters);
+
+                       return true;
+               }
+
+               public override void Emit ()
+               {
+                       Parameters.ApplyAttributes (InvokeBuilder);
+
+                       if (OptAttributes != null) {
+                               OptAttributes.Emit ();
+                       }
+
+                       base.Emit ();
+               }
+
+               protected override TypeAttributes TypeAttr {
+                       get {
+                               return Modifiers.TypeAttr (ModFlags, IsTopLevel) |
+                                       TypeAttributes.Class | TypeAttributes.Sealed |
+                                       base.TypeAttr;
+                       }
+               }
+
+               public override string[] ValidAttributeTargets {
+                       get {
+                               return attribute_targets;
+                       }
+               }
+
+               //TODO: duplicate
+               protected override bool VerifyClsCompliance ()
+               {
+                       if (!base.VerifyClsCompliance ()) {
+                               return false;
+                       }
+
+                       Parameters.VerifyClsCompliance ();
+
+                       if (!AttributeTester.IsClsCompliant (ReturnType.Type)) {
+                               Report.Error (3002, Location, "Return type of `{0}' is not CLS-compliant", GetSignatureForError ());
+                       }
+                       return true;
+               }
+
+               //
+               // Returns the MethodBase for "Invoke" from a delegate type, this is used
+               // to extract the signature of a delegate.
+               //
+               public static MethodGroupExpr GetInvokeMethod (Type container_type, Type delegate_type, Location loc)
+               {
+                       Expression ml = Expression.MemberLookup (container_type, null, delegate_type,
+                               "Invoke", loc);
+
+                       MethodGroupExpr mg = ml as MethodGroupExpr;
+                       if (mg == null) {
+                               Report.Error (-100, loc, "Internal error: could not find Invoke method!");
+                               return null;
+                       }
+
+                       return mg;
+               }
+               
+               /// <summary>
+               ///  Verifies whether the method in question is compatible with the delegate
+               ///  Returns the method itself if okay and null if not.
+               /// </summary>
+               public static MethodBase VerifyMethod (Type container_type, Type delegate_type,
+                                                      MethodGroupExpr old_mg, MethodBase mb,
+                                                      Location loc)
+               {
+                       MethodGroupExpr mg = GetInvokeMethod (container_type, delegate_type, loc);
+                       if (mg == null)
+                               return null;
+
+                       if (old_mg.HasTypeArguments)
+                               mg.HasTypeArguments = true;
+
+                       MethodBase invoke_mb = mg.Methods [0];
+                       ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb);
+
+#if GMCS_SOURCE
+                       if (!mg.HasTypeArguments &&
+                           !TypeManager.InferTypeArguments (invoke_pd, ref mb))
+                               return null;
+#endif
+
+                       ParameterData pd = TypeManager.GetParameterData (mb);
+
+                       if (invoke_pd.Count != pd.Count)
+                               return null;
+
+                       for (int i = pd.Count; i > 0; ) {
+                               i--;
+
+                               Type invoke_pd_type = invoke_pd.ParameterType (i);
+                               Type pd_type = pd.ParameterType (i);
+                               Parameter.Modifier invoke_pd_type_mod = invoke_pd.ParameterModifier (i);
+                               Parameter.Modifier pd_type_mod = pd.ParameterModifier (i);
+
+                               invoke_pd_type_mod &= ~Parameter.Modifier.PARAMS;
+                               pd_type_mod &= ~Parameter.Modifier.PARAMS;
+
+                               if (invoke_pd_type_mod != pd_type_mod)
+                                       return null;
+
+                               if (invoke_pd_type == pd_type)
+                                       continue;
+
+                               if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (invoke_pd_type), pd_type))
+                                       return null;
+
+                               if (RootContext.Version == LanguageVersion.ISO_1)
+                                       return null;
+                       }
+
+                       Type invoke_mb_retval = ((MethodInfo) invoke_mb).ReturnType;
+                       Type mb_retval = ((MethodInfo) mb).ReturnType;
+                       if (invoke_mb_retval == mb_retval)
+                               return mb;
+
+                       if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (mb_retval), invoke_mb_retval))
+                               return null;
+
+                       if (RootContext.Version == LanguageVersion.ISO_1) 
+                               return null;
+
+                       return mb;
+               }
+
+               // <summary>
+               //  Verifies whether the invocation arguments are compatible with the
+               //  delegate's target method
+               // </summary>
+               public static bool VerifyApplicability (EmitContext ec, Type delegate_type,
+                                                       ArrayList args, Location loc)
+               {
+                       int arg_count;
+
+                       if (args == null)
+                               arg_count = 0;
+                       else
+                               arg_count = args.Count;
+
+                       Expression ml = Expression.MemberLookup (
+                               ec.ContainerType, delegate_type, "Invoke", loc);
+
+                       MethodGroupExpr me = ml as MethodGroupExpr;
+                       if (me == null) {
+                               Report.Error (-100, loc, "Internal error: could not find Invoke method!" + delegate_type);
+                               return false;
+                       }
+                       
+                       MethodBase mb = me.Methods [0];
+                       ParameterData pd = TypeManager.GetParameterData (mb);
+
+                       int pd_count = pd.Count;
+
+                       bool params_method = pd.HasParams;
+                       bool is_params_applicable = false;
+                       bool is_applicable = Invocation.IsApplicable (ec, me, args, arg_count, ref mb);
+
+                       if (!is_applicable && params_method &&
+                           Invocation.IsParamsMethodApplicable (ec, me, args, arg_count, ref mb))
+                               is_applicable = is_params_applicable = true;
+
+                       if (!is_applicable && !params_method && arg_count != pd_count) {
+                               Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments",
+                                       TypeManager.CSharpName (delegate_type), arg_count.ToString ());
+                               return false;
+                       }
+
+                       return Invocation.VerifyArgumentsCompat (
+                                       ec, args, arg_count, mb, 
+                                       is_params_applicable || (!is_applicable && params_method),
+                                       delegate_type, false, loc);
+               }
+               
+               /// <summary>
+               ///  Verifies whether the delegate in question is compatible with this one in
+               ///  order to determine if instantiation from the same is possible.
+               /// </summary>
+               public static bool VerifyDelegate (EmitContext ec, Type delegate_type, Location loc)
+               {
+                       Expression ml = Expression.MemberLookup (
+                               ec.ContainerType, delegate_type, "Invoke", loc);
+                       
+                       if (!(ml is MethodGroupExpr)) {
+                               Report.Error (-100, loc, "Internal error: could not find Invoke method!");
+                               return false;
+                       }
+                       
+                       MethodBase mb = ((MethodGroupExpr) ml).Methods [0];
+                       ParameterData pd = TypeManager.GetParameterData (mb);
+
+                       Expression probe_ml = Expression.MemberLookup (
+                               ec.ContainerType, delegate_type, "Invoke", loc);
+                       
+                       if (!(probe_ml is MethodGroupExpr)) {
+                               Report.Error (-100, loc, "Internal error: could not find Invoke method!");
+                               return false;
+                       }
+                       
+                       MethodBase probe_mb = ((MethodGroupExpr) probe_ml).Methods [0];
+                       ParameterData probe_pd = TypeManager.GetParameterData (probe_mb);
+                       
+                       if (((MethodInfo) mb).ReturnType != ((MethodInfo) probe_mb).ReturnType)
+                               return false;
+
+                       if (pd.Count != probe_pd.Count)
+                               return false;
+
+                       for (int i = pd.Count; i > 0; ) {
+                               i--;
+
+                               if (pd.ParameterType (i) != probe_pd.ParameterType (i) ||
+                                   pd.ParameterModifier (i) != probe_pd.ParameterModifier (i))
+                                       return false;
+                       }
+                       
+                       return true;
+               }
+               
+               public static string FullDelegateDesc (Type del_type, MethodBase mb, ParameterData pd)
+               {
+                       StringBuilder sb = new StringBuilder ();
+                       sb.Append (TypeManager.CSharpName (((MethodInfo) mb).ReturnType));
+                       sb.Append (" ");
+                       sb.Append (TypeManager.CSharpName (del_type));
+                       sb.Append (pd.GetSignatureForError ());
+                       return sb.ToString ();                  
+               }
+               
+               // Hack around System.Reflection as found everywhere else
+               public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+                                                       MemberFilter filter, object criteria)
+               {
+                       ArrayList members = new ArrayList (2);
+
+                       if ((mt & MemberTypes.Constructor) != 0) {
+                               if (ConstructorBuilder != null && filter (ConstructorBuilder, criteria))
+                                       members.Add (ConstructorBuilder);
+                       }
+
+                       if ((mt & MemberTypes.Method) != 0) {
+                               if (InvokeBuilder != null)
+                               if (filter (InvokeBuilder, criteria))
+                                       members.Add (InvokeBuilder);
+
+                               if (BeginInvokeBuilder != null)
+                               if (filter (BeginInvokeBuilder, criteria))
+                                       members.Add (BeginInvokeBuilder);
+
+                               if (EndInvokeBuilder != null)
+                               if (filter (EndInvokeBuilder, criteria))
+                                       members.Add (EndInvokeBuilder);
+                       }
+
+                       return new MemberList (members);
+               }
+
+               public override MemberCache MemberCache {
+                       get {
+                               return null;
+                       }
+               }
+
+               public Expression InstanceExpression {
+                       get {
+                               return instance_expr;
+                       }
+                       set {
+                               instance_expr = value;
+                       }
+               }
+
+               public MethodBase TargetMethod {
+                       get {
+                               return delegate_method;
+                       }
+                       set {
+                               delegate_method = value;
+                       }
+               }
+
+               public Type TargetReturnType {
+                       get {
+                               return ret_type;
+                       }
+               }
+
+               public override AttributeTargets AttributeTargets {
+                       get {
+                               return AttributeTargets.Delegate;
+                       }
+               }
+
+               //
+               //   Represents header string for documentation comment.
+               //
+               public override string DocCommentHeader {
+                       get { return "T:"; }
+               }
+
+       }
+
+       //
+       // Base class for `NewDelegate' and `ImplicitDelegateCreation'
+       //
+       public abstract class DelegateCreation : Expression {
+               protected MethodBase constructor_method;
+               protected MethodBase delegate_method;
+               protected MethodGroupExpr method_group;
+               protected Expression delegate_instance_expression;
+
+               protected DelegateCreation () {}
+
+               public static void Error_NoMatchingMethodForDelegate (EmitContext ec, MethodGroupExpr mg, Type type, Location loc)
+               {
+                       string method_desc;
+                       MethodBase found_method = mg.Methods [0];
+
+                       if (mg.Methods.Length > 1)
+                               method_desc = found_method.Name;
+                       else
+                               method_desc = Invocation.FullMethodDesc (found_method);
+
+                       Expression invoke_method = Expression.MemberLookup (
+                               ec.ContainerType, type, "Invoke", MemberTypes.Method,
+                               Expression.AllBindingFlags, loc);
+                       MethodInfo method = ((MethodGroupExpr) invoke_method).Methods [0] as MethodInfo;
+
+                       ParameterData param = TypeManager.GetParameterData (method);
+                       string delegate_desc = Delegate.FullDelegateDesc (type, method, param);
+
+#if GMCS_SOURCE
+                       if (!mg.HasTypeArguments &&
+                           !TypeManager.InferTypeArguments (param, ref found_method)) {
+                               Report.Error (411, loc, "The type arguments for " +
+                                             "method `{0}' cannot be infered from " +
+                                             "the usage. Try specifying the type " +
+                                             "arguments explicitly.", method_desc);
+                               return;
+                       }
+#endif
+                       Report.SymbolRelatedToPreviousError (found_method);
+
+                       if (RootContext.Version == LanguageVersion.ISO_1) {
+                               Report.Error (410, loc, "The method `{0}' parameters and return type must be same as delegate `{1}' parameters and return type",
+                                       method_desc, delegate_desc);
+                               return;
+                       }
+
+                       Type delegateType = method.ReturnType;
+                       Type methodType = ((MethodInfo) found_method).ReturnType;
+                       if (delegateType != methodType &&
+                               !Convert.ImplicitReferenceConversionExists (new EmptyExpression (methodType), delegateType)) {
+                               Report.Error (407, loc, "`{0}' has the wrong return type to match the delegate `{1}'", method_desc, delegate_desc);
+                       } else {
+                               Report.Error (123, loc, "The method `{0}' parameters do not match delegate `{1}' parameters",
+                                       TypeManager.CSharpSignature (found_method), delegate_desc);
+                       }
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       if (delegate_instance_expression == null || delegate_method.IsStatic)
+                               ec.ig.Emit (OpCodes.Ldnull);
+                       else
+                               delegate_instance_expression.Emit (ec);
+                       
+                       if (delegate_method.IsVirtual && !method_group.IsBase) {
+                               ec.ig.Emit (OpCodes.Dup);
+                               ec.ig.Emit (OpCodes.Ldvirtftn, (MethodInfo) delegate_method);
+                       } else
+                               ec.ig.Emit (OpCodes.Ldftn, (MethodInfo) delegate_method);
+                       ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) constructor_method);
+               }
+
+               protected bool ResolveConstructorMethod (EmitContext ec)
+               {
+                       Expression ml = Expression.MemberLookupFinal(ec, 
+                               null, type, ".ctor", MemberTypes.Constructor, AllBindingFlags | BindingFlags.DeclaredOnly, loc);
+
+                       if (!(ml is MethodGroupExpr)) {
+                               Report.Error (-100, loc, "Internal error: Could not find delegate constructor!");
+                               return false;
+                       }
+
+                       constructor_method = ((MethodGroupExpr) ml).Methods [0];
+                       return true;
+               }
+
+               public static MethodBase ImplicitStandardConversionExists (MethodGroupExpr mg, Type targetType)
+               {
+                       foreach (MethodInfo mi in mg.Methods){
+                               MethodBase mb = Delegate.VerifyMethod (mg.DeclaringType, targetType, mg, mi, Location.Null);
+                               if (mb != null)
+                                       return mb;
+                       }
+                       return null;
+               }
+
+               protected Expression ResolveMethodGroupExpr (EmitContext ec, MethodGroupExpr mg)
+               {
+                       delegate_method = ImplicitStandardConversionExists (mg, type);
+
+                       if (delegate_method == null) {
+                               Error_NoMatchingMethodForDelegate (ec, mg, type, loc);
+                               return null;
+                       }
+                       
+                       //
+                       // Check safe/unsafe of the delegate
+                       //
+                       if (!ec.InUnsafe){
+                               ParameterData param = TypeManager.GetParameterData (delegate_method);
+                               int count = param.Count;
+                               
+                               for (int i = 0; i < count; i++){
+                                       if (param.ParameterType (i).IsPointer){
+                                               Expression.UnsafeError (loc);
+                                               return null;
+                                       }
+                               }
+                       }
+                                               
+                       //TODO: implement caching when performance will be low
+                       IMethodData md = TypeManager.GetMethod (delegate_method);
+                       if (md == null) {
+                               if (System.Attribute.GetCustomAttribute (delegate_method, TypeManager.conditional_attribute_type) != null) {
+                                       Report.SymbolRelatedToPreviousError (delegate_method);
+                                       Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute", TypeManager.CSharpSignature (delegate_method));
+                                       return null;
+                               }
+                       } else {
+                               md.SetMemberIsUsed ();
+                               if (md.OptAttributes != null && md.OptAttributes.Search (TypeManager.conditional_attribute_type) != null) {
+                                       Report.SymbolRelatedToPreviousError (delegate_method);
+                                       Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute", TypeManager.CSharpSignature (delegate_method));
+                                       return null;
+                               }
+                       }
+                       
+                       if (mg.InstanceExpression != null)
+                               delegate_instance_expression = mg.InstanceExpression.Resolve (ec);
+                       else if (ec.IsStatic) {
+                               if (!delegate_method.IsStatic) {
+                                       Report.Error (120, loc, "`{0}': An object reference is required for the nonstatic field, method or property",
+                                                     TypeManager.CSharpSignature (delegate_method));
+                                       return null;
+                               }
+                               delegate_instance_expression = null;
+                       } else
+                               delegate_instance_expression = ec.GetThis (loc);
+
+                       if (delegate_instance_expression != null && delegate_instance_expression.Type.IsValueType)
+                               delegate_instance_expression = new BoxedCast (
+                                       delegate_instance_expression, TypeManager.object_type);
+
+                       method_group = mg;
+                       eclass = ExprClass.Value;
+                       return this;
+               }
+       }
+
+       //
+       // Created from the conversion code
+       //
+       public class ImplicitDelegateCreation : DelegateCreation {
+
+               ImplicitDelegateCreation (Type t, Location l)
+               {
+                       type = t;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return this;
+               }
+
+               static public Expression Create (EmitContext ec, MethodGroupExpr mge,
+                                                Type target_type, Location loc)
+               {
+                       ImplicitDelegateCreation d = new ImplicitDelegateCreation (target_type, loc);
+                       if (!d.ResolveConstructorMethod (ec))
+                               return null;
+
+                       return d.ResolveMethodGroupExpr (ec, mge);
+               }
+       }
+       
+       //
+       // A delegate-creation-expression, invoked from the `New' class 
+       //
+       public class NewDelegate : DelegateCreation {
+               public ArrayList Arguments;
+
+               //
+               // This constructor is invoked from the `New' expression
+               //
+               public NewDelegate (Type type, ArrayList Arguments, Location loc)
+               {
+                       this.type = type;
+                       this.Arguments = Arguments;
+                       this.loc  = loc; 
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (Arguments == null || Arguments.Count != 1) {
+                               Report.Error (149, loc,
+                                             "Method name expected");
+                               return null;
+                       }
+
+                       if (!ResolveConstructorMethod (ec))
+                               return null;
+
+                       Argument a = (Argument) Arguments [0];
+                       
+                       if (!a.ResolveMethodGroup (ec))
+                               return null;
+                       
+                       Expression e = a.Expr;
+
+                       if (e is AnonymousMethodExpression && RootContext.Version != LanguageVersion.ISO_1)
+                               return ((AnonymousMethodExpression) e).Compatible (ec, type);
+
+                       MethodGroupExpr mg = e as MethodGroupExpr;
+                       if (mg != null)
+                               return ResolveMethodGroupExpr (ec, mg);
+
+                       if (!TypeManager.IsDelegateType (e.Type)) {
+                               Report.Error (149, loc, "Method name expected");
+                               return null;
+                       }
+
+                       method_group = Expression.MemberLookup (
+                               ec.ContainerType, type, "Invoke", MemberTypes.Method,
+                               Expression.AllBindingFlags, loc) as MethodGroupExpr;
+
+                       if (method_group == null) {
+                               Report.Error (-200, loc, "Internal error ! Could not find Invoke method!");
+                               return null;
+                       }
+
+                       // This is what MS' compiler reports. We could always choose
+                       // to be more verbose and actually give delegate-level specifics
+                       if (!Delegate.VerifyDelegate (ec, type, loc)) {
+                               Report.Error (29, loc, "Cannot implicitly convert type '" + e.Type + "' " +
+                                             "to type '" + type + "'");
+                               return null;
+                       }
+                               
+                       delegate_instance_expression = e;
+                       delegate_method = method_group.Methods [0];
+                       
+                       eclass = ExprClass.Value;
+                       return this;
+               }
+       }
+
+       public class DelegateInvocation : ExpressionStatement {
+
+               public Expression InstanceExpr;
+               public ArrayList  Arguments;
+
+               MethodBase method;
+               
+               public DelegateInvocation (Expression instance_expr, ArrayList args, Location loc)
+               {
+                       this.InstanceExpr = instance_expr;
+                       this.Arguments = args;
+                       this.loc = loc;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (InstanceExpr is EventExpr) {
+                               
+                               EventInfo ei = ((EventExpr) InstanceExpr).EventInfo;
+                               
+                               Expression ml = MemberLookup (
+                                       ec.ContainerType, ec.ContainerType, ei.Name,
+                                       MemberTypes.Event, AllBindingFlags | BindingFlags.DeclaredOnly, loc);
+
+                               if (ml == null) {
+                                       //
+                                       // If this is the case, then the Event does not belong 
+                                       // to this Type and so, according to the spec
+                                       // cannot be accessed directly
+                                       //
+                                       // Note that target will not appear as an EventExpr
+                                       // in the case it is being referenced within the same type container;
+                                       // it will appear as a FieldExpr in that case.
+                                       //
+                                       
+                                       Assign.error70 (ei, loc);
+                                       return null;
+                               }
+                       }
+                       
+                       
+                       Type del_type = InstanceExpr.Type;
+                       if (del_type == null)
+                               return null;
+                       
+                       if (Arguments != null){
+                               foreach (Argument a in Arguments){
+                                       if (!a.Resolve (ec, loc))
+                                               return null;
+                               }
+                       }
+                       
+                       if (!Delegate.VerifyApplicability (ec, del_type, Arguments, loc))
+                               return null;
+
+                       Expression lookup = Expression.MemberLookup (ec.ContainerType, del_type, "Invoke", loc);
+                       if (!(lookup is MethodGroupExpr)) {
+                               Report.Error (-100, loc, "Internal error: could not find Invoke method!");
+                               return null;
+                       }
+                       
+                       method = ((MethodGroupExpr) lookup).Methods [0];
+                       type = ((MethodInfo) method).ReturnType;
+                       eclass = ExprClass.Value;
+                       
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       //
+                       // Invocation on delegates call the virtual Invoke member
+                       // so we are always `instance' calls
+                       //
+                       Invocation.EmitCall (ec, false, false, InstanceExpr, method, Arguments, loc);
+               }
+
+               public override void EmitStatement (EmitContext ec)
+               {
+                       Emit (ec);
+                       // 
+                       // Pop the return value if there is one
+                       //
+                       if (method is MethodInfo){
+                               Type ret = ((MethodInfo)method).ReturnType;
+                               if (TypeManager.TypeToCoreType (ret) != TypeManager.void_type)
+                                       ec.ig.Emit (OpCodes.Pop);
+                       }
+               }
+
+       }
+}
diff --git a/mcs/mcs/driver.cs b/mcs/mcs/driver.cs
new file mode 100644 (file)
index 0000000..3ec7835
--- /dev/null
@@ -0,0 +1,2007 @@
+//
+// driver.cs: The compiler command line driver.
+//
+// Author: Miguel de Icaza (miguel@gnu.org)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
+// (C) 2004, 2005 Novell, Inc
+//
+
+namespace Mono.CSharp
+{
+       using System;
+       using System.Reflection;
+       using System.Reflection.Emit;
+       using System.Collections;
+       using System.Collections.Specialized;
+       using System.IO;
+       using System.Text;
+       using System.Globalization;
+       using System.Diagnostics;
+
+       public enum Target {
+               Library, Exe, Module, WinExe
+       };
+       
+       /// <summary>
+       ///    The compiler driver.
+       /// </summary>
+       public class Driver
+       {
+               
+               //
+               // Assemblies references to be linked.   Initialized with
+               // mscorlib.dll here.
+               static ArrayList references;
+
+               //
+               // If any of these fail, we ignore the problem.  This is so
+               // that we can list all the assemblies in Windows and not fail
+               // if they are missing on Linux.
+               //
+               static ArrayList soft_references;
+
+               // 
+               // External aliases for assemblies.
+               //
+               static Hashtable external_aliases;
+
+               //
+               // Modules to be linked
+               //
+               static ArrayList modules;
+
+               // Lookup paths
+               static ArrayList link_paths;
+
+               // Whether we want to only run the tokenizer
+               static bool tokenize = false;
+               
+               static string first_source;
+
+               static bool want_debugging_support = false;
+
+               static bool parse_only = false;
+               static bool timestamps = false;
+               static bool pause = false;
+               static bool show_counters = false;
+               
+               //
+               // Whether to load the initial config file (what CSC.RSP has by default)
+               // 
+               static bool load_default_config = true;
+
+               //
+               // A list of resource files
+               //
+               static Resources embedded_resources;
+               static string win32ResourceFile;
+               static string win32IconFile;
+
+               //
+               // An array of the defines from the command line
+               //
+               static ArrayList defines;
+
+               //
+               // Output file
+               //
+               static string output_file = null;
+
+               //
+               // Last time we took the time
+               //
+               static DateTime last_time, first_time;
+
+               //
+               // Encoding.
+               //
+               static Encoding encoding;
+
+               static public void Reset ()
+               {
+                       want_debugging_support = false;
+                       parse_only = false;
+                       timestamps = false;
+                       pause = false;
+                       show_counters = false;
+                       load_default_config = true;
+                       embedded_resources = null;
+                       win32ResourceFile = win32IconFile = null;
+                       defines = null;
+                       output_file = null;
+                       encoding = null;
+                       first_source = null;
+               }
+
+               public static void ShowTime (string msg)
+               {
+                       if (!timestamps)
+                               return;
+
+                       DateTime now = DateTime.Now;
+                       TimeSpan span = now - last_time;
+                       last_time = now;
+
+                       Console.WriteLine (
+                               "[{0:00}:{1:000}] {2}",
+                               (int) span.TotalSeconds, span.Milliseconds, msg);
+               }
+
+               public static void ShowTotalTime (string msg)
+               {
+                       if (!timestamps)
+                               return;
+
+                       DateTime now = DateTime.Now;
+                       TimeSpan span = now - first_time;
+                       last_time = now;
+
+                       Console.WriteLine (
+                               "[{0:00}:{1:000}] {2}",
+                               (int) span.TotalSeconds, span.Milliseconds, msg);
+               }              
+              
+               static void tokenize_file (SourceFile file)
+               {
+                       Stream input;
+
+                       try {
+                               input = File.OpenRead (file.Name);
+                       } catch {
+                               Report.Error (2001, "Source file `" + file.Name + "' could not be found");
+                               return;
+                       }
+
+                       using (input){
+                               SeekableStreamReader reader = new SeekableStreamReader (input, encoding);
+                               Tokenizer lexer = new Tokenizer (reader, file, defines);
+                               int token, tokens = 0, errors = 0;
+
+                               while ((token = lexer.token ()) != Token.EOF){
+                                       tokens++;
+                                       if (token == Token.ERROR)
+                                               errors++;
+                               }
+                               Console.WriteLine ("Tokenized: " + tokens + " found " + errors + " errors");
+                       }
+                       
+                       return;
+               }
+
+               // MonoTODO("Change error code for aborted compilation to something reasonable")]               
+               static void parse (SourceFile file)
+               {
+                       CSharpParser parser;
+                       Stream input;
+
+                       try {
+                               input = File.OpenRead (file.Name);
+                       } catch {
+                               Report.Error (2001, "Source file `" + file.Name + "' could not be found");
+                               return;
+                       }
+
+                       SeekableStreamReader reader = new SeekableStreamReader (input, encoding);
+
+                       // Check 'MZ' header
+                       if (reader.Read () == 77 && reader.Read () == 90) {
+                               Report.Error (2015, "Source file `{0}' is a binary file and not a text file", file.Name);
+                               input.Close ();
+                               return;
+                       }
+
+                       reader.Position = 0;
+                       parser = new CSharpParser (reader, file, defines);
+                       parser.ErrorOutput = Report.Stderr;
+                       try {
+                               parser.parse ();
+                       } catch (Exception ex) {
+                               Report.Error(666, "Compilation aborted: " + ex);
+                       } finally {
+                               input.Close ();
+                       }
+               }
+
+               static void OtherFlags ()
+               {
+                       Console.WriteLine (
+                               "Other flags in the compiler\n" +
+                               "   --fatal            Makes errors fatal\n" +
+                               "   --parse            Only parses the source file\n" +
+                               "   --stacktrace       Shows stack trace at error location\n" +
+                               "   --timestamp        Displays time stamps of various compiler events\n" +
+                               "   --expect-error X   Expect that error X will be encountered\n" +
+                               "   -2                 Enables experimental C# features\n" +
+                               "   -v                 Verbose parsing (for debugging the parser)\n" + 
+                               "   --mcs-debug X      Sets MCS debugging level to X\n");
+               }
+               
+               static void Usage ()
+               {
+                       Console.WriteLine (
+                               "Mono C# compiler, (C) 2001 - 2005 Novell, Inc.\n" +
+                               "mcs [options] source-files\n" +
+                               "   --about            About the Mono C# compiler\n" +
+                               "   -addmodule:MODULE  Adds the module to the generated assembly\n" + 
+                               "   -checked[+|-]      Set default context to checked\n" +
+                               "   -codepage:ID       Sets code page to the one in ID (number, utf8, reset)\n" +
+                               "   -clscheck[+|-]     Disables CLS Compliance verifications" + Environment.NewLine +
+                               "   -define:S1[;S2]    Defines one or more symbols (short: /d:)\n" +
+                               "   -debug[+|-], -g    Generate debugging information\n" + 
+                               "   -delaysign[+|-]    Only insert the public key into the assembly (no signing)\n" +
+                               "   -doc:FILE          XML Documentation file to generate\n" + 
+                               "   -keycontainer:NAME The key pair container used to strongname the assembly\n" +
+                               "   -keyfile:FILE      The strongname key file used to strongname the assembly\n" +
+                               "   -langversion:TEXT  Specifies language version modes: ISO-1 or Default\n" + 
+                               "   -lib:PATH1,PATH2   Adds the paths to the assembly link path\n" +
+                               "   -main:class        Specified the class that contains the entry point\n" +
+                               "   -noconfig[+|-]     Disables implicit references to assemblies\n" +
+                               "   -nostdlib[+|-]     Does not load core libraries\n" +
+                               "   -nowarn:W1[,W2]    Disables one or more warnings\n" + 
+                               "   -optimize[+|-]     Enables code optimalizations\n" + 
+                               "   -out:FNAME         Specifies output file\n" +
+                               "   -pkg:P1[,Pn]       References packages P1..Pn\n" + 
+                               "   -recurse:SPEC      Recursively compiles the files in SPEC ([dir]/file)\n" + 
+                               "   -reference:ASS     References the specified assembly (-r:ASS)\n" +
+                               "   -target:KIND       Specifies the target (KIND is one of: exe, winexe,\n" +
+                               "                      library, module), (short: /t:)\n" +
+                               "   -unsafe[+|-]       Allows unsafe code\n" +
+                               "   -warnaserror[+|-]  Treat warnings as errors\n" +
+                               "   -warn:LEVEL        Sets warning level (the highest is 4, the default is 2)\n" +
+                               "   -help2             Show other help flags\n" + 
+                               "\n" +
+                               "Resources:\n" +
+                               "   -linkresource:FILE[,ID] Links FILE as a resource\n" +
+                               "   -resource:FILE[,ID]     Embed FILE as a resource\n" +
+                               "   -win32res:FILE          Specifies Win32 resource file (.res)\n" +
+                               "   -win32icon:FILE         Use this icon for the output\n" +
+                                "   @file                   Read response file for more options\n\n" +
+                               "Options can be of the form -option or /option");
+               }
+
+               static void TargetUsage ()
+               {
+                       Report.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'");
+               }
+               
+               static void About ()
+               {
+                       Console.WriteLine (
+                               "The Mono C# compiler is (C) 2001-2005, Novell, Inc.\n\n" +
+                               "The compiler source code is released under the terms of the GNU GPL\n\n" +
+
+                               "For more information on Mono, visit the project Web site\n" +
+                               "   http://www.go-mono.com\n\n" +
+
+                               "The compiler was written by Miguel de Icaza, Ravi Pratap, Martin Baulig, Marek Safar, Raja R Harinath");
+                       Environment.Exit (0);
+               }
+
+               public static int counter1, counter2;
+               
+               public static int Main (string[] args)
+               {
+#if GMCS_SOURCE
+                       RootContext.Version = LanguageVersion.Default;
+#endif
+                       Location.InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t";
+
+                       bool ok = MainDriver (args);
+                       
+                       if (ok && Report.Errors == 0) {
+                               if (Report.Warnings > 0) {
+                                       Console.WriteLine ("Compilation succeeded - {0} warning(s)", Report.Warnings);
+                               }
+                               if (show_counters){
+                                       Console.WriteLine ("Counter1: " + counter1);
+                                       Console.WriteLine ("Counter2: " + counter2);
+                               }
+                               if (pause)
+                                       Console.ReadLine ();
+                               return 0;
+                       } else {
+                               Console.WriteLine("Compilation failed: {0} error(s), {1} warnings",
+                                       Report.Errors, Report.Warnings);
+                               return 1;
+                       }
+               }
+
+               static public void LoadAssembly (string assembly, bool soft)
+               {
+                       LoadAssembly (assembly, null, soft);
+               }
+
+               static void Error6 (string name, string log)
+               {
+                       if (log != null && log.Length > 0)
+                               Report.ExtraInformation (Location.Null, "Log:\n" + log + "\n(log related to previous ");
+                       Report.Error (6, "cannot find metadata file `{0}'", name);
+               }
+
+               static void Error9 (string type, string filename, string log)
+               {
+                       if (log != null && log.Length > 0)
+                               Report.ExtraInformation (Location.Null, "Log:\n" + log + "\n(log related to previous ");
+                       Report.Error (9, "file `{0}' has invalid `{1}' metadata", filename, type);
+               }
+
+               static void BadAssembly (string filename, string log)
+               {
+                       MethodInfo adder_method = AssemblyClass.AddModule_Method;
+
+                       if (adder_method != null) {
+                               AssemblyName an = new AssemblyName ();
+                               an.Name = ".temp";
+                               AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly (an, AssemblyBuilderAccess.Run);
+                               try {
+                                       object m = null;
+                                       try {
+                                               m = adder_method.Invoke (ab, new object [] { filename });
+                                       } catch (TargetInvocationException ex) {
+                                               throw ex.InnerException;
+                                       }
+
+                                       if (m != null) {
+                                               Report.Error (1509, "referenced file `{0}' is not an assembly; try using the '-addmodule' option", filename);
+                                               return;
+                                       }
+                               } catch (FileNotFoundException) {
+                                       // did the file get deleted during compilation? who cares? swallow the exception
+                               } catch (BadImageFormatException) {
+                                       // swallow exception
+                               } catch (FileLoadException) {
+                                       // swallow exception
+                               }
+                       }
+                       Error9 ("assembly", filename, log);
+               }
+
+               static public void LoadAssembly (string assembly, string alias, bool soft)
+               {
+                       Assembly a = null;
+                       string total_log = "";
+
+                       try {
+                               try {
+                                       char[] path_chars = { '/', '\\' };
+
+                                       if (assembly.IndexOfAny (path_chars) != -1) {
+                                               a = Assembly.LoadFrom (assembly);
+                                       } else {
+                                               string ass = assembly;
+                                               if (ass.EndsWith (".dll") || ass.EndsWith (".exe"))
+                                                       ass = assembly.Substring (0, assembly.Length - 4);
+                                               a = Assembly.Load (ass);
+                                       }
+                               } catch (FileNotFoundException) {
+                                       bool err = !soft;
+                                       foreach (string dir in link_paths) {
+                                               string full_path = Path.Combine (dir, assembly);
+                                               if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe"))
+                                                       full_path += ".dll";
+
+                                               try {
+                                                       a = Assembly.LoadFrom (full_path);
+                                                       err = false;
+                                                       break;
+                                               } catch (FileNotFoundException ff) {
+                                                       total_log += ff.FusionLog;
+                                               }
+                                       }
+                                       if (err) {
+                                               Error6 (assembly, total_log);
+                                               return;
+                                       }
+                               }
+
+                               // Extern aliased refs require special handling
+                               if (alias == null)
+                                       RootNamespace.Global.AddAssemblyReference (a);
+                               else
+                                       RootNamespace.DefineRootNamespace (alias, a);
+
+                       } catch (BadImageFormatException f) {
+                               // .NET 2.0 throws this if we try to load a module without an assembly manifest ...
+                               BadAssembly (f.FileName, f.FusionLog);
+                       } catch (FileLoadException f) {
+                               // ... while .NET 1.1 throws this
+                               BadAssembly (f.FileName, f.FusionLog);
+                       }
+               }
+
+               static public void LoadModule (string module)
+               {
+                       Module m = null;
+                       string total_log = "";
+
+                       try {
+                               try {
+                                       m = CodeGen.Assembly.AddModule (module);
+                               } catch (FileNotFoundException) {
+                                       bool err = true;
+                                       foreach (string dir in link_paths) {
+                                               string full_path = Path.Combine (dir, module);
+                                               if (!module.EndsWith (".netmodule"))
+                                                       full_path += ".netmodule";
+
+                                               try {
+                                                       m = CodeGen.Assembly.AddModule (full_path);
+                                                       err = false;
+                                                       break;
+                                               } catch (FileNotFoundException ff) {
+                                                       total_log += ff.FusionLog;
+                                               }
+                                       }
+                                       if (err) {
+                                               Error6 (module, total_log);
+                                               return;
+                                       }
+                               }
+
+                               RootNamespace.Global.AddModuleReference (m);
+
+                       } catch (BadImageFormatException f) {
+                               Error9 ("module", f.FileName, f.FusionLog);
+                       } catch (FileLoadException f) {
+                               Error9 ("module", f.FileName, f.FusionLog);
+                       }
+               }
+
+               /// <summary>
+               ///   Loads all assemblies referenced on the command line
+               /// </summary>
+               static public void LoadReferences ()
+               {
+                       foreach (string r in references)
+                               LoadAssembly (r, false);
+
+                       foreach (string r in soft_references)
+                               LoadAssembly (r, true);
+
+                       foreach (DictionaryEntry entry in external_aliases)
+                               LoadAssembly ((string) entry.Value, (string) entry.Key, false);
+                       
+                       return;
+               }
+
+               static void SetupDefaultDefines ()
+               {
+                       defines = new ArrayList ();
+                       defines.Add ("__MonoCS__");
+               }
+
+               static string [] LoadArgs (string file)
+               {
+                       StreamReader f;
+                       ArrayList args = new ArrayList ();
+                       string line;
+                       try {
+                               f = new StreamReader (file);
+                       } catch {
+                               return null;
+                       }
+
+                       StringBuilder sb = new StringBuilder ();
+                       
+                       while ((line = f.ReadLine ()) != null){
+                               int t = line.Length;
+
+                               for (int i = 0; i < t; i++){
+                                       char c = line [i];
+                                       
+                                       if (c == '"' || c == '\''){
+                                               char end = c;
+                                               
+                                               for (i++; i < t; i++){
+                                                       c = line [i];
+
+                                                       if (c == end)
+                                                               break;
+                                                       sb.Append (c);
+                                               }
+                                       } else if (c == ' '){
+                                               if (sb.Length > 0){
+                                                       args.Add (sb.ToString ());
+                                                       sb.Length = 0;
+                                               }
+                                       } else
+                                               sb.Append (c);
+                               }
+                               if (sb.Length > 0){
+                                       args.Add (sb.ToString ());
+                                       sb.Length = 0;
+                               }
+                       }
+
+                       string [] ret_value = new string [args.Count];
+                       args.CopyTo (ret_value, 0);
+
+                       return ret_value;
+               }
+
+               //
+               // Returns the directory where the system assemblies are installed
+               //
+               static string GetSystemDir ()
+               {
+                       return Path.GetDirectoryName (typeof (object).Assembly.Location);
+               }
+
+               //
+               // Given a path specification, splits the path from the file/pattern
+               //
+               static void SplitPathAndPattern (string spec, out string path, out string pattern)
+               {
+                       int p = spec.LastIndexOf ('/');
+                       if (p != -1){
+                               //
+                               // Windows does not like /file.cs, switch that to:
+                               // "\", "file.cs"
+                               //
+                               if (p == 0){
+                                       path = "\\";
+                                       pattern = spec.Substring (1);
+                               } else {
+                                       path = spec.Substring (0, p);
+                                       pattern = spec.Substring (p + 1);
+                               }
+                               return;
+                       }
+
+                       p = spec.LastIndexOf ('\\');
+                       if (p != -1){
+                               path = spec.Substring (0, p);
+                               pattern = spec.Substring (p + 1);
+                               return;
+                       }
+
+                       path = ".";
+                       pattern = spec;
+               }
+
+               static void ProcessFile (string f)
+               {
+                       if (first_source == null)
+                               first_source = f;
+
+                       Location.AddFile (f);
+               }
+
+               static void ProcessFiles ()
+               {
+                       Location.Initialize ();
+
+                       foreach (SourceFile file in Location.SourceFiles) {
+                               if (tokenize) {
+                                       tokenize_file (file);
+                               } else {
+                                       parse (file);
+                               }
+                       }
+               }
+
+               static void CompileFiles (string spec, bool recurse)
+               {
+                       string path, pattern;
+
+                       SplitPathAndPattern (spec, out path, out pattern);
+                       if (pattern.IndexOf ('*') == -1){
+                               ProcessFile (spec);
+                               return;
+                       }
+
+                       string [] files = null;
+                       try {
+                               files = Directory.GetFiles (path, pattern);
+                       } catch (System.IO.DirectoryNotFoundException) {
+                               Report.Error (2001, "Source file `" + spec + "' could not be found");
+                               return;
+                       } catch (System.IO.IOException){
+                               Report.Error (2001, "Source file `" + spec + "' could not be found");
+                               return;
+                       }
+                       foreach (string f in files) {
+                               ProcessFile (f);
+                       }
+
+                       if (!recurse)
+                               return;
+                       
+                       string [] dirs = null;
+
+                       try {
+                               dirs = Directory.GetDirectories (path);
+                       } catch {
+                       }
+                       
+                       foreach (string d in dirs) {
+                                       
+                               // Don't include path in this string, as each
+                               // directory entry already does
+                               CompileFiles (d + "/" + pattern, true);
+                       }
+               }
+
+               static void DefineDefaultConfig ()
+               {
+                       //
+                       // For now the "default config" is harcoded into the compiler
+                       // we can move this outside later
+                       //
+                       string [] default_config = {
+                               "System",
+                               "System.Xml",
+#if false
+                               //
+                               // Is it worth pre-loading all this stuff?
+                               //
+                               "Accessibility",
+                               "System.Configuration.Install",
+                               "System.Data",
+                               "System.Design",
+                               "System.DirectoryServices",
+                               "System.Drawing.Design",
+                               "System.Drawing",
+                               "System.EnterpriseServices",
+                               "System.Management",
+                               "System.Messaging",
+                               "System.Runtime.Remoting",
+                               "System.Runtime.Serialization.Formatters.Soap",
+                               "System.Security",
+                               "System.ServiceProcess",
+                               "System.Web",
+                               "System.Web.RegularExpressions",
+                               "System.Web.Services",
+                               "System.Windows.Forms"
+#endif
+                       };
+                       
+                       int p = 0;
+                       foreach (string def in default_config)
+                               soft_references.Insert (p++, def);
+               }
+
+               public static string OutputFile
+               {
+                       set {
+                               output_file = value;
+                       }
+                       get {
+                               return Path.GetFileName (output_file);
+                       }
+               }
+
+               static void SetWarningLevel (string s)
+               {
+                       int level = -1;
+
+                       try {
+                               level = Int32.Parse (s);
+                       } catch {
+                       }
+                       if (level < 0 || level > 4){
+                               Report.Error (1900, "Warning level must be in the range 0-4");
+                               return;
+                       }
+                       RootContext.WarningLevel = level;
+               }
+
+               static void SetupV2 ()
+               {
+                       RootContext.Version = LanguageVersion.Default;
+                       defines.Add ("__V2__");
+               }
+               
+               static void Version ()
+               {
+                       string version = Assembly.GetExecutingAssembly ().GetName ().Version.ToString ();
+                       Console.WriteLine ("Mono C# compiler version {0}", version);
+                       Environment.Exit (0);
+               }
+               
+               //
+               // Currently handles the Unix-like command line options, but will be
+               // deprecated in favor of the CSCParseOption, which will also handle the
+               // options that start with a dash in the future.
+               //
+               static bool UnixParseOption (string arg, ref string [] args, ref int i)
+               {
+                       switch (arg){
+                       case "-v":
+                               CSharpParser.yacc_verbose_flag++;
+                               return true;
+
+                       case "--version":
+                               Version ();
+                               return true;
+                               
+                       case "--parse":
+                               parse_only = true;
+                               return true;
+                               
+                       case "--main": case "-m":
+                               Report.Warning (-29, 1, "Compatibility: Use -main:CLASS instead of --main CLASS or -m CLASS");
+                               if ((i + 1) >= args.Length){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               RootContext.MainClass = args [++i];
+                               return true;
+                               
+                       case "--unsafe":
+                               Report.Warning (-29, 1, "Compatibility: Use -unsafe instead of --unsafe");
+                               RootContext.Unsafe = true;
+                               return true;
+                               
+                       case "/?": case "/h": case "/help":
+                       case "--help":
+                               Usage ();
+                               Environment.Exit (0);
+                               return true;
+
+                       case "--define":
+                               Report.Warning (-29, 1, "Compatibility: Use -d:SYMBOL instead of --define SYMBOL");
+                               if ((i + 1) >= args.Length){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               defines.Add (args [++i]);
+                               return true;
+
+                       case "--show-counters":
+                               show_counters = true;
+                               return true;
+                               
+                       case "--expect-error": {
+                               int code = 0;
+                               
+                               try {
+                                       code = Int32.Parse (
+                                               args [++i], NumberStyles.AllowLeadingSign);
+                                       Report.ExpectedError = code;
+                               } catch {
+                                       Report.Error (-14, "Invalid number specified");
+                               } 
+                               return true;
+                       }
+                               
+                       case "--tokenize": 
+                               tokenize = true;
+                               return true;
+                               
+                       case "-o": 
+                       case "--output":
+                               Report.Warning (-29, 1, "Compatibility: Use -out:FILE instead of --output FILE or -o FILE");
+                               if ((i + 1) >= args.Length){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               OutputFile = args [++i];
+                               return true;
+
+                       case "--checked":
+                               Report.Warning (-29, 1, "Compatibility: Use -checked instead of --checked");
+                               RootContext.Checked = true;
+                               return true;
+                               
+                       case "--stacktrace":
+                               Report.Stacktrace = true;
+                               return true;
+                               
+                       case "--linkresource":
+                       case "--linkres":
+                               Report.Warning (-29, 1, "Compatibility: Use -linkres:VALUE instead of --linkres VALUE");
+                               if ((i + 1) >= args.Length){
+                                       Usage ();
+                                       Report.Error (5, "Missing argument to --linkres"); 
+                                       Environment.Exit (1);
+                               }
+                               if (embedded_resources == null)
+                                       embedded_resources = new Resources ();
+                               
+                               embedded_resources.Add (false, args [++i], args [i]);
+                               return true;
+                               
+                       case "--resource":
+                       case "--res":
+                               Report.Warning (-29, 1, "Compatibility: Use -res:VALUE instead of --res VALUE");
+                               if ((i + 1) >= args.Length){
+                                       Usage ();
+                                       Report.Error (5, "Missing argument to --resource"); 
+                                       Environment.Exit (1);
+                               }
+                               if (embedded_resources == null)
+                                       embedded_resources = new Resources ();
+                               
+                               embedded_resources.Add (true, args [++i], args [i]);
+                               return true;
+                               
+                       case "--target":
+                               Report.Warning (-29, 1, "Compatibility: Use -target:KIND instead of --target KIND");
+                               if ((i + 1) >= args.Length){
+                                       Environment.Exit (1);
+                                       return true;
+                               }
+                               
+                               string type = args [++i];
+                               switch (type){
+                               case "library":
+                                       RootContext.Target = Target.Library;
+                                       RootContext.TargetExt = ".dll";
+                                       break;
+                                       
+                               case "exe":
+                                       RootContext.Target = Target.Exe;
+                                       break;
+                                       
+                               case "winexe":
+                                       RootContext.Target = Target.WinExe;
+                                       break;
+                                       
+                               case "module":
+                                       RootContext.Target = Target.Module;
+                                       RootContext.TargetExt = ".dll";
+                                       break;
+                               default:
+                                       TargetUsage ();
+                                       break;
+                               }
+                               return true;
+                               
+                       case "-r":
+                               Report.Warning (-29, 1, "Compatibility: Use -r:LIBRARY instead of -r library");
+                               if ((i + 1) >= args.Length){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               
+                               string val = args [++i];
+                               int idx = val.IndexOf ('=');
+                               if (idx > -1) {
+                                       string alias = val.Substring (0, idx);
+                                       string assembly = val.Substring (idx + 1);
+                                       AddExternAlias (alias, assembly);
+                                       return true;
+                               }
+
+                               references.Add (val);
+                               return true;
+                               
+                       case "-L":
+                               Report.Warning (-29, 1, "Compatibility: Use -lib:ARG instead of --L arg");
+                               if ((i + 1) >= args.Length){
+                                       Usage ();       
+                                       Environment.Exit (1);
+                               }
+                               link_paths.Add (args [++i]);
+                               return true;
+                               
+                       case "--nostdlib":
+                               Report.Warning (-29, 1, "Compatibility: Use -nostdlib instead of --nostdlib");
+                               RootContext.StdLib = false;
+                               return true;
+                               
+                       case "--fatal":
+                               Report.Fatal = true;
+                               return true;
+                               
+                       case "--werror":
+                               Report.Warning (-29, 1, "Compatibility: Use -warnaserror: option instead of --werror");
+                               Report.WarningsAreErrors = true;
+                               return true;
+
+                       case "--nowarn":
+                               Report.Warning (-29, 1, "Compatibility: Use -nowarn instead of --nowarn");
+                               if ((i + 1) >= args.Length){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               int warn = 0;
+                               
+                               try {
+                                       warn = Int32.Parse (args [++i]);
+                               } catch {
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               Report.SetIgnoreWarning (warn);
+                               return true;
+                               
+                       case "--wlevel":
+                               Report.Warning (-29, 1, "Compatibility: Use -warn:LEVEL instead of --wlevel LEVEL");
+                               if ((i + 1) >= args.Length){
+                                       Report.Error (
+                                               1900,
+                                               "--wlevel requires a value from 0 to 4");
+                                       Environment.Exit (1);
+                               }
+
+                               SetWarningLevel (args [++i]);
+                               return true;
+
+                       case "--mcs-debug":
+                               if ((i + 1) >= args.Length){
+                                       Report.Error (5, "--mcs-debug requires an argument");
+                                       Environment.Exit (1);
+                               }
+
+                               try {
+                                       Report.DebugFlags = Int32.Parse (args [++i]);
+                               } catch {
+                                       Report.Error (5, "Invalid argument to --mcs-debug");
+                                       Environment.Exit (1);
+                               }
+                               return true;
+                               
+                       case "--about":
+                               About ();
+                               return true;
+                               
+                       case "--recurse":
+                               Report.Warning (-29, 1, "Compatibility: Use -recurse:PATTERN option instead --recurse PATTERN");
+                               if ((i + 1) >= args.Length){
+                                       Report.Error (5, "--recurse requires an argument");
+                                       Environment.Exit (1);
+                               }
+                               CompileFiles (args [++i], true); 
+                               return true;
+                               
+                       case "--timestamp":
+                               timestamps = true;
+                               last_time = first_time = DateTime.Now;
+                               return true;
+
+                       case "--pause":
+                               pause = true;
+                               return true;
+                               
+                       case "--debug": case "-g":
+                               Report.Warning (-29, 1, "Compatibility: Use -debug option instead of -g or --debug");
+                               want_debugging_support = true;
+                               return true;
+                               
+                       case "--noconfig":
+                               Report.Warning (-29, 1, "Compatibility: Use -noconfig option instead of --noconfig");
+                               load_default_config = false;
+                               return true;
+                       }
+
+                       return false;
+               }
+
+               //
+               // This parses the -arg and /arg options to the compiler, even if the strings
+               // in the following text use "/arg" on the strings.
+               //
+               static bool CSCParseOption (string option, ref string [] args, ref int i)
+               {
+                       int idx = option.IndexOf (':');
+                       string arg, value;
+
+                       if (idx == -1){
+                               arg = option;
+                               value = "";
+                       } else {
+                               arg = option.Substring (0, idx);
+
+                               value = option.Substring (idx + 1);
+                       }
+
+                       switch (arg){
+                       case "/nologo":
+                               return true;
+
+                       case "/t":
+                       case "/target":
+                               switch (value){
+                               case "exe":
+                                       RootContext.Target = Target.Exe;
+                                       break;
+
+                               case "winexe":
+                                       RootContext.Target = Target.WinExe;
+                                       break;
+
+                               case "library":
+                                       RootContext.Target = Target.Library;
+                                       RootContext.TargetExt = ".dll";
+                                       break;
+
+                               case "module":
+                                       RootContext.Target = Target.Module;
+                                       RootContext.TargetExt = ".netmodule";
+                                       break;
+
+                               default:
+                                       TargetUsage ();
+                                       break;
+                               }
+                               return true;
+
+                       case "/out":
+                               if (value.Length == 0){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               OutputFile = value;
+                               return true;
+
+                       case "/optimize":
+                       case "/optimize+":
+                               RootContext.Optimize = true;
+                               return true;
+
+                       case "/optimize-":
+                               RootContext.Optimize = false;
+                               return true;
+
+                       case "/incremental":
+                       case "/incremental+":
+                       case "/incremental-":
+                               // nothing.
+                               return true;
+
+                       case "/d":
+                       case "/define": {
+                               string [] defs;
+
+                               if (value.Length == 0){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+
+                               defs = value.Split (new Char [] {';', ','});
+                               foreach (string d in defs){
+                                       defines.Add (d);
+                               }
+                               return true;
+                       }
+
+                       case "/bugreport":
+                               //
+                               // We should collect data, runtime, etc and store in the file specified
+                               //
+                               Console.WriteLine ("To file bug reports, please visit: http://www.mono-project.com/Bugs");
+                               return true;
+
+                       case "/pkg": {
+                               string packages;
+
+                               if (value.Length == 0){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               packages = String.Join (" ", value.Split (new Char [] { ';', ',', '\n', '\r'}));
+                               
+                               ProcessStartInfo pi = new ProcessStartInfo ();
+                               pi.FileName = "pkg-config";
+                               pi.RedirectStandardOutput = true;
+                               pi.UseShellExecute = false;
+                               pi.Arguments = "--libs " + packages;
+                               Process p = null;
+                               try {
+                                       p = Process.Start (pi);
+                               } catch (Exception e) {
+                                       Report.Error (-27, "Couldn't run pkg-config: " + e.Message);
+                                       Environment.Exit (1);
+                               }
+
+                               if (p.StandardOutput == null){
+                                       Report.Warning (-27, 1, "Specified package did not return any information");
+                                       return true;
+                               }
+                               string pkgout = p.StandardOutput.ReadToEnd ();
+                               p.WaitForExit ();
+                               if (p.ExitCode != 0) {
+                                       Report.Error (-27, "Error running pkg-config. Check the above output.");
+                                       Environment.Exit (1);
+                               }
+
+                               if (pkgout != null){
+                                       string [] xargs = pkgout.Trim (new Char [] {' ', '\n', '\r', '\t'}).
+                                               Split (new Char [] { ' ', '\t'});
+                                       args = AddArgs (args, xargs);
+                               }
+                               
+                               p.Close ();
+                               return true;
+                       }
+                               
+                       case "/linkres":
+                       case "/linkresource":
+                       case "/res":
+                       case "/resource":
+                               if (embedded_resources == null)
+                                       embedded_resources = new Resources ();
+
+                               bool embeded = arg.StartsWith ("/r");
+                               string[] s = value.Split (',');
+                               switch (s.Length) {
+                                       case 1:
+                                               if (s[0].Length == 0)
+                                                       goto default;
+                                               embedded_resources.Add (embeded, s [0], Path.GetFileName (s[0]));
+                                               break;
+                                       case 2:
+                                               embedded_resources.Add (embeded, s [0], s [1]);
+                                               break;
+                                       case 3:
+                                               if (s [2] != "public" && s [2] != "private") {
+                                                       Report.Error (1906, "Invalid resource visibility option `{0}'. Use either `public' or `private' instead", s [2]);
+                                                       return true;
+                                               }
+                                               embedded_resources.Add (embeded, s [0], s [1], s [2] == "private");
+                                               break;
+                                       default:
+                                               Report.Error (-2005, "Wrong number of arguments for option `{0}'", option);
+                                               break;
+                               }
+
+                               return true;
+                               
+                       case "/recurse":
+                               if (value.Length == 0){
+                                       Report.Error (5, "-recurse requires an argument");
+                                       Environment.Exit (1);
+                               }
+                               CompileFiles (value, true); 
+                               return true;
+
+                       case "/r":
+                       case "/reference": {
+                               if (value.Length == 0){
+                                       Report.Error (5, "-reference requires an argument");
+                                       Environment.Exit (1);
+                               }
+
+                               string [] refs = value.Split (new char [] { ';', ',' });
+                               foreach (string r in refs){
+                                       string val = r;
+                                       int index = val.IndexOf ('=');
+                                       if (index > -1) {
+                                               string alias = r.Substring (0, index);
+                                               string assembly = r.Substring (index + 1);
+                                               AddExternAlias (alias, assembly);
+                                               return true;
+                                       }
+                                       
+                                       references.Add (val);
+                               }
+                               return true;
+                       }
+                       case "/addmodule": {
+                               if (value.Length == 0){
+                                       Report.Error (5, arg + " requires an argument");
+                                       Environment.Exit (1);
+                               }
+
+                               string [] refs = value.Split (new char [] { ';', ',' });
+                               foreach (string r in refs){
+                                       modules.Add (r);
+                               }
+                               return true;
+                       }
+                       case "/win32res": {
+                               if (value.Length == 0) {
+                                       Report.Error (5, arg + " requires an argument");
+                                       Environment.Exit (1);
+                               }
+
+                               win32ResourceFile = value;
+                               return true;
+                       }
+                       case "/win32icon": {
+                               if (value.Length == 0) {
+                                       Report.Error (5, arg + " requires an argument");
+                                       Environment.Exit (1);
+                               }
+
+                               win32IconFile = value;
+                               return true;
+                       }
+                       case "/doc": {
+                               if (value.Length == 0){
+                                       Report.Error (2006, arg + " requires an argument");
+                                       Environment.Exit (1);
+                               }
+                               RootContext.Documentation = new Documentation (value);
+                               return true;
+                       }
+                       case "/lib": {
+                               string [] libdirs;
+                               
+                               if (value.Length == 0){
+                                       Report.Error (5, "/lib requires an argument");
+                                       Environment.Exit (1);
+                               }
+
+                               libdirs = value.Split (new Char [] { ',' });
+                               foreach (string dir in libdirs)
+                                       link_paths.Add (dir);
+                               return true;
+                       }
+
+                       case "/debug-":
+                               want_debugging_support = false;
+                               return true;
+                               
+                       case "/debug":
+                       case "/debug+":
+                               want_debugging_support = true;
+                               return true;
+
+                       case "/checked":
+                       case "/checked+":
+                               RootContext.Checked = true;
+                               return true;
+
+                       case "/checked-":
+                               RootContext.Checked = false;
+                               return true;
+
+                       case "/clscheck":
+                       case "/clscheck+":
+                               return true;
+
+                       case "/clscheck-":
+                               RootContext.VerifyClsCompliance = false;
+                               return true;
+
+                       case "/unsafe":
+                       case "/unsafe+":
+                               RootContext.Unsafe = true;
+                               return true;
+
+                       case "/unsafe-":
+                               RootContext.Unsafe = false;
+                               return true;
+
+                       case "/warnaserror":
+                       case "/warnaserror+":
+                               Report.WarningsAreErrors = true;
+                               return true;
+
+                       case "/warnaserror-":
+                               Report.WarningsAreErrors = false;
+                               return true;
+
+                       case "/warn":
+                               SetWarningLevel (value);
+                               return true;
+
+                       case "/nowarn": {
+                               string [] warns;
+
+                               if (value.Length == 0){
+                                       Report.Error (5, "/nowarn requires an argument");
+                                       Environment.Exit (1);
+                               }
+                               
+                               warns = value.Split (new Char [] {','});
+                               foreach (string wc in warns){
+                                       try {
+                                               int warn = Int32.Parse (wc);
+                                               if (warn < 1) {
+                                                       throw new ArgumentOutOfRangeException("warn");
+                                               }
+                                               Report.SetIgnoreWarning (warn);
+                                       } catch {
+                                               Report.Error (1904, String.Format("`{0}' is not a valid warning number", wc));
+                                       }
+                               }
+                               return true;
+                       }
+
+                       case "/noconfig-":
+                               load_default_config = true;
+                               return true;
+                               
+                       case "/noconfig":
+                       case "/noconfig+":
+                               load_default_config = false;
+                               return true;
+
+                       case "/help2":
+                               OtherFlags ();
+                               Environment.Exit(0);
+                               return true;
+                               
+                       case "/help":
+                       case "/?":
+                               Usage ();
+                               Environment.Exit (0);
+                               return true;
+
+                       case "/main":
+                       case "/m":
+                               if (value.Length == 0){
+                                       Report.Error (5, arg + " requires an argument");                                        
+                                       Environment.Exit (1);
+                               }
+                               RootContext.MainClass = value;
+                               return true;
+
+                       case "/nostdlib":
+                       case "/nostdlib+":
+                               RootContext.StdLib = false;
+                               return true;
+
+                       case "/nostdlib-":
+                               RootContext.StdLib = true;
+                               return true;
+
+                       case "/fullpaths":
+                               return true;
+
+                       case "/keyfile":
+                               if (value == String.Empty) {
+                                       Report.Error (5, arg + " requires an argument");
+                                       Environment.Exit (1);
+                               }
+                               RootContext.StrongNameKeyFile = value;
+                               return true;
+                       case "/keycontainer":
+                               if (value == String.Empty) {
+                                       Report.Error (5, arg + " requires an argument");
+                                       Environment.Exit (1);
+                               }
+                               RootContext.StrongNameKeyContainer = value;
+                               return true;
+                       case "/delaysign+":
+                               RootContext.StrongNameDelaySign = true;
+                               return true;
+                       case "/delaysign-":
+                               RootContext.StrongNameDelaySign = false;
+                               return true;
+
+                       case "/v2":
+                       case "/2":
+                               Console.WriteLine ("The compiler option -2 is obsolete. Please use /langversion instead");
+                               SetupV2 ();
+                               return true;
+                               
+                       case "/langversion":
+                               switch (value.ToLower (CultureInfo.InvariantCulture)) {
+                                       case "iso-1":
+                                               RootContext.Version = LanguageVersion.ISO_1;
+                                               return true;
+
+                                       case "default":
+                                               SetupV2 ();
+                                               return true;
+                               }
+                               Report.Error (1617, "Invalid option `{0}' for /langversion. It must be either `ISO-1' or `Default'", value);
+                               return true;
+
+                       case "/codepage":
+                               switch (value) {
+                               case "utf8":
+                                       encoding = new UTF8Encoding();
+                                       break;
+                               case "reset":
+                                       encoding = Encoding.Default;
+                                       break;
+                               default:
+                                       try {
+                                               encoding = Encoding.GetEncoding (
+                                               Int32.Parse (value));
+                                       } catch {
+                                               Report.Error (2016, "Code page `{0}' is invalid or not installed", value);
+                                       }
+                                       break;
+                               }
+                               return true;
+                       }
+
+                       return false;
+               }
+
+               static void Error_WrongOption (string option)
+               {
+                       Report.Error (2007, "Unrecognized command-line option: `{0}'", option);
+               }
+
+               static string [] AddArgs (string [] args, string [] extra_args)
+               {
+                       string [] new_args;
+                       new_args = new string [extra_args.Length + args.Length];
+
+                       // if args contains '--' we have to take that into account
+                       // split args into first half and second half based on '--'
+                       // and add the extra_args before --
+                       int split_position = Array.IndexOf (args, "--");
+                       if (split_position != -1)
+                       {
+                               Array.Copy (args, new_args, split_position);
+                               extra_args.CopyTo (new_args, split_position);
+                               Array.Copy (args, split_position, new_args, split_position + extra_args.Length, args.Length - split_position);
+                       }
+                       else
+                       {
+                               args.CopyTo (new_args, 0);
+                               extra_args.CopyTo (new_args, args.Length);
+                       }
+
+                       return new_args;
+               }
+
+               static void AddExternAlias (string identifier, string assembly)
+               {
+                       if (assembly.Length == 0) {
+                               Report.Error (1680, "Invalid reference alias '" + identifier + "='. Missing filename");
+                               return;
+                       }
+
+                       if (!IsExternAliasValid (identifier)) {
+                               Report.Error (1679, "Invalid extern alias for /reference. Alias '" + identifier + "' is not a valid identifier");
+                               return;
+                       }
+                       
+                       // Could here hashtable throw an exception?
+                       external_aliases [identifier] = assembly;
+               }
+               
+               static bool IsExternAliasValid (string identifier)
+               {
+                       if (identifier.Length == 0)
+                               return false;
+                       if (identifier [0] != '_' && !Char.IsLetter (identifier [0]))
+                               return false;
+
+                       for (int i = 1; i < identifier.Length; i++) {
+                               char c = identifier [i];
+                               if (Char.IsLetter (c) || Char.IsDigit (c))
+                                       continue;
+
+                               UnicodeCategory category = Char.GetUnicodeCategory (c);
+                               if (category != UnicodeCategory.Format || category != UnicodeCategory.NonSpacingMark ||
+                                               category != UnicodeCategory.SpacingCombiningMark ||
+                                               category != UnicodeCategory.ConnectorPunctuation)
+                                       return false;
+                       }
+                       
+                       return true;
+               }
+               
+               /// <summary>
+               ///    Parses the arguments, and drives the compilation
+               ///    process.
+               /// </summary>
+               ///
+               /// <remarks>
+               ///    TODO: Mostly structured to debug the compiler
+               ///    now, needs to be turned into a real driver soon.
+               /// </remarks>
+               // [MonoTODO("Change error code for unknown argument to something reasonable")]
+               internal static bool MainDriver (string [] args)
+               {
+                       int i;
+                       bool parsing_options = true;
+
+                       encoding = Encoding.Default;
+
+                       references = new ArrayList ();
+                       external_aliases = new Hashtable ();
+                       soft_references = new ArrayList ();
+                       modules = new ArrayList ();
+                       link_paths = new ArrayList ();
+
+                       SetupDefaultDefines ();
+                       
+                       //
+                       // Setup defaults
+                       //
+                       // This is not required because Assembly.Load knows about this
+                       // path.
+                       //
+
+                       Hashtable response_file_list = null;
+
+                       for (i = 0; i < args.Length; i++){
+                               string arg = args [i];
+                               if (arg.Length == 0)
+                                       continue;
+
+                               if (arg.StartsWith ("@")){
+                                       string [] extra_args;
+                                       string response_file = arg.Substring (1);
+
+                                       if (response_file_list == null)
+                                               response_file_list = new Hashtable ();
+                                       
+                                       if (response_file_list.Contains (response_file)){
+                                               Report.Error (
+                                                       1515, "Response file `" + response_file +
+                                                       "' specified multiple times");
+                                               Environment.Exit (1);
+                                       }
+                                       
+                                       response_file_list.Add (response_file, response_file);
+                                                   
+                                       extra_args = LoadArgs (response_file);
+                                       if (extra_args == null){
+                                               Report.Error (2011, "Unable to open response file: " +
+                                                             response_file);
+                                               return false;
+                                       }
+
+                                       args = AddArgs (args, extra_args);
+                                       continue;
+                               }
+
+                               if (parsing_options){
+                                       if (arg == "--"){
+                                               parsing_options = false;
+                                               continue;
+                                       }
+                                       
+                                       if (arg.StartsWith ("-")){
+                                               if (UnixParseOption (arg, ref args, ref i))
+                                                       continue;
+
+                                               // Try a -CSCOPTION
+                                               string csc_opt = "/" + arg.Substring (1);
+                                               if (CSCParseOption (csc_opt, ref args, ref i))
+                                                       continue;
+
+                                               Error_WrongOption (arg);
+                                               return false;
+                                       } else {
+                                               if (arg [0] == '/'){
+                                                       if (CSCParseOption (arg, ref args, ref i))
+                                                               continue;
+
+                                                       // Need to skip `/home/test.cs' however /test.cs is considered as error
+                                                       if (arg.Length < 2 || arg.IndexOf ('/', 2) == -1) {
+                                                               Error_WrongOption (arg);
+                                                               return false;
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               CompileFiles (arg, false); 
+                       }
+
+                       ProcessFiles ();
+
+                       if (tokenize)
+                               return true;
+
+                       if (RootContext.ToplevelTypes.NamespaceEntry != null)
+                               throw new InternalErrorException ("who set it?");
+
+                       //
+                       // If we are an exe, require a source file for the entry point
+                       //
+                       if (RootContext.Target == Target.Exe || RootContext.Target == Target.WinExe || RootContext.Target == Target.Module){
+                               if (first_source == null){
+                                       Report.Error (2008, "No files to compile were specified");
+                                       return false;
+                               }
+
+                       }
+
+                       //
+                       // If there is nothing to put in the assembly, and we are not a library
+                       //
+                       if (first_source == null && embedded_resources == null){
+                               Report.Error (2008, "No files to compile were specified");
+                               return false;
+                       }
+
+                       if (Report.Errors > 0)
+                               return false;
+                       
+                       if (parse_only)
+                               return true;
+
+                       //
+                       // Load Core Library for default compilation
+                       //
+                       if (RootContext.StdLib)
+                               references.Insert (0, "mscorlib");
+
+                       if (load_default_config)
+                               DefineDefaultConfig ();
+
+                       if (Report.Errors > 0){
+                               return false;
+                       }
+
+                       //
+                       // Load assemblies required
+                       //
+                       if (timestamps)
+                               ShowTime ("Loading references");
+                       link_paths.Add (GetSystemDir ());
+                       link_paths.Add (Directory.GetCurrentDirectory ());
+                       LoadReferences ();
+                       
+                       if (timestamps)
+                               ShowTime ("   References loaded");
+                       
+                       if (Report.Errors > 0){
+                               return false;
+                       }
+
+                       //
+                       // Quick hack
+                       //
+                       if (output_file == null){
+                               if (first_source == null){
+                                       Report.Error (1562, "If no source files are specified you must specify the output file with -out:");
+                                       return false;
+                               }
+                                       
+                               int pos = first_source.LastIndexOf ('.');
+
+                               if (pos > 0)
+                                       output_file = first_source.Substring (0, pos) + RootContext.TargetExt;
+                               else
+                                       output_file = first_source + RootContext.TargetExt;
+                       }
+
+                       if (!CodeGen.Init (output_file, output_file, want_debugging_support))
+                               return false;
+
+                       if (RootContext.Target == Target.Module) {
+                               PropertyInfo module_only = typeof (AssemblyBuilder).GetProperty ("IsModuleOnly", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
+                               if (module_only == null) {
+                                       Report.RuntimeMissingSupport (Location.Null, "/target:module");
+                                       Environment.Exit (1);
+                               }
+
+                               MethodInfo set_method = module_only.GetSetMethod (true);
+                               set_method.Invoke (CodeGen.Assembly.Builder, BindingFlags.Default, null, new object[]{true}, null);
+                       }
+
+                       RootNamespace.Global.AddModuleReference (CodeGen.Module.Builder);
+
+                       if (modules.Count > 0) {
+                               foreach (string module in modules)
+                                       LoadModule (module);
+                       }
+                       
+                       //
+                       // Before emitting, we need to get the core
+                       // types emitted from the user defined types
+                       // or from the system ones.
+                       //
+                       if (timestamps)
+                               ShowTime ("Initializing Core Types");
+                       if (!RootContext.StdLib){
+                               RootContext.ResolveCore ();
+                               if (Report.Errors > 0)
+                                       return false;
+                       }
+                       
+                       TypeManager.InitCoreTypes ();
+                       if (timestamps)
+                               ShowTime ("   Core Types done");
+
+                       CodeGen.Module.Resolve ();
+
+                       //
+                       // The second pass of the compiler
+                       //
+                       if (timestamps)
+                               ShowTime ("Resolving tree");
+                       RootContext.ResolveTree ();
+
+                       if (Report.Errors > 0)
+                               return false;
+                       if (timestamps)
+                               ShowTime ("Populate tree");
+                       if (!RootContext.StdLib)
+                               RootContext.BootCorlib_PopulateCoreTypes ();
+                       RootContext.PopulateTypes ();
+
+                       TypeManager.InitCodeHelpers ();
+
+                       RootContext.DefineTypes ();
+                       
+                       if (Report.Errors == 0 &&
+                               RootContext.Documentation != null &&
+                               !RootContext.Documentation.OutputDocComment (
+                                       output_file))
+                               return false;
+
+                       //
+                       // Verify using aliases now
+                       //
+                       NamespaceEntry.VerifyAllUsing ();
+                       
+                       if (Report.Errors > 0){
+                               return false;
+                       }
+
+                       CodeGen.Assembly.Resolve ();
+                       
+                       if (RootContext.VerifyClsCompliance) {
+                               if (CodeGen.Assembly.IsClsCompliant) {
+                                       AttributeTester.VerifyModulesClsCompliance ();
+                                       TypeManager.LoadAllImportedTypes ();
+                               }
+                       }
+                       if (Report.Errors > 0)
+                               return false;
+                       
+                       //
+                       // The code generator
+                       //
+                       if (timestamps)
+                               ShowTime ("Emitting code");
+                       ShowTotalTime ("Total so far");
+                       RootContext.EmitCode ();
+                       if (timestamps)
+                               ShowTime ("   done");
+
+                       if (Report.Errors > 0){
+                               return false;
+                       }
+
+                       if (timestamps)
+                               ShowTime ("Closing types");
+
+                       RootContext.CloseTypes ();
+
+                       PEFileKinds k = PEFileKinds.ConsoleApplication;
+
+                       switch (RootContext.Target) {
+                       case Target.Library:
+                       case Target.Module:
+                               k = PEFileKinds.Dll; break;
+                       case Target.Exe:
+                               k = PEFileKinds.ConsoleApplication; break;
+                       case Target.WinExe:
+                               k = PEFileKinds.WindowApplication; break;
+                       }
+
+                       if (RootContext.NeedsEntryPoint) {
+                               MethodInfo ep = RootContext.EntryPoint;
+
+                               if (ep == null) {
+                                       if (RootContext.MainClass != null) {
+                                               DeclSpace main_cont = RootContext.ToplevelTypes.GetDefinition (RootContext.MainClass) as DeclSpace;
+                                               if (main_cont == null) {
+                                                       Report.Error (1555, "Could not find `{0}' specified for Main method", RootContext.MainClass); 
+                                                       return false;
+                                               }
+
+                                               if (!(main_cont is ClassOrStruct)) {
+                                                       Report.Error (1556, "`{0}' specified for Main method must be a valid class or struct", RootContext.MainClass);
+                                                       return false;
+                                               }
+
+                                               Report.Error (1558, main_cont.Location, "`{0}' does not have a suitable static Main method", main_cont.GetSignatureForError ());
+                                               return false;
+                                       }
+
+                                       if (Report.Errors == 0)
+                                               Report.Error (5001, "Program `{0}' does not contain a static `Main' method suitable for an entry point",
+                                                       output_file);
+                                       return false;
+                               }
+
+                               CodeGen.Assembly.Builder.SetEntryPoint (ep, k);
+                       } else if (RootContext.MainClass != null) {
+                               Report.Error (2017, "Cannot specify -main if building a module or library");
+                       }
+
+                       if (embedded_resources != null){
+                               if (RootContext.Target == Target.Module) {
+                                       Report.Error (1507, "Cannot link resource file when building a module");
+                                       return false;
+                               }
+
+                               embedded_resources.Emit ();
+                       }
+
+                       //
+                       // Add Win32 resources
+                       //
+
+                       CodeGen.Assembly.Builder.DefineVersionInfoResource ();
+
+                       if (win32ResourceFile != null) {
+                               try {
+                                       CodeGen.Assembly.Builder.DefineUnmanagedResource (win32ResourceFile);
+                               }
+                               catch (ArgumentException) {
+                                       Report.RuntimeMissingSupport (Location.Null, "resource embeding");
+                               }
+                       }
+
+                       if (win32IconFile != null) {
+                               MethodInfo define_icon = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
+                               if (define_icon == null) {
+                                       Report.RuntimeMissingSupport (Location.Null, "resource embeding");
+                               }
+                               define_icon.Invoke (CodeGen.Assembly.Builder, new object [] { win32IconFile });
+                       }
+
+                       if (Report.Errors > 0)
+                               return false;
+                       
+                       CodeGen.Save (output_file);
+                       if (timestamps) {
+                               ShowTime ("Saved output");
+                               ShowTotalTime ("Total");
+                       }
+
+                       Timer.ShowTimers ();
+                       
+                       if (Report.ExpectedError != 0) {
+                               if (Report.Errors == 0) {
+                                       Console.WriteLine ("Failed to report expected error " + Report.ExpectedError + ".\n" +
+                                               "No other errors reported.");
+                                       
+                                       Environment.Exit (2);
+                               } else {
+                                       Console.WriteLine ("Failed to report expected error " + Report.ExpectedError + ".\n" +
+                                               "However, other errors were reported.");
+                                       
+                                       Environment.Exit (1);
+                               }
+                               
+                               
+                               return false;
+                       }
+
+#if DEBUGME
+                       Console.WriteLine ("Size of strings held: " + DeclSpace.length);
+                       Console.WriteLine ("Size of strings short: " + DeclSpace.small);
+#endif
+                       return (Report.Errors == 0);
+               }
+       }
+
+       class Resources
+       {
+               interface IResource
+               {
+                       void Emit ();
+                       string FileName { get; }
+               }
+
+               class EmbededResource : IResource
+               {
+                       static MethodInfo embed_res;
+
+                       static EmbededResource () {
+                               Type[] argst = new Type [] { 
+                                                                                          typeof (string), typeof (string), typeof (ResourceAttributes)
+                                                                                  };
+
+                               embed_res = typeof (AssemblyBuilder).GetMethod (
+                                       "EmbedResourceFile", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic,
+                                       null, CallingConventions.Any, argst, null);
+                               
+                               if (embed_res == null) {
+                                       Report.RuntimeMissingSupport (Location.Null, "Resource embedding");
+                               }
+                       }
+
+                       readonly object[] args;
+
+                       public EmbededResource (string name, string file, bool isPrivate)
+                       {
+                               args = new object [3];
+                               args [0] = name;
+                               args [1] = file;
+                               args [2] = isPrivate ? ResourceAttributes.Private : ResourceAttributes.Public;
+                       }
+
+                       public void Emit()
+                       {
+                               embed_res.Invoke (CodeGen.Assembly.Builder, args);
+                       }
+
+                       public string FileName {
+                               get {
+                                       return (string)args [1];
+                               }
+                       }
+               }
+
+               class LinkedResource : IResource
+               {
+                       readonly string file;
+                       readonly string name;
+                       readonly ResourceAttributes attribute;
+
+                       public LinkedResource (string name, string file, bool isPrivate)
+                       {
+                               this.name = name;
+                               this.file = file;
+                               this.attribute = isPrivate ? ResourceAttributes.Private : ResourceAttributes.Public;
+                       }
+
+                       public void Emit ()
+                       {
+                               CodeGen.Assembly.Builder.AddResourceFile (name, Path.GetFileName(file), attribute);
+                       }
+
+                       public string FileName {
+                               get {
+                                       return file;
+                               }
+                       }
+               }
+
+
+               IDictionary embedded_resources = new HybridDictionary ();
+
+               public void Add (bool embeded, string file, string name)
+               {
+                       Add (embeded, file, name, false);
+               }
+
+               public void Add (bool embeded, string file, string name, bool isPrivate)
+               {
+                       if (embedded_resources.Contains (name)) {
+                               Report.Error (1508, "The resource identifier `{0}' has already been used in this assembly", name);
+                               return;
+                       }
+                       IResource r = embeded ? 
+                               (IResource) new EmbededResource (name, file, isPrivate) : 
+                               new LinkedResource (name, file, isPrivate);
+
+                       embedded_resources.Add (name, r);
+               }
+
+               public void Emit ()
+               {
+                       foreach (IResource r in embedded_resources.Values) {
+                               if (!File.Exists (r.FileName)) {
+                                       Report.Error (1566, "Error reading resource file `{0}'", r.FileName);
+                                       continue;
+                               }
+                               
+                               r.Emit ();
+                       }
+               }
+       }
+
+       //
+       // This is the only public entry point
+       //
+       public class CompilerCallableEntryPoint : MarshalByRefObject {
+               public static bool InvokeCompiler (string [] args, TextWriter error)
+               {
+                       Report.Stderr = error;
+                       try {
+                               return Driver.MainDriver (args) && Report.Errors == 0;
+                       }
+                       finally {
+                               Report.Stderr = Console.Error;
+                               Reset ();
+                       }
+               }
+
+               public static int[] AllWarningNumbers {
+                       get {
+                               return Report.AllWarnings;
+                       }
+               }
+               
+               static void Reset ()
+               {
+                       Driver.Reset ();
+                       Location.Reset ();
+                       RootContext.Reset ();
+                       Report.Reset ();
+                       TypeManager.Reset ();
+                       TypeHandle.Reset ();
+                       RootNamespace.Reset ();
+                       NamespaceEntry.Reset ();
+                       CodeGen.Reset ();
+                       Attribute.Reset ();
+                       AttributeTester.Reset ();
+               }
+       }
+}
diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs
new file mode 100644 (file)
index 0000000..6f51d61
--- /dev/null
@@ -0,0 +1,4205 @@
+//
+// ecore.cs: Core of the Expression representation for the intermediate tree.
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//   Marek Safar (marek.safar@seznam.cz)
+//
+// (C) 2001, 2002, 2003 Ximian, Inc.
+//
+//
+
+namespace Mono.CSharp {
+       using System;
+       using System.Collections;
+       using System.Diagnostics;
+       using System.Reflection;
+       using System.Reflection.Emit;
+       using System.Text;
+
+       /// <remarks>
+       ///   The ExprClass class contains the is used to pass the 
+       ///   classification of an expression (value, variable, namespace,
+       ///   type, method group, property access, event access, indexer access,
+       ///   nothing).
+       /// </remarks>
+       public enum ExprClass : byte {
+               Invalid,
+               
+               Value,
+               Variable,
+               Namespace,
+               Type,
+               MethodGroup,
+               PropertyAccess,
+               EventAccess,
+               IndexerAccess,
+               Nothing, 
+       }
+
+       /// <remarks>
+       ///   This is used to tell Resolve in which types of expressions we're
+       ///   interested.
+       /// </remarks>
+       [Flags]
+       public enum ResolveFlags {
+               // Returns Value, Variable, PropertyAccess, EventAccess or IndexerAccess.
+               VariableOrValue         = 1,
+
+               // Returns a type expression.
+               Type                    = 2,
+
+               // Returns a method group.
+               MethodGroup             = 4,
+
+               // Mask of all the expression class flags.
+               MaskExprClass           = 7,
+
+               // Disable control flow analysis while resolving the expression.
+               // This is used when resolving the instance expression of a field expression.
+               DisableFlowAnalysis     = 8,
+
+               // Set if this is resolving the first part of a MemberAccess.
+               Intermediate            = 16,
+
+               // Disable control flow analysis _of struct_ while resolving the expression.
+               // This is used when resolving the instance expression of a field expression.
+               DisableStructFlowAnalysis       = 32,
+
+       }
+
+       //
+       // This is just as a hint to AddressOf of what will be done with the
+       // address.
+       [Flags]
+       public enum AddressOp {
+               Store = 1,
+               Load  = 2,
+               LoadStore = 3
+       };
+       
+       /// <summary>
+       ///   This interface is implemented by variables
+       /// </summary>
+       public interface IMemoryLocation {
+               /// <summary>
+               ///   The AddressOf method should generate code that loads
+               ///   the address of the object and leaves it on the stack.
+               ///
+               ///   The `mode' argument is used to notify the expression
+               ///   of whether this will be used to read from the address or
+               ///   write to the address.
+               ///
+               ///   This is just a hint that can be used to provide good error
+               ///   reporting, and should have no other side effects. 
+               /// </summary>
+               void AddressOf (EmitContext ec, AddressOp mode);
+       }
+
+       /// <summary>
+       ///   This interface is implemented by variables
+       /// </summary>
+       public interface IVariable {
+               VariableInfo VariableInfo {
+                       get;
+               }
+
+               bool VerifyFixed ();
+       }
+
+       /// <remarks>
+       ///   Base class for expressions
+       /// </remarks>
+       public abstract class Expression {
+               public ExprClass eclass;
+               protected Type type;
+               protected Location loc;
+               
+               public Type Type {
+                       get { return type; }
+                       set { type = value; }
+               }
+
+               public virtual Location Location {
+                       get { return loc; }
+               }
+
+               /// <summary>
+               ///   Utility wrapper routine for Error, just to beautify the code
+               /// </summary>
+               public void Error (int error, string s)
+               {
+                       Report.Error (error, loc, s);
+               }
+
+               // Not nice but we have broken hierarchy.
+               public virtual void CheckMarshalByRefAccess ()
+               {
+               }
+
+               public virtual bool GetAttributableValue (Type valueType, out object value)
+               {
+                       Attribute.Error_AttributeArgumentNotValid (loc);
+                       value = null;
+                       return false;
+               }
+
+               public virtual string GetSignatureForError ()
+               {
+                       return TypeManager.CSharpName (type);
+               }
+
+               public static bool IsAccessorAccessible (Type invocation_type, MethodInfo mi, out bool must_do_cs1540_check)
+               {
+                       MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;
+
+                       must_do_cs1540_check = false; // by default we do not check for this
+
+                       if (ma == MethodAttributes.Public)
+                               return true;
+                       
+                       //
+                       // If only accessible to the current class or children
+                       //
+                       if (ma == MethodAttributes.Private)
+                               return TypeManager.IsPrivateAccessible (invocation_type, mi.DeclaringType) ||
+                                       TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType);
+
+                       if (mi.DeclaringType.Assembly == invocation_type.Assembly ||
+                                       TypeManager.IsFriendAssembly (mi.DeclaringType.Assembly)) {
+                               if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
+                                       return true;
+                       } else {
+                               if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
+                                       return false;
+                       }
+
+                       // Family and FamANDAssem require that we derive.
+                       // FamORAssem requires that we derive if in different assemblies.
+                       if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType))
+                               return false;
+
+                       if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType))
+                               must_do_cs1540_check = true;
+
+                       return true;
+               }
+
+               /// <summary>
+               ///   Performs semantic analysis on the Expression
+               /// </summary>
+               ///
+               /// <remarks>
+               ///   The Resolve method is invoked to perform the semantic analysis
+               ///   on the node.
+               ///
+               ///   The return value is an expression (it can be the
+               ///   same expression in some cases) or a new
+               ///   expression that better represents this node.
+               ///   
+               ///   For example, optimizations of Unary (LiteralInt)
+               ///   would return a new LiteralInt with a negated
+               ///   value.
+               ///   
+               ///   If there is an error during semantic analysis,
+               ///   then an error should be reported (using Report)
+               ///   and a null value should be returned.
+               ///   
+               ///   There are two side effects expected from calling
+               ///   Resolve(): the the field variable "eclass" should
+               ///   be set to any value of the enumeration
+               ///   `ExprClass' and the type variable should be set
+               ///   to a valid type (this is the type of the
+               ///   expression).
+               /// </remarks>
+               public abstract Expression DoResolve (EmitContext ec);
+
+               public virtual Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       return null;
+               }
+
+               //
+               // This is used if the expression should be resolved as a type or namespace name.
+               // the default implementation fails.   
+               //
+               public virtual FullNamedExpression ResolveAsTypeStep (IResolveContext ec,  bool silent)
+               {
+                       return null;
+               }
+
+               //
+               // This is used to resolve the expression as a type, a null
+               // value will be returned if the expression is not a type
+               // reference
+               //
+               public virtual TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
+               {
+                       TypeExpr te = ResolveAsBaseTerminal (ec, silent);
+                       if (te == null)
+                               return null;
+
+                       if (!silent) {
+                               ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (te.Type);
+                               if (obsolete_attr != null && !ec.IsInObsoleteScope) {
+                                       AttributeTester.Report_ObsoleteMessage (obsolete_attr, te.GetSignatureForError (), Location);
+                               }
+                       }
+
+                       // Constrains don't need to be checked for overrides
+                       GenericMethod gm = ec.GenericDeclContainer as GenericMethod;
+                       if (gm != null && (gm.ModFlags & Modifiers.OVERRIDE) != 0) {
+                               te.loc = loc;
+                               return te;
+                       }
+
+                       ConstructedType ct = te as ConstructedType;
+                       if ((ct != null) && !ct.CheckConstraints (ec))
+                               return null;
+
+                       return te;
+               }
+
+               public TypeExpr ResolveAsBaseTerminal (IResolveContext ec, bool silent)
+               {
+                       int errors = Report.Errors;
+
+                       FullNamedExpression fne = ResolveAsTypeStep (ec, silent);
+
+                       if (fne == null)
+                               return null;
+
+                       if (fne.eclass != ExprClass.Type) {
+                               if (!silent && errors == Report.Errors)
+                                       fne.Error_UnexpectedKind (null, "type", loc);
+                               return null;
+                       }
+
+                       TypeExpr te = fne as TypeExpr;
+
+                       if (!te.CheckAccessLevel (ec.DeclContainer)) {
+                               Report.SymbolRelatedToPreviousError (te.Type);
+                               ErrorIsInaccesible (loc, TypeManager.CSharpName (te.Type));
+                               return null;
+                       }
+
+                       te.loc = loc;
+                       return te;
+               }
+
+               public static void ErrorIsInaccesible (Location loc, string name)
+               {
+                       Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", name);
+               }
+
+               protected static void Error_CannotAccessProtected (Location loc, MemberInfo m, Type qualifier, Type container)
+               {
+                       Report.Error (1540, loc, "Cannot access protected member `{0}' via a qualifier of type `{1}'."
+                               + " The qualifier must be of type `{2}' or derived from it", 
+                               TypeManager.GetFullNameSignature (m),
+                               TypeManager.CSharpName (qualifier),
+                               TypeManager.CSharpName (container));
+
+               }
+
+               protected void Error_CannotAssign (string to, string roContext)
+               {
+                       Report.Error (1656, loc, "Cannot assign to `{0}' because it is a `{1}'",
+                               to, roContext);
+               }
+
+               public static void Error_VoidInvalidInTheContext (Location loc)
+               {
+                       Report.Error (1547, loc, "Keyword `void' cannot be used in this context");
+               }
+
+               public virtual void Error_ValueCannotBeConverted (Location loc, Type target, bool expl)
+               {
+                       if (Type.FullName == target.FullName){
+                               Report.ExtraInformation (loc,
+                                       String.Format (
+                                       "The type {0} has two conflicting definitions, one comes from {1} and the other from {2}",
+                                       Type.FullName, Type.Assembly.FullName, target.Assembly.FullName));
+                                                        
+                       }
+
+                       if (expl) {
+                               Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",
+                                       GetSignatureForError (), TypeManager.CSharpName (target));
+                               return;
+                       }
+                       
+                       Expression e = (this is EnumConstant) ? ((EnumConstant)this).Child : this;
+                       bool b = Convert.ExplicitNumericConversion (e, target) != null;
+
+                       if (b || Convert.ExplicitReferenceConversionExists (Type, target) ||
+                               Convert.ExplicitUnsafe (e, target) != null || Convert.UserDefinedConversion (null, this, target, Location.Null, true) != null) {
+                               Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)",
+                                       TypeManager.CSharpName (Type), TypeManager.CSharpName (target));
+                               return;
+                       }
+
+                       if (Type != TypeManager.string_type && this is Constant && !(this is EmptyConstantCast)) {
+                               Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
+                                       ((Constant)(this)).GetValue ().ToString (), TypeManager.CSharpName (target));
+                               return;
+                       }
+
+                       Report.Error (29, loc, "Cannot implicitly convert type {0} to `{1}'",
+                               Type == TypeManager.anonymous_method_type ?
+                               "anonymous method" : "`" + GetSignatureForError () + "'",
+                               TypeManager.CSharpName (target));
+               }
+
+               protected static void Error_TypeDoesNotContainDefinition (Location loc, Type type, string name)
+               {
+                       Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'",
+                               TypeManager.CSharpName (type), name);
+               }
+
+               protected static void Error_ValueAssignment (Location loc)
+               {
+                       Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer");
+               }
+
+               ResolveFlags ExprClassToResolveFlags
+               {
+                       get {
+                               switch (eclass) {
+                                       case ExprClass.Type:
+                                       case ExprClass.Namespace:
+                                               return ResolveFlags.Type;
+
+                                       case ExprClass.MethodGroup:
+                                               return ResolveFlags.MethodGroup;
+
+                                       case ExprClass.Value:
+                                       case ExprClass.Variable:
+                                       case ExprClass.PropertyAccess:
+                                       case ExprClass.EventAccess:
+                                       case ExprClass.IndexerAccess:
+                                               return ResolveFlags.VariableOrValue;
+
+                                       default:
+                                               throw new Exception ("Expression " + GetType () +
+                                                       " ExprClass is Invalid after resolve");
+                               }
+                       }
+               }
+              
+               /// <summary>
+               ///   Resolves an expression and performs semantic analysis on it.
+               /// </summary>
+               ///
+               /// <remarks>
+               ///   Currently Resolve wraps DoResolve to perform sanity
+               ///   checking and assertion checking on what we expect from Resolve.
+               /// </remarks>
+               public Expression Resolve (EmitContext ec, ResolveFlags flags)
+               {
+                       if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type) 
+                               return ResolveAsTypeStep (ec, false);
+
+                       bool do_flow_analysis = ec.DoFlowAnalysis;
+                       bool omit_struct_analysis = ec.OmitStructFlowAnalysis;
+                       if ((flags & ResolveFlags.DisableFlowAnalysis) != 0)
+                               do_flow_analysis = false;
+                       if ((flags & ResolveFlags.DisableStructFlowAnalysis) != 0)
+                               omit_struct_analysis = true;
+
+                       Expression e;
+                       using (ec.WithFlowAnalysis (do_flow_analysis, omit_struct_analysis)) {
+                               if (this is SimpleName) {
+                                       bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate;
+                                       e = ((SimpleName) this).DoResolve (ec, intermediate);
+                               } else {
+                                       e = DoResolve (ec);
+                               }
+                       }
+
+                       if (e == null)
+                               return null;
+
+                       if ((flags & e.ExprClassToResolveFlags) == 0) {
+                               e.Error_UnexpectedKind (flags, loc);
+                               return null;
+                       }
+
+                       if (e.type == null && !(e is Namespace)) {
+                               throw new Exception (
+                                       "Expression " + e.GetType () +
+                                       " did not set its type after Resolve\n" +
+                                       "called from: " + this.GetType ());
+                       }
+
+                       return e;
+               }
+
+               /// <summary>
+               ///   Resolves an expression and performs semantic analysis on it.
+               /// </summary>
+               public Expression Resolve (EmitContext ec)
+               {
+                       Expression e = Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
+
+                       if (e != null && e.eclass == ExprClass.MethodGroup && RootContext.Version == LanguageVersion.ISO_1) {
+                               ((MethodGroupExpr) e).ReportUsageError ();
+                               return null;
+                       }
+                       return e;
+               }
+
+               public Constant ResolveAsConstant (EmitContext ec, MemberCore mc)
+               {
+                       Expression e = Resolve (ec);
+                       if (e == null)
+                               return null;
+
+                       Constant c = e as Constant;
+                       if (c != null)
+                               return c;
+
+                       Const.Error_ExpressionMustBeConstant (loc, mc.GetSignatureForError ());
+                       return null;
+               }
+
+               /// <summary>
+               ///   Resolves an expression for LValue assignment
+               /// </summary>
+               ///
+               /// <remarks>
+               ///   Currently ResolveLValue wraps DoResolveLValue to perform sanity
+               ///   checking and assertion checking on what we expect from Resolve
+               /// </remarks>
+               public Expression ResolveLValue (EmitContext ec, Expression right_side, Location loc)
+               {
+                       int errors = Report.Errors;
+                       bool out_access = right_side == EmptyExpression.OutAccess;
+
+                       Expression e = DoResolveLValue (ec, right_side);
+
+                       if (e != null && out_access && !(e is IMemoryLocation)) {
+                               // FIXME: There's no problem with correctness, the 'Expr = null' handles that.
+                               //        Enabling this 'throw' will "only" result in deleting useless code elsewhere,
+
+                               //throw new InternalErrorException ("ResolveLValue didn't return an IMemoryLocation: " +
+                               //                                e.GetType () + " " + e.GetSignatureForError ());
+                               e = null;
+                       }
+
+                       if (e == null) {
+                               if (errors == Report.Errors) {
+                                       if (out_access)
+                                               Report.Error (1510, loc, "A ref or out argument must be an assignable variable");
+                                       else
+                                               Error_ValueAssignment (loc);
+                               }
+                               return null;
+                       }
+
+                       if (e.eclass == ExprClass.Invalid)
+                               throw new Exception ("Expression " + e + " ExprClass is Invalid after resolve");
+
+                       if (e.eclass == ExprClass.MethodGroup) {
+                               ((MethodGroupExpr) e).ReportUsageError ();
+                               return null;
+                       }
+
+                       if ((e.type == null) && !(e is ConstructedType))
+                               throw new Exception ("Expression " + e + " did not set its type after Resolve");
+
+                       return e;
+               }
+
+               /// <summary>
+               ///   Emits the code for the expression
+               /// </summary>
+               ///
+               /// <remarks>
+               ///   The Emit method is invoked to generate the code
+               ///   for the expression.  
+               /// </remarks>
+               public abstract void Emit (EmitContext ec);
+
+               public virtual void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               {
+                       Emit (ec);
+                       ec.ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+               }
+
+               /// <summary>
+               ///   Protected constructor.  Only derivate types should
+               ///   be able to be created
+               /// </summary>
+
+               protected Expression ()
+               {
+                       eclass = ExprClass.Invalid;
+                       type = null;
+               }
+
+               /// <summary>
+               ///   Returns a literalized version of a literal FieldInfo
+               /// </summary>
+               ///
+               /// <remarks>
+               ///   The possible return values are:
+               ///      IntConstant, UIntConstant
+               ///      LongLiteral, ULongConstant
+               ///      FloatConstant, DoubleConstant
+               ///      StringConstant
+               ///
+               ///   The value returned is already resolved.
+               /// </remarks>
+               public static Constant Constantify (object v, Type t)
+               {
+                       if (t == TypeManager.int32_type)
+                               return new IntConstant ((int) v, Location.Null);
+                       else if (t == TypeManager.uint32_type)
+                               return new UIntConstant ((uint) v, Location.Null);
+                       else if (t == TypeManager.int64_type)
+                               return new LongConstant ((long) v, Location.Null);
+                       else if (t == TypeManager.uint64_type)
+                               return new ULongConstant ((ulong) v, Location.Null);
+                       else if (t == TypeManager.float_type)
+                               return new FloatConstant ((float) v, Location.Null);
+                       else if (t == TypeManager.double_type)
+                               return new DoubleConstant ((double) v, Location.Null);
+                       else if (t == TypeManager.string_type)
+                               return new StringConstant ((string) v, Location.Null);
+                       else if (t == TypeManager.short_type)
+                               return new ShortConstant ((short)v, Location.Null);
+                       else if (t == TypeManager.ushort_type)
+                               return new UShortConstant ((ushort)v, Location.Null);
+                       else if (t == TypeManager.sbyte_type)
+                               return new SByteConstant ((sbyte)v, Location.Null);
+                       else if (t == TypeManager.byte_type)
+                               return new ByteConstant ((byte)v, Location.Null);
+                       else if (t == TypeManager.char_type)
+                               return new CharConstant ((char)v, Location.Null);
+                       else if (t == TypeManager.bool_type)
+                               return new BoolConstant ((bool) v, Location.Null);
+                       else if (t == TypeManager.decimal_type)
+                               return new DecimalConstant ((decimal) v, Location.Null);
+                       else if (TypeManager.IsEnumType (t)){
+                               Type real_type = TypeManager.TypeToCoreType (v.GetType ());
+                               if (real_type == t)
+                                       real_type = System.Enum.GetUnderlyingType (real_type);
+
+                               Constant e = Constantify (v, real_type);
+
+                               return new EnumConstant (e, t);
+                       } else if (v == null && !TypeManager.IsValueType (t))
+                               return new NullLiteral (Location.Null);
+                       else
+                               throw new Exception ("Unknown type for constant (" + t +
+                                                    "), details: " + v);
+               }
+
+               /// <summary>
+               ///   Returns a fully formed expression after a MemberLookup
+               /// </summary>
+               /// 
+               public static Expression ExprClassFromMemberInfo (Type containerType, MemberInfo mi, Location loc)
+               {
+                       if (mi is EventInfo)
+                               return new EventExpr ((EventInfo) mi, loc);
+                       else if (mi is FieldInfo)
+                               return new FieldExpr ((FieldInfo) mi, loc);
+                       else if (mi is PropertyInfo)
+                               return new PropertyExpr (containerType, (PropertyInfo) mi, loc);
+                       else if (mi is Type){
+                               return new TypeExpression ((System.Type) mi, loc);
+                       }
+
+                       return null;
+               }
+
+               protected static ArrayList almostMatchedMembers = new ArrayList (4);
+
+               //
+               // FIXME: Probably implement a cache for (t,name,current_access_set)?
+               //
+               // This code could use some optimizations, but we need to do some
+               // measurements.  For example, we could use a delegate to `flag' when
+               // something can not any longer be a method-group (because it is something
+               // else).
+               //
+               // Return values:
+               //     If the return value is an Array, then it is an array of
+               //     MethodBases
+               //   
+               //     If the return value is an MemberInfo, it is anything, but a Method
+               //
+               //     null on error.
+               //
+               // FIXME: When calling MemberLookup inside an `Invocation', we should pass
+               // the arguments here and have MemberLookup return only the methods that
+               // match the argument count/type, unlike we are doing now (we delay this
+               // decision).
+               //
+               // This is so we can catch correctly attempts to invoke instance methods
+               // from a static body (scan for error 120 in ResolveSimpleName).
+               //
+               //
+               // FIXME: Potential optimization, have a static ArrayList
+               //
+
+               public static Expression MemberLookup (Type container_type, Type queried_type, string name,
+                                                      MemberTypes mt, BindingFlags bf, Location loc)
+               {
+                       return MemberLookup (container_type, null, queried_type, name, mt, bf, loc);
+               }
+
+               //
+               // Lookup type `queried_type' for code in class `container_type' with a qualifier of
+               // `qualifier_type' or null to lookup members in the current class.
+               //
+
+               public static Expression MemberLookup (Type container_type,
+                                                      Type qualifier_type, Type queried_type,
+                                                      string name, MemberTypes mt,
+                                                      BindingFlags bf, Location loc)
+               {
+                       almostMatchedMembers.Clear ();
+
+                       MemberInfo [] mi = TypeManager.MemberLookup (container_type, qualifier_type,
+                                                                    queried_type, mt, bf, name, almostMatchedMembers);
+
+                       if (mi == null)
+                               return null;
+
+                       if (mi.Length > 1) {
+                               bool is_interface = qualifier_type != null && qualifier_type.IsInterface;
+                               MemberInfo non_method = null;
+                               ArrayList methods = new ArrayList (2);
+
+                               foreach (MemberInfo m in mi) {
+                                       if (m is MethodBase) {
+                                               methods.Add (m);
+                                               continue;
+                                       }
+
+                                       if (non_method == null) {
+                                               non_method = m;
+                                               continue;
+                                       }
+
+                                       Report.SymbolRelatedToPreviousError (m);
+                                       Report.SymbolRelatedToPreviousError (non_method);
+                                       Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
+                                               TypeManager.GetFullNameSignature (m), TypeManager.GetFullNameSignature (non_method));
+                                       return null;
+                               }
+
+                               if (methods.Count == 0)
+                                       return null;
+
+                               if (non_method != null) {
+                                       MethodBase method = (MethodBase) methods [0];
+
+                                       if (method.DeclaringType == non_method.DeclaringType) {
+                                               // Cannot happen with C# code, but is valid in IL
+                                               Report.SymbolRelatedToPreviousError (method);
+                                               Report.SymbolRelatedToPreviousError (non_method);
+                                               Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
+                                                             TypeManager.GetFullNameSignature (non_method),
+                                                             TypeManager.CSharpSignature (method));
+                                               return null;
+                                       }
+
+                                       if (is_interface) {
+                                               Report.SymbolRelatedToPreviousError (method);
+                                               Report.SymbolRelatedToPreviousError (non_method);
+                                               Report.Warning (467, 2, loc, "Ambiguity between method `{0}' and non-method `{1}'. Using method `{0}'",
+                                                               TypeManager.CSharpSignature (method), TypeManager.GetFullNameSignature (non_method));
+                                       }
+                               }
+
+                               return new MethodGroupExpr (methods, loc);
+                       }
+
+                       if (mi [0] is MethodBase)
+                               return new MethodGroupExpr (mi, loc);
+
+                       return ExprClassFromMemberInfo (container_type, mi [0], loc);
+               }
+
+               public const MemberTypes AllMemberTypes =
+                       MemberTypes.Constructor |
+                       MemberTypes.Event       |
+                       MemberTypes.Field       |
+                       MemberTypes.Method      |
+                       MemberTypes.NestedType  |
+                       MemberTypes.Property;
+               
+               public const BindingFlags AllBindingFlags =
+                       BindingFlags.Public |
+                       BindingFlags.Static |
+                       BindingFlags.Instance;
+
+               public static Expression MemberLookup (Type container_type, Type queried_type,
+                                                      string name, Location loc)
+               {
+                       return MemberLookup (container_type, null, queried_type, name,
+                                            AllMemberTypes, AllBindingFlags, loc);
+               }
+
+               public static Expression MemberLookup (Type container_type, Type qualifier_type,
+                                                      Type queried_type, string name, Location loc)
+               {
+                       return MemberLookup (container_type, qualifier_type, queried_type,
+                                            name, AllMemberTypes, AllBindingFlags, loc);
+               }
+
+               public static Expression MethodLookup (Type container_type, Type queried_type,
+                                                      string name, Location loc)
+               {
+                       return MemberLookup (container_type, null, queried_type, name,
+                                            MemberTypes.Method, AllBindingFlags, loc);
+               }
+
+               /// <summary>
+               ///   This is a wrapper for MemberLookup that is not used to "probe", but
+               ///   to find a final definition.  If the final definition is not found, we
+               ///   look for private members and display a useful debugging message if we
+               ///   find it.
+               /// </summary>
+               public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
+                                                           Type queried_type, string name, Location loc)
+               {
+                       return MemberLookupFinal (ec, qualifier_type, queried_type, name,
+                                                 AllMemberTypes, AllBindingFlags, loc);
+               }
+
+               public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
+                                                           Type queried_type, string name,
+                                                           MemberTypes mt, BindingFlags bf,
+                                                           Location loc)
+               {
+                       Expression e;
+
+                       int errors = Report.Errors;
+
+                       e = MemberLookup (ec.ContainerType, qualifier_type, queried_type, name, mt, bf, loc);
+
+                       if (e == null && errors == Report.Errors)
+                               // No errors were reported by MemberLookup, but there was an error.
+                               MemberLookupFailed (ec.ContainerType, qualifier_type, queried_type, name, null, true, loc);
+
+                       return e;
+               }
+
+               public static void MemberLookupFailed (Type container_type, Type qualifier_type,
+                                                      Type queried_type, string name,
+                                                      string class_name, bool complain_if_none_found, 
+                                                      Location loc)
+               {
+                       if (almostMatchedMembers.Count != 0) {
+                               for (int i = 0; i < almostMatchedMembers.Count; ++i) {
+                                       MemberInfo m = (MemberInfo) almostMatchedMembers [i];
+                                       for (int j = 0; j < i; ++j) {
+                                               if (m == almostMatchedMembers [j]) {
+                                                       m = null;
+                                                       break;
+                                               }
+                                       }
+                                       if (m == null)
+                                               continue;
+                                       
+                                       Type declaring_type = m.DeclaringType;
+                                       
+                                       Report.SymbolRelatedToPreviousError (m);
+                                       if (qualifier_type == null) {
+                                               Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
+                                                             TypeManager.CSharpName (m.DeclaringType),
+                                                             TypeManager.CSharpName (container_type));
+                                               
+                                       } else if (qualifier_type != container_type &&
+                                                  TypeManager.IsNestedFamilyAccessible (container_type, declaring_type)) {
+                                               // Although a derived class can access protected members of
+                                               // its base class it cannot do so through an instance of the
+                                               // base class (CS1540).  If the qualifier_type is a base of the
+                                               // ec.ContainerType and the lookup succeeds with the latter one,
+                                               // then we are in this situation.
+                                               Error_CannotAccessProtected (loc, m, qualifier_type, container_type);
+                                       } else {
+                                               ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (m));
+                                       }
+                               }
+                               almostMatchedMembers.Clear ();
+                               return;
+                       }
+
+                       MemberInfo[] lookup = null;
+                       if (queried_type == null) {
+                               class_name = "global::";
+                       } else {
+                               lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
+                                       AllMemberTypes, AllBindingFlags |
+                                       BindingFlags.NonPublic, name, null);
+                       }
+
+                       if (lookup == null) {
+                               if (!complain_if_none_found)
+                                       return;
+
+                               if (class_name != null)
+                                       Report.Error (103, loc, "The name `{0}' does not exist in the context of `{1}'",
+                                               name, class_name);
+                               else
+                                       Error_TypeDoesNotContainDefinition (loc, queried_type, name);
+                               return;
+                       }
+
+                       if (TypeManager.MemberLookup (queried_type, null, queried_type,
+                                                     AllMemberTypes, AllBindingFlags |
+                                                     BindingFlags.NonPublic, name, null) == null) {
+                               if ((lookup.Length == 1) && (lookup [0] is Type)) {
+                                       Type t = (Type) lookup [0];
+
+                                       Report.Error (305, loc,
+                                                     "Using the generic type `{0}' " +
+                                                     "requires {1} type arguments",
+                                                     TypeManager.CSharpName (t),
+                                                     TypeManager.GetNumberOfTypeArguments (t).ToString ());
+                                       return;
+                               }
+                       }
+
+                       MemberList ml = TypeManager.FindMembers (queried_type, MemberTypes.Constructor,
+                                                                BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly, null, null);
+                       if (name == ".ctor" && ml.Count == 0)
+                       {
+                               Report.Error (143, loc, "The type `{0}' has no constructors defined", TypeManager.CSharpName (queried_type));
+                               return;
+                       }
+
+                       Report.SymbolRelatedToPreviousError (lookup [0]);
+                       ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0]));
+               }
+
+               /// <summary>
+               ///   Returns an expression that can be used to invoke operator true
+               ///   on the expression if it exists.
+               /// </summary>
+               static public Expression GetOperatorTrue (EmitContext ec, Expression e, Location loc)
+               {
+                       return GetOperatorTrueOrFalse (ec, e, true, loc);
+               }
+
+               /// <summary>
+               ///   Returns an expression that can be used to invoke operator false
+               ///   on the expression if it exists.
+               /// </summary>
+               static public Expression GetOperatorFalse (EmitContext ec, Expression e, Location loc)
+               {
+                       return GetOperatorTrueOrFalse (ec, e, false, loc);
+               }
+
+               static Expression GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
+               {
+                       MethodBase method;
+                       Expression operator_group;
+
+#if GMCS_SOURCE
+                       if (TypeManager.IsNullableType (e.Type))
+                               return new Nullable.OperatorTrueOrFalse (e, is_true, loc).Resolve (ec);
+#endif
+
+                       operator_group = MethodLookup (ec.ContainerType, e.Type, is_true ? "op_True" : "op_False", loc);
+                       if (operator_group == null)
+                               return null;
+
+                       ArrayList arguments = new ArrayList ();
+                       arguments.Add (new Argument (e, Argument.AType.Expression));
+                       method = Invocation.OverloadResolve (
+                               ec, (MethodGroupExpr) operator_group, arguments, false, loc);
+
+                       if (method == null)
+                               return null;
+
+                       return new StaticCallExpr ((MethodInfo) method, arguments, loc);
+               }
+
+               /// <summary>
+               ///   Resolves the expression `e' into a boolean expression: either through
+               ///   an implicit conversion, or through an `operator true' invocation
+               /// </summary>
+               public static Expression ResolveBoolean (EmitContext ec, Expression e, Location loc)
+               {
+                       e = e.Resolve (ec);
+                       if (e == null)
+                               return null;
+
+                       if (e.Type == TypeManager.bool_type)
+                               return e;
+
+                       Expression converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, Location.Null);
+
+                       if (converted != null)
+                               return converted;
+
+                       //
+                       // If no implicit conversion to bool exists, try using `operator true'
+                       //
+                       converted = Expression.GetOperatorTrue (ec, e, loc);
+                       if (converted == null){
+                               e.Error_ValueCannotBeConverted (loc, TypeManager.bool_type, false);
+                               return null;
+                       }
+                       return converted;
+               }
+               
+               public virtual string ExprClassName
+               {
+                       get {
+                               switch (eclass){
+                                       case ExprClass.Invalid:
+                                               return "Invalid";
+                                       case ExprClass.Value:
+                                               return "value";
+                                       case ExprClass.Variable:
+                                               return "variable";
+                                       case ExprClass.Namespace:
+                                               return "namespace";
+                                       case ExprClass.Type:
+                                               return "type";
+                                       case ExprClass.MethodGroup:
+                                               return "method group";
+                                       case ExprClass.PropertyAccess:
+                                               return "property access";
+                                       case ExprClass.EventAccess:
+                                               return "event access";
+                                       case ExprClass.IndexerAccess:
+                                               return "indexer access";
+                                       case ExprClass.Nothing:
+                                               return "null";
+                               }
+                               throw new Exception ("Should not happen");
+                       }
+               }
+               
+               /// <summary>
+               ///   Reports that we were expecting `expr' to be of class `expected'
+               /// </summary>
+               public void Error_UnexpectedKind (DeclSpace ds, string expected, Location loc)
+               {
+                       Error_UnexpectedKind (ds, expected, ExprClassName, loc);
+               }
+
+               public void Error_UnexpectedKind (DeclSpace ds, string expected, string was, Location loc)
+               {
+                       string name = GetSignatureForError ();
+                       if (ds != null)
+                               name = ds.GetSignatureForError () + '.' + name;
+
+                       Report.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected",
+                             name, was, expected);
+               }
+
+               public void Error_UnexpectedKind (ResolveFlags flags, Location loc)
+               {
+                       string [] valid = new string [4];
+                       int count = 0;
+
+                       if ((flags & ResolveFlags.VariableOrValue) != 0) {
+                               valid [count++] = "variable";
+                               valid [count++] = "value";
+                       }
+
+                       if ((flags & ResolveFlags.Type) != 0)
+                               valid [count++] = "type";
+
+                       if ((flags & ResolveFlags.MethodGroup) != 0)
+                               valid [count++] = "method group";
+
+                       if (count == 0)
+                               valid [count++] = "unknown";
+
+                       StringBuilder sb = new StringBuilder (valid [0]);
+                       for (int i = 1; i < count - 1; i++) {
+                               sb.Append ("', `");
+                               sb.Append (valid [i]);
+                       }
+                       if (count > 1) {
+                               sb.Append ("' or `");
+                               sb.Append (valid [count - 1]);
+                       }
+
+                       Report.Error (119, loc, 
+                               "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName, sb.ToString ());
+               }
+               
+               public static void UnsafeError (Location loc)
+               {
+                       Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context");
+               }
+
+               //
+               // Load the object from the pointer.  
+               //
+               public static void LoadFromPtr (ILGenerator ig, Type t)
+               {
+                       if (t == TypeManager.int32_type)
+                               ig.Emit (OpCodes.Ldind_I4);
+                       else if (t == TypeManager.uint32_type)
+                               ig.Emit (OpCodes.Ldind_U4);
+                       else if (t == TypeManager.short_type)
+                               ig.Emit (OpCodes.Ldind_I2);
+                       else if (t == TypeManager.ushort_type)
+                               ig.Emit (OpCodes.Ldind_U2);
+                       else if (t == TypeManager.char_type)
+                               ig.Emit (OpCodes.Ldind_U2);
+                       else if (t == TypeManager.byte_type)
+                               ig.Emit (OpCodes.Ldind_U1);
+                       else if (t == TypeManager.sbyte_type)
+                               ig.Emit (OpCodes.Ldind_I1);
+                       else if (t == TypeManager.uint64_type)
+                               ig.Emit (OpCodes.Ldind_I8);
+                       else if (t == TypeManager.int64_type)
+                               ig.Emit (OpCodes.Ldind_I8);
+                       else if (t == TypeManager.float_type)
+                               ig.Emit (OpCodes.Ldind_R4);
+                       else if (t == TypeManager.double_type)
+                               ig.Emit (OpCodes.Ldind_R8);
+                       else if (t == TypeManager.bool_type)
+                               ig.Emit (OpCodes.Ldind_I1);
+                       else if (t == TypeManager.intptr_type)
+                               ig.Emit (OpCodes.Ldind_I);
+                       else if (TypeManager.IsEnumType (t)) {
+                               if (t == TypeManager.enum_type)
+                                       ig.Emit (OpCodes.Ldind_Ref);
+                               else
+                                       LoadFromPtr (ig, TypeManager.EnumToUnderlying (t));
+                       } else if (t.IsValueType || TypeManager.IsGenericParameter (t))
+                               ig.Emit (OpCodes.Ldobj, t);
+                       else if (t.IsPointer)
+                               ig.Emit (OpCodes.Ldind_I);
+                       else
+                               ig.Emit (OpCodes.Ldind_Ref);
+               }
+
+               //
+               // The stack contains the pointer and the value of type `type'
+               //
+               public static void StoreFromPtr (ILGenerator ig, Type type)
+               {
+                       if (TypeManager.IsEnumType (type))
+                               type = TypeManager.EnumToUnderlying (type);
+                       if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
+                               ig.Emit (OpCodes.Stind_I4);
+                       else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
+                               ig.Emit (OpCodes.Stind_I8);
+                       else if (type == TypeManager.char_type || type == TypeManager.short_type ||
+                                type == TypeManager.ushort_type)
+                               ig.Emit (OpCodes.Stind_I2);
+                       else if (type == TypeManager.float_type)
+                               ig.Emit (OpCodes.Stind_R4);
+                       else if (type == TypeManager.double_type)
+                               ig.Emit (OpCodes.Stind_R8);
+                       else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type ||
+                                type == TypeManager.bool_type)
+                               ig.Emit (OpCodes.Stind_I1);
+                       else if (type == TypeManager.intptr_type)
+                               ig.Emit (OpCodes.Stind_I);
+                       else if (type.IsValueType || TypeManager.IsGenericParameter (type))
+                               ig.Emit (OpCodes.Stobj, type);
+                       else
+                               ig.Emit (OpCodes.Stind_Ref);
+               }
+               
+               //
+               // Returns the size of type `t' if known, otherwise, 0
+               //
+               public static int GetTypeSize (Type t)
+               {
+                       t = TypeManager.TypeToCoreType (t);
+                       if (t == TypeManager.int32_type ||
+                           t == TypeManager.uint32_type ||
+                           t == TypeManager.float_type)
+                               return 4;
+                       else if (t == TypeManager.int64_type ||
+                                t == TypeManager.uint64_type ||
+                                t == TypeManager.double_type)
+                               return 8;
+                       else if (t == TypeManager.byte_type ||
+                                t == TypeManager.sbyte_type ||
+                                t == TypeManager.bool_type)    
+                               return 1;
+                       else if (t == TypeManager.short_type ||
+                                t == TypeManager.char_type ||
+                                t == TypeManager.ushort_type)
+                               return 2;
+                       else if (t == TypeManager.decimal_type)
+                               return 16;
+                       else
+                               return 0;
+               }
+
+               public static void Error_NegativeArrayIndex (Location loc)
+               {
+                       Report.Error (248, loc, "Cannot create an array with a negative size");
+               }
+
+               protected void Error_CannotCallAbstractBase (string name)
+               {
+                       Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
+               }
+               
+               //
+               // Converts `source' to an int, uint, long or ulong.
+               //
+               public Expression ExpressionToArrayArgument (EmitContext ec, Expression source, Location loc)
+               {
+                       Expression target;
+                       
+                       using (ec.With (EmitContext.Flags.CheckState, true)) {
+                               target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc);
+                               if (target == null)
+                                       target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc);
+                               if (target == null)
+                                       target = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, loc);
+                               if (target == null)
+                                       target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc);
+
+                               if (target == null) {
+                                       source.Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false);
+                                       return null;
+                               }
+                       }
+
+                       //
+                       // Only positive constants are allowed at compile time
+                       //
+                       if (target is Constant){
+                               if (target is IntConstant){
+                                       if (((IntConstant) target).Value < 0){
+                                               Error_NegativeArrayIndex (loc);
+                                               return null;
+                                       }
+                               }
+
+                               if (target is LongConstant){
+                                       if (((LongConstant) target).Value < 0){
+                                               Error_NegativeArrayIndex (loc);
+                                               return null;
+                                       }
+                               }
+                               
+                       }
+
+                       return target;
+               }
+               
+       }
+
+       /// <summary>
+       ///   This is just a base class for expressions that can
+       ///   appear on statements (invocations, object creation,
+       ///   assignments, post/pre increment and decrement).  The idea
+       ///   being that they would support an extra Emition interface that
+       ///   does not leave a result on the stack.
+       /// </summary>
+       public abstract class ExpressionStatement : Expression {
+
+               public virtual ExpressionStatement ResolveStatement (EmitContext ec)
+               {
+                       Expression e = Resolve (ec);
+                       if (e == null)
+                               return null;
+
+                       ExpressionStatement es = e as ExpressionStatement;
+                       if (es == null)
+                               Error (201, "Only assignment, call, increment, decrement and new object " +
+                                      "expressions can be used as a statement");
+
+                       return es;
+               }
+
+               /// <summary>
+               ///   Requests the expression to be emitted in a `statement'
+               ///   context.  This means that no new value is left on the
+               ///   stack after invoking this method (constrasted with
+               ///   Emit that will always leave a value on the stack).
+               /// </summary>
+               public abstract void EmitStatement (EmitContext ec);
+       }
+
+       /// <summary>
+       ///   This kind of cast is used to encapsulate the child
+       ///   whose type is child.Type into an expression that is
+       ///   reported to return "return_type".  This is used to encapsulate
+       ///   expressions which have compatible types, but need to be dealt
+       ///   at higher levels with.
+       ///
+       ///   For example, a "byte" expression could be encapsulated in one
+       ///   of these as an "unsigned int".  The type for the expression
+       ///   would be "unsigned int".
+       ///
+       /// </summary>
+       public class EmptyCast : Expression {
+               protected readonly Expression child;
+
+               public EmptyCast (Expression child, Type return_type)
+               {
+                       eclass = child.eclass;
+                       loc = child.Location;
+                       type = return_type;
+                       this.child = child;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       child.Emit (ec);
+               }
+
+               public override bool GetAttributableValue (Type valueType, out object value)
+               {
+                       return child.GetAttributableValue (valueType, out value);
+               }
+
+       }
+
+       /// <summary>
+       ///    Performs a cast using an operator (op_Explicit or op_Implicit)
+       /// </summary>
+       public class OperatorCast : EmptyCast {
+               MethodInfo conversion_operator;
+               bool find_explicit;
+                       
+               public OperatorCast (Expression child, Type target_type) : this (child, target_type, false) {}
+
+               public OperatorCast (Expression child, Type target_type, bool find_explicit)
+                       : base (child, target_type)
+               {
+                       this.find_explicit = find_explicit;
+               }
+
+               // Returns the implicit operator that converts from
+               // 'child.Type' to our target type (type)
+               MethodInfo GetConversionOperator (bool find_explicit)
+               {
+                       string operator_name = find_explicit ? "op_Explicit" : "op_Implicit";
+
+                       MemberInfo [] mi;
+
+                       mi = TypeManager.MemberLookup (child.Type, child.Type, child.Type, MemberTypes.Method,
+                               BindingFlags.Static | BindingFlags.Public, operator_name, null);
+
+                       if (mi == null){
+                               mi = TypeManager.MemberLookup (type, type, type, MemberTypes.Method,
+                                                              BindingFlags.Static | BindingFlags.Public, operator_name, null);
+                       }
+                       
+                       foreach (MethodInfo oper in mi) {
+                               ParameterData pd = TypeManager.GetParameterData (oper);
+
+                               if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
+                                       return oper;
+                       }
+
+                       return null;
+
+
+               }
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       child.Emit (ec);
+                       conversion_operator = GetConversionOperator (find_explicit);
+
+                       if (conversion_operator == null)
+                               throw new InternalErrorException ("Outer conversion routine is out of sync");
+
+                       ig.Emit (OpCodes.Call, conversion_operator);
+               }
+               
+       }
+       
+       /// <summary>
+       ///     This is a numeric cast to a Decimal
+       /// </summary>
+       public class CastToDecimal : EmptyCast {
+               MethodInfo conversion_operator;
+
+               public CastToDecimal (Expression child)
+                       : this (child, false)
+               {
+               }
+
+               public CastToDecimal (Expression child, bool find_explicit)
+                       : base (child, TypeManager.decimal_type)
+               {
+                       conversion_operator = GetConversionOperator (find_explicit);
+
+                       if (conversion_operator == null)
+                               throw new InternalErrorException ("Outer conversion routine is out of sync");
+               }
+
+               // Returns the implicit operator that converts from
+               // 'child.Type' to System.Decimal.
+               MethodInfo GetConversionOperator (bool find_explicit)
+               {
+                       string operator_name = find_explicit ? "op_Explicit" : "op_Implicit";
+                       
+                       MemberInfo [] mi = TypeManager.MemberLookup (type, type, type, MemberTypes.Method,
+                               BindingFlags.Static | BindingFlags.Public, operator_name, null);
+
+                       foreach (MethodInfo oper in mi) {
+                               ParameterData pd = TypeManager.GetParameterData (oper);
+
+                               if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
+                                       return oper;
+                       }
+
+                       return null;
+               }
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       child.Emit (ec);
+
+                       ig.Emit (OpCodes.Call, conversion_operator);
+               }
+       }
+
+       /// <summary>
+       ///     This is an explicit numeric cast from a Decimal
+       /// </summary>
+       public class CastFromDecimal : EmptyCast
+       {
+               static IDictionary operators;
+
+               public CastFromDecimal (Expression child, Type return_type)
+                       : base (child, return_type)
+               {
+                       if (child.Type != TypeManager.decimal_type)
+                               throw new InternalErrorException (
+                                       "The expected type is Decimal, instead it is " + child.Type.FullName);
+               }
+
+               // Returns the explicit operator that converts from an
+               // express of type System.Decimal to 'type'.
+               public Expression Resolve ()
+               {
+                       if (operators == null) {
+                                MemberInfo[] all_oper = TypeManager.MemberLookup (TypeManager.decimal_type,
+                                       TypeManager.decimal_type, TypeManager.decimal_type, MemberTypes.Method,
+                                       BindingFlags.Static | BindingFlags.Public, "op_Explicit", null);
+
+                               operators = new System.Collections.Specialized.HybridDictionary ();
+                               foreach (MethodInfo oper in all_oper) {
+                                       ParameterData pd = TypeManager.GetParameterData (oper);
+                                       if (pd.ParameterType (0) == TypeManager.decimal_type)
+                                               operators.Add (oper.ReturnType, oper);
+                               }
+                       }
+
+                       return operators.Contains (type) ? this : null;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       child.Emit (ec);
+
+                       ig.Emit (OpCodes.Call, (MethodInfo)operators [type]);
+               }
+       }
+
+       
+       //
+       // Constant specialization of EmptyCast.
+       // We need to special case this since an empty cast of
+       // a constant is still a constant. 
+       //
+       public class EmptyConstantCast : Constant
+       {
+               public readonly Constant child;
+
+               public EmptyConstantCast(Constant child, Type type)
+                       : base (child.Location)
+               {
+                       eclass = child.eclass;
+                       this.child = child;
+                       this.type = type;
+               }
+
+               public override string AsString ()
+               {
+                       return child.AsString ();
+               }
+
+               public override object GetValue ()
+               {
+                       return child.GetValue ();
+               }
+
+               public override Constant Reduce (bool inCheckedContext, Type target_type)
+               {
+                       return child.Reduce (inCheckedContext, target_type);
+               }
+
+               public override Constant Increment ()
+               {
+                       return child.Increment ();
+               }
+
+               public override bool IsDefaultValue
+               {
+                       get { return child.IsDefaultValue; }
+               }
+
+               public override bool IsNegative
+               {
+                       get { return child.IsNegative; }
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       child.Emit (ec);
+               }
+
+               public override Constant ToType (Type type)
+               {
+                       return child.ToType (type);
+               }
+       }
+
+
+       /// <summary>
+       ///  This class is used to wrap literals which belong inside Enums
+       /// </summary>
+       public class EnumConstant : Constant {
+               public Constant Child;
+
+               public EnumConstant (Constant child, Type enum_type):
+                       base (child.Location)
+               {
+                       eclass = child.eclass;
+                       this.Child = child;
+                       type = enum_type;
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       Child.Emit (ec);
+               }
+
+               public override bool GetAttributableValue (Type valueType, out object value)
+               {
+                       value = GetTypedValue ();
+                       return true;
+               }
+
+               public override string GetSignatureForError()
+               {
+                       return TypeManager.CSharpName (Type);
+               }
+
+               public override object GetValue ()
+               {
+                       return Child.GetValue ();
+               }
+
+               public override object GetTypedValue ()
+               {
+                       // FIXME: runtime is not ready to work with just emited enums
+                       if (!RootContext.StdLib) {
+                               return Child.GetValue ();
+                       }
+
+                       return System.Enum.ToObject (type, Child.GetValue ());
+               }
+               
+               public override string AsString ()
+               {
+                       return Child.AsString ();
+               }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return Child.ConvertToDouble ();
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return Child.ConvertToFloat ();
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       return Child.ConvertToULong ();
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return Child.ConvertToLong ();
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return Child.ConvertToUInt ();
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return Child.ConvertToInt ();
+               }
+
+               public override Constant Increment()
+               {
+                       return new EnumConstant (Child.Increment (), type);
+               }
+
+               public override bool IsDefaultValue {
+                       get {
+                               return Child.IsDefaultValue;
+                       }
+               }
+
+               public override bool IsZeroInteger {
+                       get { return Child.IsZeroInteger; }
+               }
+
+               public override bool IsNegative {
+                       get {
+                               return Child.IsNegative;
+                       }
+               }
+
+               public override Constant Reduce(bool inCheckedContext, Type target_type)
+               {
+                       if (Child.Type == target_type)
+                               return Child;
+
+                       return Child.Reduce (inCheckedContext, target_type);
+               }
+
+               public override Constant ToType (Type type)
+               {
+                       if (Type == type) {
+                               // This is workaround of mono bug. It can be removed when the latest corlib spreads enough
+                               if (TypeManager.IsEnumType (type.UnderlyingSystemType))
+                                       return this;
+
+                               if (type.UnderlyingSystemType != Child.Type)
+                                       Child = Child.ToType (type.UnderlyingSystemType);
+                               return this;
+                       }
+
+                       if (!Convert.ImplicitStandardConversionExists (this, type)){
+                               return null;
+                       }
+
+                       return Child.ToType (type);
+               }
+
+       }
+
+       /// <summary>
+       ///   This kind of cast is used to encapsulate Value Types in objects.
+       ///
+       ///   The effect of it is to box the value type emitted by the previous
+       ///   operation.
+       /// </summary>
+       public class BoxedCast : EmptyCast {
+
+               public BoxedCast (Expression expr, Type target_type)
+                       : base (expr, target_type)
+               {
+                       eclass = ExprClass.Value;
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       base.Emit (ec);
+                       
+                       ec.ig.Emit (OpCodes.Box, child.Type);
+               }
+       }
+
+       public class UnboxCast : EmptyCast {
+               public UnboxCast (Expression expr, Type return_type)
+                       : base (expr, return_type)
+               {
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess)
+                               Report.Error (445, loc, "Cannot modify the result of an unboxing conversion");
+                       return base.DoResolveLValue (ec, right_side);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       Type t = type;
+                       ILGenerator ig = ec.ig;
+                       
+                       base.Emit (ec);
+#if GMCS_SOURCE
+                       if (t.IsGenericParameter || t.IsGenericType && t.IsValueType)
+                               ig.Emit (OpCodes.Unbox_Any, t);
+                       else
+#endif
+                       {
+                               ig.Emit (OpCodes.Unbox, t);
+
+                               LoadFromPtr (ig, t);
+                       }
+               }
+       }
+       
+       /// <summary>
+       ///   This is used to perform explicit numeric conversions.
+       ///
+       ///   Explicit numeric conversions might trigger exceptions in a checked
+       ///   context, so they should generate the conv.ovf opcodes instead of
+       ///   conv opcodes.
+       /// </summary>
+       public class ConvCast : EmptyCast {
+               public enum Mode : byte {
+                       I1_U1, I1_U2, I1_U4, I1_U8, I1_CH,
+                       U1_I1, U1_CH,
+                       I2_I1, I2_U1, I2_U2, I2_U4, I2_U8, I2_CH,
+                       U2_I1, U2_U1, U2_I2, U2_CH,
+                       I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH,
+                       U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH,
+                       I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH,
+                       U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH,
+                       CH_I1, CH_U1, CH_I2,
+                       R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH,
+                       R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4
+               }
+
+               Mode mode;
+               
+               public ConvCast (Expression child, Type return_type, Mode m)
+                       : base (child, return_type)
+               {
+                       mode = m;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override string ToString ()
+               {
+                       return String.Format ("ConvCast ({0}, {1})", mode, child);
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       base.Emit (ec);
+
+                       if (ec.CheckState){
+                               switch (mode){
+                               case Mode.I1_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
+                               case Mode.I1_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+                               case Mode.I1_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
+                               case Mode.I1_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
+                               case Mode.I1_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+
+                               case Mode.U1_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
+                               case Mode.U1_CH: /* nothing */ break;
+
+                               case Mode.I2_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
+                               case Mode.I2_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
+                               case Mode.I2_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+                               case Mode.I2_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
+                               case Mode.I2_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
+                               case Mode.I2_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+
+                               case Mode.U2_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
+                               case Mode.U2_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
+                               case Mode.U2_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
+                               case Mode.U2_CH: /* nothing */ break;
+
+                               case Mode.I4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
+                               case Mode.I4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
+                               case Mode.I4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
+                               case Mode.I4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
+                               case Mode.I4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+                               case Mode.I4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
+                               case Mode.I4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+
+                               case Mode.U4_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
+                               case Mode.U4_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
+                               case Mode.U4_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
+                               case Mode.U4_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
+                               case Mode.U4_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
+                               case Mode.U4_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
+
+                               case Mode.I8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
+                               case Mode.I8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
+                               case Mode.I8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
+                               case Mode.I8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+                               case Mode.I8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
+                               case Mode.I8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
+                               case Mode.I8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
+                               case Mode.I8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+
+                               case Mode.U8_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
+                               case Mode.U8_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
+                               case Mode.U8_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
+                               case Mode.U8_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
+                               case Mode.U8_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
+                               case Mode.U8_U4: ig.Emit (OpCodes.Conv_Ovf_U4_Un); break;
+                               case Mode.U8_I8: ig.Emit (OpCodes.Conv_Ovf_I8_Un); break;
+                               case Mode.U8_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
+
+                               case Mode.CH_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
+                               case Mode.CH_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
+                               case Mode.CH_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
+
+                               case Mode.R4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
+                               case Mode.R4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
+                               case Mode.R4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
+                               case Mode.R4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+                               case Mode.R4_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
+                               case Mode.R4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
+                               case Mode.R4_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
+                               case Mode.R4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
+                               case Mode.R4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+
+                               case Mode.R8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
+                               case Mode.R8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
+                               case Mode.R8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
+                               case Mode.R8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+                               case Mode.R8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
+                               case Mode.R8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
+                               case Mode.R8_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
+                               case Mode.R8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
+                               case Mode.R8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+                               case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
+                               }
+                       } else {
+                               switch (mode){
+                               case Mode.I1_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.I1_U2: ig.Emit (OpCodes.Conv_U2); break;
+                               case Mode.I1_U4: ig.Emit (OpCodes.Conv_U4); break;
+                               case Mode.I1_U8: ig.Emit (OpCodes.Conv_I8); break;
+                               case Mode.I1_CH: ig.Emit (OpCodes.Conv_U2); break;
+
+                               case Mode.U1_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.U1_CH: ig.Emit (OpCodes.Conv_U2); break;
+
+                               case Mode.I2_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.I2_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.I2_U2: ig.Emit (OpCodes.Conv_U2); break;
+                               case Mode.I2_U4: ig.Emit (OpCodes.Conv_U4); break;
+                               case Mode.I2_U8: ig.Emit (OpCodes.Conv_I8); break;
+                               case Mode.I2_CH: ig.Emit (OpCodes.Conv_U2); break;
+
+                               case Mode.U2_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.U2_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.U2_I2: ig.Emit (OpCodes.Conv_I2); break;
+                               case Mode.U2_CH: /* nothing */ break;
+
+                               case Mode.I4_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.I4_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.I4_I2: ig.Emit (OpCodes.Conv_I2); break;
+                               case Mode.I4_U4: /* nothing */ break;
+                               case Mode.I4_U2: ig.Emit (OpCodes.Conv_U2); break;
+                               case Mode.I4_U8: ig.Emit (OpCodes.Conv_I8); break;
+                               case Mode.I4_CH: ig.Emit (OpCodes.Conv_U2); break;
+
+                               case Mode.U4_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.U4_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.U4_I2: ig.Emit (OpCodes.Conv_I2); break;
+                               case Mode.U4_U2: ig.Emit (OpCodes.Conv_U2); break;
+                               case Mode.U4_I4: /* nothing */ break;
+                               case Mode.U4_CH: ig.Emit (OpCodes.Conv_U2); break;
+
+                               case Mode.I8_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.I8_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.I8_I2: ig.Emit (OpCodes.Conv_I2); break;
+                               case Mode.I8_U2: ig.Emit (OpCodes.Conv_U2); break;
+                               case Mode.I8_I4: ig.Emit (OpCodes.Conv_I4); break;
+                               case Mode.I8_U4: ig.Emit (OpCodes.Conv_U4); break;
+                               case Mode.I8_U8: /* nothing */ break;
+                               case Mode.I8_CH: ig.Emit (OpCodes.Conv_U2); break;
+
+                               case Mode.U8_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.U8_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.U8_I2: ig.Emit (OpCodes.Conv_I2); break;
+                               case Mode.U8_U2: ig.Emit (OpCodes.Conv_U2); break;
+                               case Mode.U8_I4: ig.Emit (OpCodes.Conv_I4); break;
+                               case Mode.U8_U4: ig.Emit (OpCodes.Conv_U4); break;
+                               case Mode.U8_I8: /* nothing */ break;
+                               case Mode.U8_CH: ig.Emit (OpCodes.Conv_U2); break;
+
+                               case Mode.CH_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.CH_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.CH_I2: ig.Emit (OpCodes.Conv_I2); break;
+
+                               case Mode.R4_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.R4_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.R4_I2: ig.Emit (OpCodes.Conv_I2); break;
+                               case Mode.R4_U2: ig.Emit (OpCodes.Conv_U2); break;
+                               case Mode.R4_I4: ig.Emit (OpCodes.Conv_I4); break;
+                               case Mode.R4_U4: ig.Emit (OpCodes.Conv_U4); break;
+                               case Mode.R4_I8: ig.Emit (OpCodes.Conv_I8); break;
+                               case Mode.R4_U8: ig.Emit (OpCodes.Conv_U8); break;
+                               case Mode.R4_CH: ig.Emit (OpCodes.Conv_U2); break;
+
+                               case Mode.R8_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.R8_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.R8_I2: ig.Emit (OpCodes.Conv_I2); break;
+                               case Mode.R8_U2: ig.Emit (OpCodes.Conv_U2); break;
+                               case Mode.R8_I4: ig.Emit (OpCodes.Conv_I4); break;
+                               case Mode.R8_U4: ig.Emit (OpCodes.Conv_U4); break;
+                               case Mode.R8_I8: ig.Emit (OpCodes.Conv_I8); break;
+                               case Mode.R8_U8: ig.Emit (OpCodes.Conv_U8); break;
+                               case Mode.R8_CH: ig.Emit (OpCodes.Conv_U2); break;
+                               case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
+                               }
+                       }
+               }
+       }
+       
+       public class OpcodeCast : EmptyCast {
+               OpCode op, op2;
+               bool second_valid;
+               
+               public OpcodeCast (Expression child, Type return_type, OpCode op)
+                       : base (child, return_type)
+                       
+               {
+                       this.op = op;
+                       second_valid = false;
+               }
+
+               public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
+                       : base (child, return_type)
+                       
+               {
+                       this.op = op;
+                       this.op2 = op2;
+                       second_valid = true;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       base.Emit (ec);
+                       ec.ig.Emit (op);
+
+                       if (second_valid)
+                               ec.ig.Emit (op2);
+               }                       
+       }
+
+       /// <summary>
+       ///   This kind of cast is used to encapsulate a child and cast it
+       ///   to the class requested
+       /// </summary>
+       public class ClassCast : EmptyCast {
+               public ClassCast (Expression child, Type return_type)
+                       : base (child, return_type)
+                       
+               {
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       base.Emit (ec);
+
+                       if (TypeManager.IsGenericParameter (child.Type))
+                               ec.ig.Emit (OpCodes.Box, child.Type);
+
+#if GMCS_SOURCE
+                       if (type.IsGenericParameter)
+                               ec.ig.Emit (OpCodes.Unbox_Any, type);
+                       else
+#endif
+                               ec.ig.Emit (OpCodes.Castclass, type);
+               }
+       }
+       
+       /// <summary>
+       ///   SimpleName expressions are formed of a single word and only happen at the beginning 
+       ///   of a dotted-name.
+       /// </summary>
+       public class SimpleName : Expression {
+               public string Name;
+               public readonly TypeArguments Arguments;
+               bool in_transit;
+
+               public SimpleName (string name, Location l)
+               {
+                       Name = name;
+                       loc = l;
+               }
+
+               public SimpleName (string name, TypeArguments args, Location l)
+               {
+                       Name = name;
+                       Arguments = args;
+                       loc = l;
+               }
+
+               public SimpleName (string name, TypeParameter[] type_params, Location l)
+               {
+                       Name = name;
+                       loc = l;
+
+                       Arguments = new TypeArguments (l);
+                       foreach (TypeParameter type_param in type_params)
+                               Arguments.Add (new TypeParameterExpr (type_param, l));
+               }
+
+               public static string RemoveGenericArity (string name)
+               {
+                       int start = 0;
+                       StringBuilder sb = new StringBuilder ();
+                       while (start < name.Length) {
+                               int pos = name.IndexOf ('`', start);
+                               if (pos < 0) {
+                                       sb.Append (name.Substring (start));
+                                       break;
+                               }
+
+                               sb.Append (name.Substring (start, pos-start));
+
+                               pos++;
+                               while ((pos < name.Length) && Char.IsNumber (name [pos]))
+                                       pos++;
+
+                               start = pos;
+                       }
+
+                       return sb.ToString ();
+               }
+
+               public SimpleName GetMethodGroup ()
+               {
+                       return new SimpleName (RemoveGenericArity (Name), Arguments, loc);
+               }
+
+               public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
+               {
+                       if (ec.IsFieldInitializer)
+                               Report.Error (236, l,
+                                       "A field initializer cannot reference the nonstatic field, method, or property `{0}'",
+                                       name);
+                       else
+                               Report.Error (
+                                       120, l, "`{0}': An object reference is required for the nonstatic field, method or property",
+                                       name);
+               }
+
+               public bool IdenticalNameAndTypeName (EmitContext ec, Expression resolved_to, Location loc)
+               {
+                       return resolved_to != null && resolved_to.Type != null && 
+                               resolved_to.Type.Name == Name &&
+                               (ec.DeclContainer.LookupType (Name, loc, /* ignore_cs0104 = */ true) != null);
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return SimpleNameResolve (ec, null, false);
+               }
+
+               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       return SimpleNameResolve (ec, right_side, false);
+               }
+               
+
+               public Expression DoResolve (EmitContext ec, bool intermediate)
+               {
+                       return SimpleNameResolve (ec, null, intermediate);
+               }
+
+               private bool IsNestedChild (Type t, Type parent)
+               {
+                       if (parent == null)
+                               return false;
+
+                       while (parent != null) {
+                               parent = TypeManager.DropGenericTypeArguments (parent);
+                               if (TypeManager.IsNestedChildOf (t, parent))
+                                       return true;
+
+                               parent = parent.BaseType;
+                       }
+
+                       return false;
+               }
+
+               FullNamedExpression ResolveNested (IResolveContext ec, Type t)
+               {
+                       if (!TypeManager.IsGenericTypeDefinition (t))
+                               return null;
+
+                       DeclSpace ds = ec.DeclContainer;
+                       while (ds != null) {
+                               if (IsNestedChild (t, ds.TypeBuilder))
+                                       break;
+
+                               ds = ds.Parent;
+                       }
+
+                       if (ds == null)
+                               return null;
+
+                       Type[] gen_params = TypeManager.GetTypeArguments (t);
+
+                       int arg_count = Arguments != null ? Arguments.Count : 0;
+
+                       for (; (ds != null) && ds.IsGeneric; ds = ds.Parent) {
+                               if (arg_count + ds.CountTypeParameters == gen_params.Length) {
+                                       TypeArguments new_args = new TypeArguments (loc);
+                                       foreach (TypeParameter param in ds.TypeParameters)
+                                               new_args.Add (new TypeParameterExpr (param, loc));
+
+                                       if (Arguments != null)
+                                               new_args.Add (Arguments);
+
+                                       return new ConstructedType (t, new_args, loc);
+                               }
+                       }
+
+                       return null;
+               }
+
+               public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
+               {
+                       FullNamedExpression fne = ec.GenericDeclContainer.LookupGeneric (Name, loc);
+                       if (fne != null)
+                               return fne.ResolveAsTypeStep (ec, silent);
+
+                       int errors = Report.Errors;
+                       fne = ec.DeclContainer.LookupType (Name, loc, /*ignore_cs0104=*/ false);
+
+                       if (fne != null) {
+                               if (fne.Type == null)
+                                       return fne;
+
+                               FullNamedExpression nested = ResolveNested (ec, fne.Type);
+                               if (nested != null)
+                                       return nested.ResolveAsTypeStep (ec, false);
+
+                               if (Arguments != null) {
+                                       ConstructedType ct = new ConstructedType (fne, Arguments, loc);
+                                       return ct.ResolveAsTypeStep (ec, false);
+                               }
+
+                               return fne;
+                       }
+
+                       if (silent || errors != Report.Errors)
+                               return null;
+
+                       MemberCore mc = ec.DeclContainer.GetDefinition (Name);
+                       if (mc != null) {
+                               Error_UnexpectedKind (ec.DeclContainer, "type", GetMemberType (mc), loc);
+                               return null;
+                       }
+
+                       string ns = ec.DeclContainer.NamespaceEntry.NS.Name;
+                       string fullname = (ns.Length > 0) ? ns + "." + Name : Name;
+                       foreach (Assembly a in RootNamespace.Global.Assemblies) {
+                               Type type = a.GetType (fullname);
+                               if (type != null) {
+                                       Report.SymbolRelatedToPreviousError (type);
+                                       Expression.ErrorIsInaccesible (loc, fullname);
+                                       return null;
+                               }
+                       }
+
+                       Type t = ec.DeclContainer.NamespaceEntry.NS.LookForAnyGenericType (Name);
+                       if (t != null) {
+                               Namespace.Error_InvalidNumberOfTypeArguments (t, loc);
+                               return null;
+                       }
+
+                       NamespaceEntry.Error_NamespaceNotFound (loc, Name);
+                       return null;
+               }
+
+               // TODO: I am still not convinced about this. If someone else will need it
+               // implement this as virtual property in MemberCore hierarchy
+               string GetMemberType (MemberCore mc)
+               {
+                       if (mc is PropertyBase)
+                               return "property";
+                       if (mc is Indexer)
+                               return "indexer";
+                       if (mc is FieldBase)
+                               return "field";
+                       if (mc is MethodCore)
+                               return "method";
+                       if (mc is EnumMember)
+                               return "enum";
+
+                       return "type";
+               }
+
+               Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
+               {
+                       if (in_transit)
+                               return null;
+                       in_transit = true;
+
+                       Expression e = DoSimpleNameResolve (ec, right_side, intermediate);
+                       if (e == null)
+                               return null;
+
+                       if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
+                               return e;
+
+                       return null;
+               }
+
+               /// <remarks>
+               ///   7.5.2: Simple Names. 
+               ///
+               ///   Local Variables and Parameters are handled at
+               ///   parse time, so they never occur as SimpleNames.
+               ///
+               ///   The `intermediate' flag is used by MemberAccess only
+               ///   and it is used to inform us that it is ok for us to 
+               ///   avoid the static check, because MemberAccess might end
+               ///   up resolving the Name as a Type name and the access as
+               ///   a static type access.
+               ///
+               ///   ie: Type Type; .... { Type.GetType (""); }
+               ///
+               ///   Type is both an instance variable and a Type;  Type.GetType
+               ///   is the static method not an instance method of type.
+               /// </remarks>
+               Expression DoSimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
+               {
+                       Expression e = null;
+
+                       //
+                       // Stage 1: Performed by the parser (binding to locals or parameters).
+                       //
+                       Block current_block = ec.CurrentBlock;
+                       if (current_block != null){
+                               LocalInfo vi = current_block.GetLocalInfo (Name);
+                               if (vi != null){
+                                       if (Arguments != null) {
+                                               Report.Error (307, loc,
+                                                             "The variable `{0}' cannot be used with type arguments",
+                                                             Name);
+                                               return null;
+                                       }
+
+                                       LocalVariableReference var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
+                                       if (right_side != null) {
+                                               return var.ResolveLValue (ec, right_side, loc);
+                                       } else {
+                                               ResolveFlags rf = ResolveFlags.VariableOrValue;
+                                               if (intermediate)
+                                                       rf |= ResolveFlags.DisableFlowAnalysis;
+                                               return var.Resolve (ec, rf);
+                                       }
+                               }
+
+                               ParameterReference pref = current_block.Toplevel.GetParameterReference (Name, loc);
+                               if (pref != null) {
+                                       if (Arguments != null) {
+                                               Report.Error (307, loc,
+                                                             "The variable `{0}' cannot be used with type arguments",
+                                                             Name);
+                                               return null;
+                                       }
+
+                                       if (right_side != null)
+                                               return pref.ResolveLValue (ec, right_side, loc);
+                                       else
+                                               return pref.Resolve (ec);
+                               }
+                       }
+                       
+                       //
+                       // Stage 2: Lookup members 
+                       //
+
+                       DeclSpace lookup_ds = ec.DeclContainer;
+                       Type almost_matched_type = null;
+                       ArrayList almost_matched = null;
+                       do {
+                               if (lookup_ds.TypeBuilder == null)
+                                       break;
+
+                               e = MemberLookup (ec.ContainerType, lookup_ds.TypeBuilder, Name, loc);
+                               if (e != null)
+                                       break;
+
+                               if (almost_matched == null && almostMatchedMembers.Count > 0) {
+                                       almost_matched_type = lookup_ds.TypeBuilder;
+                                       almost_matched = (ArrayList) almostMatchedMembers.Clone ();
+                               }
+
+                               lookup_ds =lookup_ds.Parent;
+                       } while (lookup_ds != null);
+
+                       if (e == null && ec.ContainerType != null)
+                               e = MemberLookup (ec.ContainerType, ec.ContainerType, Name, loc);
+
+                       if (e == null) {
+                               if (almost_matched == null && almostMatchedMembers.Count > 0) {
+                                       almost_matched_type = ec.ContainerType;
+                                       almost_matched = (ArrayList) almostMatchedMembers.Clone ();
+                               }
+                               e = ResolveAsTypeStep (ec, true);
+                       }
+
+                       if (e == null) {
+                               if (almost_matched != null)
+                                       almostMatchedMembers = almost_matched;
+                               if (almost_matched_type == null)
+                                       almost_matched_type = ec.ContainerType;
+                               MemberLookupFailed (ec.ContainerType, null, almost_matched_type, ((SimpleName) this).Name, ec.DeclContainer.Name, true, loc);
+                               return null;
+                       }
+
+                       if (e is TypeExpr) {
+                               if (Arguments == null)
+                                       return e;
+
+                               ConstructedType ct = new ConstructedType (
+                                       (FullNamedExpression) e, Arguments, loc);
+                               return ct.ResolveAsTypeStep (ec, false);
+                       }
+
+                       if (e is MemberExpr) {
+                               MemberExpr me = (MemberExpr) e;
+
+                               Expression left;
+                               if (me.IsInstance) {
+                                       if (ec.IsStatic || ec.IsFieldInitializer) {
+                                               //
+                                               // Note that an MemberExpr can be both IsInstance and IsStatic.
+                                               // An unresolved MethodGroupExpr can contain both kinds of methods
+                                               // and each predicate is true if the MethodGroupExpr contains
+                                               // at least one of that kind of method.
+                                               //
+
+                                               if (!me.IsStatic &&
+                                                   (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) {
+                                                       Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ());
+                                                       return EmptyExpression.Null;
+                                               }
+
+                                               //
+                                               // Pass the buck to MemberAccess and Invocation.
+                                               //
+                                               left = EmptyExpression.Null;
+                                       } else {
+                                               left = ec.GetThis (loc);
+                                       }
+                               } else {
+                                       left = new TypeExpression (ec.ContainerType, loc);
+                               }
+
+                               e = me.ResolveMemberAccess (ec, left, loc, null);
+                               if (e == null)
+                                       return null;
+
+                               me = e as MemberExpr;
+                               if (me == null)
+                                       return e;
+
+                               if (Arguments != null) {
+                                       MethodGroupExpr mg = me as MethodGroupExpr;
+                                       if (mg == null)
+                                               return null;
+
+                                       return mg.ResolveGeneric (ec, Arguments);
+                               }
+
+                               if (!me.IsStatic && (me.InstanceExpression != null) &&
+                                   TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
+                                   me.InstanceExpression.Type != me.DeclaringType &&
+                                   !TypeManager.IsFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
+                                   (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) {
+                                       Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
+                                               TypeManager.CSharpName (me.DeclaringType), TypeManager.CSharpName (me.InstanceExpression.Type));
+                                       return null;
+                               }
+
+                               return (right_side != null)
+                                       ? me.DoResolveLValue (ec, right_side)
+                                       : me.DoResolve (ec);
+                       }
+
+                       return e;
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       //
+                       // If this is ever reached, then we failed to
+                       // find the name as a namespace
+                       //
+
+                       Error (103, "The name `" + Name +
+                              "' does not exist in the class `" +
+                              ec.DeclContainer.Name + "'");
+               }
+
+               public override string ToString ()
+               {
+                       return Name;
+               }
+
+               public override string GetSignatureForError ()
+               {
+                       return Name;
+               }
+       }
+
+       /// <summary>
+       ///   Represents a namespace or a type.  The name of the class was inspired by
+       ///   section 10.8.1 (Fully Qualified Names).
+       /// </summary>
+       public abstract class FullNamedExpression : Expression {
+               public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
+               {
+                       return this;
+               }
+
+               public abstract string FullName {
+                       get;
+               }
+       }
+       
+       /// <summary>
+       ///   Expression that evaluates to a type
+       /// </summary>
+       public abstract class TypeExpr : FullNamedExpression {
+               override public FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
+               {
+                       TypeExpr t = DoResolveAsTypeStep (ec);
+                       if (t == null)
+                               return null;
+
+                       eclass = ExprClass.Type;
+                       return t;
+               }
+
+               override public Expression DoResolve (EmitContext ec)
+               {
+                       return ResolveAsTypeTerminal (ec, false);
+               }
+
+               override public void Emit (EmitContext ec)
+               {
+                       throw new Exception ("Should never be called");
+               }
+
+               public virtual bool CheckAccessLevel (DeclSpace ds)
+               {
+                       return ds.CheckAccessLevel (Type);
+               }
+
+               public virtual bool AsAccessible (DeclSpace ds, int flags)
+               {
+                       return ds.AsAccessible (Type, flags);
+               }
+
+               public virtual bool IsClass {
+                       get { return Type.IsClass; }
+               }
+
+               public virtual bool IsValueType {
+                       get { return Type.IsValueType; }
+               }
+
+               public virtual bool IsInterface {
+                       get { return Type.IsInterface; }
+               }
+
+               public virtual bool IsSealed {
+                       get { return Type.IsSealed; }
+               }
+
+               public virtual bool CanInheritFrom ()
+               {
+                       if (Type == TypeManager.enum_type ||
+                           (Type == TypeManager.value_type && RootContext.StdLib) ||
+                           Type == TypeManager.multicast_delegate_type ||
+                           Type == TypeManager.delegate_type ||
+                           Type == TypeManager.array_type)
+                               return false;
+
+                       return true;
+               }
+
+               protected abstract TypeExpr DoResolveAsTypeStep (IResolveContext ec);
+
+               public abstract string Name {
+                       get;
+               }
+
+               public override bool Equals (object obj)
+               {
+                       TypeExpr tobj = obj as TypeExpr;
+                       if (tobj == null)
+                               return false;
+
+                       return Type == tobj.Type;
+               }
+
+               public override int GetHashCode ()
+               {
+                       return Type.GetHashCode ();
+               }
+               
+               public override string ToString ()
+               {
+                       return Name;
+               }
+       }
+
+       /// <summary>
+       ///   Fully resolved Expression that already evaluated to a type
+       /// </summary>
+       public class TypeExpression : TypeExpr {
+               public TypeExpression (Type t, Location l)
+               {
+                       Type = t;
+                       eclass = ExprClass.Type;
+                       loc = l;
+               }
+
+               protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
+               {
+                       return this;
+               }
+
+               public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
+               {
+                       return this;
+               }
+
+               public override string Name {
+                       get { return Type.ToString (); }
+               }
+
+               public override string FullName {
+                       get { return Type.FullName; }
+               }
+       }
+
+       /// <summary>
+       ///   Used to create types from a fully qualified name.  These are just used
+       ///   by the parser to setup the core types.  A TypeLookupExpression is always
+       ///   classified as a type.
+       /// </summary>
+       public sealed class TypeLookupExpression : TypeExpr {
+               readonly string name;
+               
+               public TypeLookupExpression (string name)
+               {
+                       this.name = name;
+                       eclass = ExprClass.Type;
+               }
+
+               public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
+               {
+                       // It's null for corlib compilation only
+                       if (type == null)
+                               return DoResolveAsTypeStep (ec);
+
+                       return this;
+               }
+
+               static readonly char [] dot_array = { '.' };
+               protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
+               {
+                       // If name is of the form `N.I', first lookup `N', then search a member `I' in it.
+                       string rest = null;
+                       string lookup_name = name;
+                       int pos = name.IndexOf ('.');
+                       if (pos >= 0) {
+                               rest = name.Substring (pos + 1);
+                               lookup_name = name.Substring (0, pos);
+                       }
+
+                       FullNamedExpression resolved = RootNamespace.Global.Lookup (ec.DeclContainer, lookup_name, Location.Null);
+
+                       if (resolved != null && rest != null) {
+                               // Now handle the rest of the the name.
+                               string [] elements = rest.Split (dot_array);
+                               string element;
+                               int count = elements.Length;
+                               int i = 0;
+                               while (i < count && resolved != null && resolved is Namespace) {
+                                       Namespace ns = resolved as Namespace;
+                                       element = elements [i++];
+                                       lookup_name += "." + element;
+                                       resolved = ns.Lookup (ec.DeclContainer, element, Location.Null);
+                               }
+
+                               if (resolved != null && resolved is TypeExpr) {
+                                       Type t = ((TypeExpr) resolved).Type;
+                                       while (t != null) {
+                                               if (!ec.DeclContainer.CheckAccessLevel (t)) {
+                                                       resolved = null;
+                                                       lookup_name = t.FullName;
+                                                       break;
+                                               }
+                                               if (i == count) {
+                                                       type = t;
+                                                       return this;
+                                               }
+                                               t = TypeManager.GetNestedType (t, elements [i++]);
+                                       }
+                               }
+                       }
+
+                       if (resolved == null) {
+                               NamespaceEntry.Error_NamespaceNotFound (loc, lookup_name);
+                               return null;
+                       }
+
+                       if (!(resolved is TypeExpr)) {
+                               resolved.Error_UnexpectedKind (ec.DeclContainer, "type", loc);
+                               return null;
+                       }
+
+                       type = resolved.Type;
+                       return this;
+               }
+
+               public override string Name {
+                       get { return name; }
+               }
+
+               public override string FullName {
+                       get { return name; }
+               }
+       }
+
+       /// <summary>
+       ///   Represents an "unbound generic type", ie. typeof (Foo<>).
+       ///   See 14.5.11.
+       /// </summary>
+       public class UnboundTypeExpression : TypeExpr
+       {
+               MemberName name;
+
+               public UnboundTypeExpression (MemberName name, Location l)
+               {
+                       this.name = name;
+                       loc = l;
+               }
+
+               protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
+               {
+                       Expression expr;
+                       if (name.Left != null) {
+                               Expression lexpr = name.Left.GetTypeExpression ();
+                               expr = new MemberAccess (lexpr, name.Basename);
+                       } else {
+                               expr = new SimpleName (name.Basename, loc);
+                       }
+
+                       FullNamedExpression fne = expr.ResolveAsTypeStep (ec, false);
+                       if (fne == null)
+                               return null;
+
+                       type = fne.Type;
+                       return new TypeExpression (type, loc);
+               }
+
+               public override string Name {
+                       get { return name.FullName; }
+               }
+
+               public override string FullName {
+                       get { return name.FullName; }
+               }
+       }
+
+       public class TypeAliasExpression : TypeExpr {
+               FullNamedExpression alias;
+               TypeExpr texpr;
+               TypeArguments args;
+               string name;
+
+               public TypeAliasExpression (FullNamedExpression alias, TypeArguments args, Location l)
+               {
+                       this.alias = alias;
+                       this.args = args;
+                       loc = l;
+
+                       eclass = ExprClass.Type;
+                       if (args != null)
+                               name = alias.FullName + "<" + args.ToString () + ">";
+                       else
+                               name = alias.FullName;
+               }
+
+               public override string Name {
+                       get { return alias.FullName; }
+               }
+
+               public override string FullName {
+                       get { return name; }
+               }
+
+               protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
+               {
+                       texpr = alias.ResolveAsTypeTerminal (ec, false);
+                       if (texpr == null)
+                               return null;
+
+                       Type type = texpr.Type;
+                       int num_args = TypeManager.GetNumberOfTypeArguments (type);
+
+                       if (args != null) {
+                               if (num_args == 0) {
+                                       Report.Error (308, loc,
+                                                     "The non-generic type `{0}' cannot " +
+                                                     "be used with type arguments.",
+                                                     TypeManager.CSharpName (type));
+                                       return null;
+                               }
+
+                               ConstructedType ctype = new ConstructedType (type, args, loc);
+                               return ctype.ResolveAsTypeTerminal (ec, false);
+                       } else if (num_args > 0) {
+                               Report.Error (305, loc,
+                                             "Using the generic type `{0}' " +
+                                             "requires {1} type arguments",
+                                             TypeManager.CSharpName (type), num_args.ToString ());
+                               return null;
+                       }
+
+                       return texpr;
+               }
+
+               public override bool CheckAccessLevel (DeclSpace ds)
+               {
+                       return texpr.CheckAccessLevel (ds);
+               }
+
+               public override bool AsAccessible (DeclSpace ds, int flags)
+               {
+                       return texpr.AsAccessible (ds, flags);
+               }
+
+               public override bool IsClass {
+                       get { return texpr.IsClass; }
+               }
+
+               public override bool IsValueType {
+                       get { return texpr.IsValueType; }
+               }
+
+               public override bool IsInterface {
+                       get { return texpr.IsInterface; }
+               }
+
+               public override bool IsSealed {
+                       get { return texpr.IsSealed; }
+               }
+       }
+
+       /// <summary>
+       ///   This class denotes an expression which evaluates to a member
+       ///   of a struct or a class.
+       /// </summary>
+       public abstract class MemberExpr : Expression
+       {
+               /// <summary>
+               ///   The name of this member.
+               /// </summary>
+               public abstract string Name {
+                       get;
+               }
+
+               /// <summary>
+               ///   Whether this is an instance member.
+               /// </summary>
+               public abstract bool IsInstance {
+                       get;
+               }
+
+               /// <summary>
+               ///   Whether this is a static member.
+               /// </summary>
+               public abstract bool IsStatic {
+                       get;
+               }
+
+               /// <summary>
+               ///   The type which declares this member.
+               /// </summary>
+               public abstract Type DeclaringType {
+                       get;
+               }
+
+               /// <summary>
+               ///   The instance expression associated with this member, if it's a
+               ///   non-static member.
+               /// </summary>
+               public Expression InstanceExpression;
+
+               public static void error176 (Location loc, string name)
+               {
+                       Report.Error (176, loc, "Static member `{0}' cannot be accessed " +
+                                     "with an instance reference, qualify it with a type name instead", name);
+               }
+
+               // TODO: possible optimalization
+               // Cache resolved constant result in FieldBuilder <-> expression map
+               public virtual Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
+                                                              SimpleName original)
+               {
+                       //
+                       // Precondition:
+                       //   original == null || original.Resolve (...) ==> left
+                       //
+
+                       if (left is TypeExpr) {
+                               if (!IsStatic) {
+                                       SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
+                                       return null;
+                               }
+
+                               return this;
+                       }
+                               
+                       if (!IsInstance) {
+                               if (original != null && original.IdenticalNameAndTypeName (ec, left, loc))
+                                       return this;
+
+                               error176 (loc, GetSignatureForError ());
+                               return null;
+                       }
+
+                       InstanceExpression = left;
+
+                       return this;
+               }
+
+               protected void EmitInstance (EmitContext ec, bool prepare_for_load)
+               {
+                       if (IsStatic)
+                               return;
+
+                       if (InstanceExpression == EmptyExpression.Null) {
+                               SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
+                               return;
+                       }
+                               
+                       if (InstanceExpression.Type.IsValueType) {
+                               if (InstanceExpression is IMemoryLocation) {
+                                       ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
+                               } else {
+                                       LocalTemporary t = new LocalTemporary (InstanceExpression.Type);
+                                       InstanceExpression.Emit (ec);
+                                       t.Store (ec);
+                                       t.AddressOf (ec, AddressOp.Store);
+                               }
+                       } else
+                               InstanceExpression.Emit (ec);
+
+                       if (prepare_for_load)
+                               ec.ig.Emit (OpCodes.Dup);
+               }
+       }
+
+       /// <summary>
+       ///   MethodGroup Expression.
+       ///  
+       ///   This is a fully resolved expression that evaluates to a type
+       /// </summary>
+       public class MethodGroupExpr : MemberExpr {
+               public MethodBase [] Methods;
+               bool has_type_arguments = false;
+               bool identical_type_name = false;
+               bool is_base;
+               
+               public MethodGroupExpr (MemberInfo [] mi, Location l)
+               {
+                       Methods = new MethodBase [mi.Length];
+                       mi.CopyTo (Methods, 0);
+                       eclass = ExprClass.MethodGroup;
+                       type = TypeManager.object_type;
+                       loc = l;
+               }
+
+               public MethodGroupExpr (ArrayList list, Location l)
+               {
+                       Methods = new MethodBase [list.Count];
+
+                       try {
+                               list.CopyTo (Methods, 0);
+                       } catch {
+                               foreach (MemberInfo m in list){
+                                       if (!(m is MethodBase)){
+                                               Console.WriteLine ("Name " + m.Name);
+                                               Console.WriteLine ("Found a: " + m.GetType ().FullName);
+                                       }
+                               }
+                               throw;
+                       }
+
+                       loc = l;
+                       eclass = ExprClass.MethodGroup;
+                       type = TypeManager.object_type;
+               }
+
+               public override Type DeclaringType {
+                       get {
+                                //
+                                // We assume that the top-level type is in the end
+                                //
+                               return Methods [Methods.Length - 1].DeclaringType;
+                                //return Methods [0].DeclaringType;
+                       }
+               }
+
+               public bool HasTypeArguments {
+                       get {
+                               return has_type_arguments;
+                       }
+
+                       set {
+                               has_type_arguments = value;
+                       }
+               }
+
+               public bool IdenticalTypeName {
+                       get {
+                               return identical_type_name;
+                       }
+
+                       set {
+                               identical_type_name = value;
+                       }
+               }
+
+               public bool IsBase {
+                       get {
+                               return is_base;
+                       }
+                       set {
+                               is_base = value;
+                       }
+               }
+
+               public override string GetSignatureForError ()
+               {
+                       return TypeManager.CSharpSignature (Methods [0]);
+               }
+
+               public override string Name {
+                       get {
+                               return Methods [0].Name;
+                       }
+               }
+
+               public override bool IsInstance {
+                       get {
+                               foreach (MethodBase mb in Methods)
+                                       if (!mb.IsStatic)
+                                               return true;
+
+                               return false;
+                       }
+               }
+
+               public override bool IsStatic {
+                       get {
+                               foreach (MethodBase mb in Methods)
+                                       if (mb.IsStatic)
+                                               return true;
+
+                               return false;
+                       }
+               }
+
+               public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
+                                                               SimpleName original)
+               {
+                       if (!(left is TypeExpr) &&
+                           original != null && original.IdenticalNameAndTypeName (ec, left, loc))
+                               IdenticalTypeName = true;
+
+                       return base.ResolveMemberAccess (ec, left, loc, original);
+               }
+               
+               override public Expression DoResolve (EmitContext ec)
+               {
+                       if (!IsInstance)
+                               InstanceExpression = null;
+
+                       if (InstanceExpression != null) {
+                               InstanceExpression = InstanceExpression.DoResolve (ec);
+                               if (InstanceExpression == null)
+                                       return null;
+                       }
+
+                       return this;
+               }
+
+               public void ReportUsageError ()
+               {
+                       Report.Error (654, loc, "Method `" + DeclaringType + "." +
+                                     Name + "()' is referenced without parentheses");
+               }
+
+               override public void Emit (EmitContext ec)
+               {
+                       ReportUsageError ();
+               }
+
+               bool RemoveMethods (bool keep_static)
+               {
+                       ArrayList smethods = new ArrayList ();
+
+                       foreach (MethodBase mb in Methods){
+                               if (mb.IsStatic == keep_static)
+                                       smethods.Add (mb);
+                       }
+
+                       if (smethods.Count == 0)
+                               return false;
+
+                       Methods = new MethodBase [smethods.Count];
+                       smethods.CopyTo (Methods, 0);
+
+                       return true;
+               }
+               
+               /// <summary>
+               ///   Removes any instance methods from the MethodGroup, returns
+               ///   false if the resulting set is empty.
+               /// </summary>
+               public bool RemoveInstanceMethods ()
+               {
+                       return RemoveMethods (true);
+               }
+
+               /// <summary>
+               ///   Removes any static methods from the MethodGroup, returns
+               ///   false if the resulting set is empty.
+               /// </summary>
+               public bool RemoveStaticMethods ()
+               {
+                       return RemoveMethods (false);
+               }
+
+               public Expression ResolveGeneric (EmitContext ec, TypeArguments args)
+               {
+#if GMCS_SOURCE
+                       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 Methods) {
+                               MethodInfo mi = mb as MethodInfo;
+                               if ((mi == null) || !mi.IsGenericMethod)
+                                       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.MakeGenericMethod (atypes));
+                       }
+
+                       if (list.Count > 0) {
+                               MethodGroupExpr new_mg = new MethodGroupExpr (list, Location);
+                               new_mg.InstanceExpression = InstanceExpression;
+                               new_mg.HasTypeArguments = true;
+                               new_mg.IsBase = IsBase;
+                               return new_mg;
+                       }
+
+                       if (first != null)
+                               Report.Error (
+                                       305, loc, "Using the generic method `{0}' " +
+                                       "requires {1} type arguments", Name,
+                                       first_count.ToString ());
+                       else
+                               Report.Error (
+                                       308, loc, "The non-generic method `{0}' " +
+                                       "cannot be used with type arguments", Name);
+
+                       return null;
+#else
+                       throw new NotImplementedException ();
+#endif
+               }
+       }
+
+       /// <summary>
+       ///   Fully resolved expression that evaluates to a Field
+       /// </summary>
+       public class FieldExpr : MemberExpr, IAssignMethod, IMemoryLocation, IVariable {
+               public readonly FieldInfo FieldInfo;
+               VariableInfo variable_info;
+               
+               LocalTemporary temp;
+               bool prepared;
+               bool in_initializer;
+
+               public FieldExpr (FieldInfo fi, Location l, bool in_initializer):
+                       this (fi, l)
+               {
+                       this.in_initializer = in_initializer;
+               }
+               
+               public FieldExpr (FieldInfo fi, Location l)
+               {
+                       FieldInfo = fi;
+                       eclass = ExprClass.Variable;
+                       type = TypeManager.TypeToCoreType (fi.FieldType);
+                       loc = l;
+               }
+
+               public override string Name {
+                       get {
+                               return FieldInfo.Name;
+                       }
+               }
+
+               public override bool IsInstance {
+                       get {
+                               return !FieldInfo.IsStatic;
+                       }
+               }
+
+               public override bool IsStatic {
+                       get {
+                               return FieldInfo.IsStatic;
+                       }
+               }
+
+               public override Type DeclaringType {
+                       get {
+                               return FieldInfo.DeclaringType;
+                       }
+               }
+
+               public override string GetSignatureForError ()
+               {
+                       return TypeManager.GetFullNameSignature (FieldInfo);
+               }
+
+               public VariableInfo VariableInfo {
+                       get {
+                               return variable_info;
+                       }
+               }
+
+               public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
+                                                               SimpleName original)
+               {
+                       FieldInfo fi = TypeManager.GetGenericFieldDefinition (FieldInfo);
+
+                       Type t = fi.FieldType;
+
+                       if (fi.IsLiteral || (fi.IsInitOnly && t == TypeManager.decimal_type)) {
+                               IConstant ic = TypeManager.GetConstant (fi);
+                               if (ic == null) {
+                                       if (fi.IsLiteral) {
+                                               ic = new ExternalConstant (fi);
+                                       } else {
+                                               ic = ExternalConstant.CreateDecimal (fi);
+                                               if (ic == null) {
+                                                       return base.ResolveMemberAccess (ec, left, loc, original);
+                                               }
+                                       }
+                                       TypeManager.RegisterConstant (fi, ic);
+                               }
+
+                               bool left_is_type = left is TypeExpr;
+                               if (!left_is_type && (original == null || !original.IdenticalNameAndTypeName (ec, left, loc))) {
+                                       Report.SymbolRelatedToPreviousError (FieldInfo);
+                                       error176 (loc, TypeManager.GetFullNameSignature (FieldInfo));
+                                       return null;
+                               }
+
+                               if (ic.ResolveValue ()) {
+                                       if (!ec.IsInObsoleteScope)
+                                               ic.CheckObsoleteness (loc);
+                               }
+
+                               return ic.Value;
+                       }
+                       
+                       if (t.IsPointer && !ec.InUnsafe) {
+                               UnsafeError (loc);
+                               return null;
+                       }
+
+                       return base.ResolveMemberAccess (ec, left, loc, original);
+               }
+
+               override public Expression DoResolve (EmitContext ec)
+               {
+                       return DoResolve (ec, false, false);
+               }
+
+               Expression DoResolve (EmitContext ec, bool lvalue_instance, bool out_access)
+               {
+                       if (!FieldInfo.IsStatic){
+                               if (InstanceExpression == null){
+                                       //
+                                       // This can happen when referencing an instance field using
+                                       // a fully qualified type expression: TypeName.InstanceField = xxx
+                                       // 
+                                       SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
+                                       return null;
+                               }
+
+                               // Resolve the field's instance expression while flow analysis is turned
+                               // off: when accessing a field "a.b", we must check whether the field
+                               // "a.b" is initialized, not whether the whole struct "a" is initialized.
+
+                               if (lvalue_instance) {
+                                       using (ec.With (EmitContext.Flags.DoFlowAnalysis, false)) {
+                                               Expression right_side =
+                                                       out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
+                                               InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side, loc);
+                                       }
+                               } else {
+                                       ResolveFlags rf = ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis;
+                                       InstanceExpression = InstanceExpression.Resolve (ec, rf);
+                               }
+
+                               if (InstanceExpression == null)
+                                       return null;
+
+                               InstanceExpression.CheckMarshalByRefAccess ();
+                       }
+
+                       if (!in_initializer && !ec.IsFieldInitializer) {
+                               ObsoleteAttribute oa;
+                               FieldBase f = TypeManager.GetField (FieldInfo);
+                               if (f != null) {
+                                       if (!ec.IsInObsoleteScope)
+                                               f.CheckObsoleteness (loc);
+                                
+                                       // To be sure that type is external because we do not register generated fields
+                               } else if (!(FieldInfo.DeclaringType is TypeBuilder)) {                                
+                                       oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo);
+                                       if (oa != null)
+                                               AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc);
+                               }
+                       }
+
+                       AnonymousContainer am = ec.CurrentAnonymousMethod;
+                       if (am != null){
+                               if (!FieldInfo.IsStatic){
+                                       if (!am.IsIterator && (ec.TypeContainer is Struct)){
+                                               Report.Error (1673, loc,
+                                               "Anonymous methods inside structs cannot access instance members of `{0}'. Consider copying `{0}' to a local variable outside the anonymous method and using the local instead",
+                                                       "this");
+                                               return null;
+                                       }
+                               }
+                       }
+                       
+                       // If the instance expression is a local variable or parameter.
+                       IVariable var = InstanceExpression as IVariable;
+                       if ((var == null) || (var.VariableInfo == null))
+                               return this;
+
+                       VariableInfo vi = var.VariableInfo;
+                       if (!vi.IsFieldAssigned (ec, FieldInfo.Name, loc))
+                               return null;
+
+                       variable_info = vi.GetSubStruct (FieldInfo.Name);
+                       return this;
+               }
+
+               static readonly int [] codes = {
+                       191,    // instance, write access
+                       192,    // instance, out access
+                       198,    // static, write access
+                       199,    // static, out access
+                       1648,   // member of value instance, write access
+                       1649,   // member of value instance, out access
+                       1650,   // member of value static, write access
+                       1651    // member of value static, out access
+               };
+
+               static readonly string [] msgs = {
+                       /*0191*/ "A readonly field `{0}' cannot be assigned to (except in a constructor or a variable initializer)",
+                       /*0192*/ "A readonly field `{0}' cannot be passed ref or out (except in a constructor)",
+                       /*0198*/ "A static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)",
+                       /*0199*/ "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
+                       /*1648*/ "Members of readonly field `{0}' cannot be modified (except in a constructor or a variable initializer)",
+                       /*1649*/ "Members of readonly field `{0}' cannot be passed ref or out (except in a constructor)",
+                       /*1650*/ "Fields of static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)",
+                       /*1651*/ "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)"
+               };
+
+               // The return value is always null.  Returning a value simplifies calling code.
+               Expression Report_AssignToReadonly (Expression right_side)
+               {
+                       int i = 0;
+                       if (right_side == EmptyExpression.OutAccess || right_side == EmptyExpression.LValueMemberOutAccess)
+                               i += 1;
+                       if (IsStatic)
+                               i += 2;
+                       if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess)
+                               i += 4;
+                       Report.Error (codes [i], loc, msgs [i], GetSignatureForError ());
+
+                       return null;
+               }
+               
+               override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       IVariable var = InstanceExpression as IVariable;
+                       if ((var != null) && (var.VariableInfo != null))
+                               var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name);
+
+                       bool lvalue_instance = !FieldInfo.IsStatic && FieldInfo.DeclaringType.IsValueType;
+                       bool out_access = right_side == EmptyExpression.OutAccess || right_side == EmptyExpression.LValueMemberOutAccess;
+
+                       Expression e = DoResolve (ec, lvalue_instance, out_access);
+
+                       if (e == null)
+                               return null;
+
+                       FieldBase fb = TypeManager.GetField (FieldInfo);
+                       if (fb != null)
+                               fb.SetAssigned ();
+
+                       if (FieldInfo.IsInitOnly) {
+                               // InitOnly fields can only be assigned in constructors or initializers
+                               if (!ec.IsFieldInitializer && !ec.IsConstructor)
+                                       return Report_AssignToReadonly (right_side);
+
+                               if (ec.IsConstructor) {
+                                       Type ctype = ec.TypeContainer.CurrentType;
+                                       if (ctype == null)
+                                               ctype = ec.ContainerType;
+
+                                       // InitOnly fields cannot be assigned-to in a different constructor from their declaring type
+                                       if (!TypeManager.IsEqual (ctype, FieldInfo.DeclaringType))
+                                               return Report_AssignToReadonly (right_side);
+                                       // static InitOnly fields cannot be assigned-to in an instance constructor
+                                       if (IsStatic && !ec.IsStatic)
+                                               return Report_AssignToReadonly (right_side);
+                                       // instance constructors can't modify InitOnly fields of other instances of the same type
+                                       if (!IsStatic && !(InstanceExpression is This))
+                                               return Report_AssignToReadonly (right_side);
+                               }
+                       }
+
+                       if (right_side == EmptyExpression.OutAccess &&
+                           !IsStatic && !(InstanceExpression is This) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
+                               Report.SymbolRelatedToPreviousError (DeclaringType);
+                               Report.Warning (197, 1, loc,
+                                               "Passing `{0}' as ref or out or taking its address may cause a runtime exception because it is a field of a marshal-by-reference class",
+                                               GetSignatureForError ());
+                       }
+
+                       return this;
+               }
+
+               public override void CheckMarshalByRefAccess ()
+               {
+                       if (!IsStatic && Type.IsValueType && !(InstanceExpression is This) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
+                               Report.SymbolRelatedToPreviousError (DeclaringType);
+                               Report.Warning (1690, 1, loc, "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
+                                               GetSignatureForError ());
+                       }
+               }
+
+               public bool VerifyFixed ()
+               {
+                       IVariable variable = InstanceExpression as IVariable;
+                       // A variable of the form V.I is fixed when V is a fixed variable of a struct type.
+                       // We defer the InstanceExpression check after the variable check to avoid a 
+                       // separate null check on InstanceExpression.
+                       return variable != null && InstanceExpression.Type.IsValueType && variable.VerifyFixed ();
+               }
+
+               public override int GetHashCode ()
+               {
+                       return FieldInfo.GetHashCode ();
+               }
+
+               public override bool Equals (object obj)
+               {
+                       FieldExpr fe = obj as FieldExpr;
+                       if (fe == null)
+                               return false;
+
+                       if (FieldInfo != fe.FieldInfo)
+                               return false;
+
+                       if (InstanceExpression == null || fe.InstanceExpression == null)
+                               return true;
+
+                       return InstanceExpression.Equals (fe.InstanceExpression);
+               }
+               
+               public void Emit (EmitContext ec, bool leave_copy)
+               {
+                       ILGenerator ig = ec.ig;
+                       bool is_volatile = false;
+
+                       FieldBase f = TypeManager.GetField (FieldInfo);
+                       if (f != null){
+                               if ((f.ModFlags & Modifiers.VOLATILE) != 0)
+                                       is_volatile = true;
+
+                               f.SetMemberIsUsed ();
+                       }
+                       
+                       if (FieldInfo.IsStatic){
+                               if (is_volatile)
+                                       ig.Emit (OpCodes.Volatile);
+                               
+                               ig.Emit (OpCodes.Ldsfld, FieldInfo);
+                       } else {
+                               if (!prepared)
+                                       EmitInstance (ec, false);
+
+                               if (is_volatile)
+                                       ig.Emit (OpCodes.Volatile);
+
+                               IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
+                               if (ff != null)
+                               {
+                                       ig.Emit (OpCodes.Ldflda, FieldInfo);
+                                       ig.Emit (OpCodes.Ldflda, ff.Element);
+                               }
+                               else {
+                                       ig.Emit (OpCodes.Ldfld, FieldInfo);
+                               }
+                       }
+
+                       if (leave_copy) {
+                               ec.ig.Emit (OpCodes.Dup);
+                               if (!FieldInfo.IsStatic) {
+                                       temp = new LocalTemporary (this.Type);
+                                       temp.Store (ec);
+                               }
+                       }
+               }
+
+               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
+               {
+                       FieldAttributes fa = FieldInfo.Attributes;
+                       bool is_static = (fa & FieldAttributes.Static) != 0;
+                       bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
+                       ILGenerator ig = ec.ig;
+                       prepared = prepare_for_load;
+
+                       if (is_readonly && !ec.IsConstructor){
+                               Report_AssignToReadonly (source);
+                               return;
+                       }
+
+                       EmitInstance (ec, prepare_for_load);
+
+                       source.Emit (ec);
+                       if (leave_copy) {
+                               ec.ig.Emit (OpCodes.Dup);
+                               if (!FieldInfo.IsStatic) {
+                                       temp = new LocalTemporary (this.Type);
+                                       temp.Store (ec);
+                               }
+                       }
+
+                       FieldBase f = TypeManager.GetField (FieldInfo);
+                       if (f != null){
+                               if ((f.ModFlags & Modifiers.VOLATILE) != 0)
+                                       ig.Emit (OpCodes.Volatile);
+                                       
+                               f.SetAssigned ();
+                       }
+
+                       if (is_static)
+                               ig.Emit (OpCodes.Stsfld, FieldInfo);
+                       else 
+                               ig.Emit (OpCodes.Stfld, FieldInfo);
+                       
+                       if (temp != null) {
+                               temp.Emit (ec);
+                               temp.Release (ec);
+                       }
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       Emit (ec, false);
+               }
+
+               public void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       FieldBase f = TypeManager.GetField (FieldInfo);
+                       if (f != null){
+                               if ((f.ModFlags & Modifiers.VOLATILE) != 0){
+                                       Report.Warning (420, 1, loc, "`{0}': A volatile fields cannot be passed using a ref or out parameter",
+                                                       f.GetSignatureForError ());
+                                       return;
+                               }
+                                       
+                               if ((mode & AddressOp.Store) != 0)
+                                       f.SetAssigned ();
+                               if ((mode & AddressOp.Load) != 0)
+                                       f.SetMemberIsUsed ();
+                       }
+
+                       //
+                       // Handle initonly fields specially: make a copy and then
+                       // get the address of the copy.
+                       //
+                       bool need_copy;
+                       if (FieldInfo.IsInitOnly){
+                               need_copy = true;
+                               if (ec.IsConstructor){
+                                       if (FieldInfo.IsStatic){
+                                               if (ec.IsStatic)
+                                                       need_copy = false;
+                                       } else
+                                               need_copy = false;
+                               }
+                       } else
+                               need_copy = false;
+                       
+                       if (need_copy){
+                               LocalBuilder local;
+                               Emit (ec);
+                               local = ig.DeclareLocal (type);
+                               ig.Emit (OpCodes.Stloc, local);
+                               ig.Emit (OpCodes.Ldloca, local);
+                               return;
+                       }
+
+
+                       if (FieldInfo.IsStatic){
+                               ig.Emit (OpCodes.Ldsflda, FieldInfo);
+                       } else {
+                               if (!prepared)
+                                       EmitInstance (ec, false);
+                               ig.Emit (OpCodes.Ldflda, FieldInfo);
+                       }
+               }
+       }
+
+       //
+       // A FieldExpr whose address can not be taken
+       //
+       public class FieldExprNoAddress : FieldExpr, IMemoryLocation {
+               public FieldExprNoAddress (FieldInfo fi, Location loc) : base (fi, loc)
+               {
+               }
+               
+               public new void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       Report.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
+               }
+       }
+       
+       /// <summary>
+       ///   Expression that evaluates to a Property.  The Assign class
+       ///   might set the `Value' expression if we are in an assignment.
+       ///
+       ///   This is not an LValue because we need to re-write the expression, we
+       ///   can not take data from the stack and store it.  
+       /// </summary>
+       public class PropertyExpr : MemberExpr, IAssignMethod {
+               public readonly PropertyInfo PropertyInfo;
+
+               //
+               // This is set externally by the  `BaseAccess' class
+               //
+               public bool IsBase;
+               MethodInfo getter, setter;
+               bool is_static;
+
+               bool resolved;
+               
+               LocalTemporary temp;
+               bool prepared;
+
+               internal static PtrHashtable AccessorTable = new PtrHashtable (); 
+
+               public PropertyExpr (Type containerType, PropertyInfo pi, Location l)
+               {
+                       PropertyInfo = pi;
+                       eclass = ExprClass.PropertyAccess;
+                       is_static = false;
+                       loc = l;
+
+                       type = TypeManager.TypeToCoreType (pi.PropertyType);
+
+                       ResolveAccessors (containerType);
+               }
+
+               public override string Name {
+                       get {
+                               return PropertyInfo.Name;
+                       }
+               }
+
+               public override bool IsInstance {
+                       get {
+                               return !is_static;
+                       }
+               }
+
+               public override bool IsStatic {
+                       get {
+                               return is_static;
+                       }
+               }
+               
+               public override Type DeclaringType {
+                       get {
+                               return PropertyInfo.DeclaringType;
+                       }
+               }
+
+               public override string GetSignatureForError ()
+               {
+                       return TypeManager.GetFullNameSignature (PropertyInfo);
+               }
+
+               void FindAccessors (Type invocation_type)
+               {
+                       const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
+                               BindingFlags.Static | BindingFlags.Instance |
+                               BindingFlags.DeclaredOnly;
+
+                       Type current = PropertyInfo.DeclaringType;
+                       for (; current != null; current = current.BaseType) {
+                               MemberInfo[] group = TypeManager.MemberLookup (
+                                       invocation_type, invocation_type, current,
+                                       MemberTypes.Property, flags, PropertyInfo.Name, null);
+
+                               if (group == null)
+                                       continue;
+
+                               if (group.Length != 1)
+                                       // Oooops, can this ever happen ?
+                                       return;
+
+                               PropertyInfo pi = (PropertyInfo) group [0];
+
+                               if (getter == null)
+                                       getter = pi.GetGetMethod (true);
+
+                               if (setter == null)
+                                       setter = pi.GetSetMethod (true);
+
+                               MethodInfo accessor = getter != null ? getter : setter;
+
+                               if (!accessor.IsVirtual)
+                                       return;
+                       }
+               }
+
+               //
+               // We also perform the permission checking here, as the PropertyInfo does not
+               // hold the information for the accessibility of its setter/getter
+               //
+               // TODO: can use TypeManager.GetProperty to boost performance
+               void ResolveAccessors (Type containerType)
+               {
+                       FindAccessors (containerType);
+
+                       if (getter != null) {
+                               MethodBase the_getter = TypeManager.DropGenericMethodArguments (getter);
+                               IMethodData md = TypeManager.GetMethod (the_getter);
+                               if (md != null)
+                                       md.SetMemberIsUsed ();
+
+                               AccessorTable [getter] = PropertyInfo;
+                               is_static = getter.IsStatic;
+                       }
+
+                       if (setter != null) {
+                               MethodBase the_setter = TypeManager.DropGenericMethodArguments (setter);
+                               IMethodData md = TypeManager.GetMethod (the_setter);
+                               if (md != null)
+                                       md.SetMemberIsUsed ();
+
+                               AccessorTable [setter] = PropertyInfo;
+                               is_static = setter.IsStatic;
+                       }
+               }
+
+               bool InstanceResolve (EmitContext ec, bool lvalue_instance, bool must_do_cs1540_check)
+               {
+                       if (is_static) {
+                               InstanceExpression = null;
+                               return true;
+                       }
+
+                       if (InstanceExpression == null) {
+                               SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
+                               return false;
+                       }
+
+                       InstanceExpression = InstanceExpression.DoResolve (ec);
+                       if (lvalue_instance && InstanceExpression != null)
+                               InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess, loc);
+
+                       if (InstanceExpression == null)
+                               return false;
+
+                       InstanceExpression.CheckMarshalByRefAccess ();
+
+                       if (must_do_cs1540_check && (InstanceExpression != EmptyExpression.Null) &&
+                           !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.ContainerType) &&
+                           !TypeManager.IsNestedChildOf (ec.ContainerType, InstanceExpression.Type) &&
+                           !TypeManager.IsSubclassOf (InstanceExpression.Type, ec.ContainerType)) {
+                               Report.SymbolRelatedToPreviousError (PropertyInfo);
+                               Error_CannotAccessProtected (loc, PropertyInfo, InstanceExpression.Type, ec.ContainerType);
+                               return false;
+                       }
+
+                       return true;
+               }
+
+               void Error_PropertyNotFound (MethodInfo mi, bool getter)
+               {
+                       // TODO: correctly we should compare arguments but it will lead to bigger changes
+                       if (mi is MethodBuilder) {
+                               Error_TypeDoesNotContainDefinition (loc, PropertyInfo.DeclaringType, Name);
+                               return;
+                       }
+
+                       StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType));
+                       sig.Append ('.');
+                       ParameterData iparams = TypeManager.GetParameterData (mi);
+                       sig.Append (getter ? "get_" : "set_");
+                       sig.Append (Name);
+                       sig.Append (iparams.GetSignatureForError ());
+
+                       Report.SymbolRelatedToPreviousError (mi);
+                       Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly",
+                               Name, sig.ToString ());
+               }
+               
+               override public Expression DoResolve (EmitContext ec)
+               {
+                       if (resolved)
+                               return this;
+
+                       if (getter != null){
+                               if (TypeManager.GetParameterData (getter).Count != 0){
+                                       Error_PropertyNotFound (getter, true);
+                                       return null;
+                               }
+                       }
+
+                       if (getter == null){
+                               //
+                               // The following condition happens if the PropertyExpr was
+                               // created, but is invalid (ie, the property is inaccessible),
+                               // and we did not want to embed the knowledge about this in
+                               // the caller routine.  This only avoids double error reporting.
+                               //
+                               if (setter == null)
+                                       return null;
+
+                               if (InstanceExpression != EmptyExpression.Null) {
+                                       Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
+                                               TypeManager.GetFullNameSignature (PropertyInfo));
+                                       return null;
+                               }
+                       } 
+
+                       bool must_do_cs1540_check = false;
+                       if (getter != null &&
+                           !IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) {
+                               PropertyBase.PropertyMethod pm = TypeManager.GetMethod (getter) as PropertyBase.PropertyMethod;
+                               if (pm != null && pm.HasCustomAccessModifier) {
+                                       Report.SymbolRelatedToPreviousError (pm);
+                                       Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
+                                               TypeManager.CSharpSignature (getter));
+                               }
+                               else {
+                                       Report.SymbolRelatedToPreviousError (getter);
+                                       ErrorIsInaccesible (loc, TypeManager.CSharpSignature (getter));
+                               }
+                               return null;
+                       }
+                       
+                       if (!InstanceResolve (ec, false, must_do_cs1540_check))
+                               return null;
+
+                       //
+                       // Only base will allow this invocation to happen.
+                       //
+                       if (IsBase && getter.IsAbstract) {
+                               Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
+                               return null;
+                       }
+
+                       if (PropertyInfo.PropertyType.IsPointer && !ec.InUnsafe){
+                               UnsafeError (loc);
+                               return null;
+                       }
+
+                       resolved = true;
+
+                       return this;
+               }
+
+               override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       if (right_side == EmptyExpression.OutAccess) {
+                               Report.Error (206, loc, "A property or indexer `{0}' may not be passed as an out or ref parameter",
+                                             GetSignatureForError ());
+                               return null;
+                       }
+
+                       if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) {
+                               Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable",
+                                             GetSignatureForError ());
+                               return null;
+                       }
+
+                       if (setter == null){
+                               //
+                               // The following condition happens if the PropertyExpr was
+                               // created, but is invalid (ie, the property is inaccessible),
+                               // and we did not want to embed the knowledge about this in
+                               // the caller routine.  This only avoids double error reporting.
+                               //
+                               if (getter == null)
+                                       return null;
+                               Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read only)",
+                                             GetSignatureForError ());
+                               return null;
+                       }
+
+                       if (TypeManager.GetParameterData (setter).Count != 1){
+                               Error_PropertyNotFound (setter, false);
+                               return null;
+                       }
+
+                       bool must_do_cs1540_check;
+                       if (!IsAccessorAccessible (ec.ContainerType, setter, out must_do_cs1540_check)) {
+                               PropertyBase.PropertyMethod pm = TypeManager.GetMethod (setter) as PropertyBase.PropertyMethod;
+                               if (pm != null && pm.HasCustomAccessModifier) {
+                                       Report.SymbolRelatedToPreviousError (pm);
+                                       Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
+                                               TypeManager.CSharpSignature (setter));
+                               }
+                               else {
+                                       Report.SymbolRelatedToPreviousError (setter);
+                                       ErrorIsInaccesible (loc, TypeManager.CSharpSignature (setter));
+                               }
+                               return null;
+                       }
+                       
+                       if (!InstanceResolve (ec, PropertyInfo.DeclaringType.IsValueType, must_do_cs1540_check))
+                               return null;
+                       
+                       //
+                       // Only base will allow this invocation to happen.
+                       //
+                       if (IsBase && setter.IsAbstract){
+                               Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
+                               return null;
+                       }
+
+                       return this;
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       Emit (ec, false);
+               }
+               
+               public void Emit (EmitContext ec, bool leave_copy)
+               {
+                       //
+                       // Special case: length of single dimension array property is turned into ldlen
+                       //
+                       if ((getter == TypeManager.system_int_array_get_length) ||
+                           (getter == TypeManager.int_array_get_length)){
+                               Type iet = InstanceExpression.Type;
+
+                               //
+                               // System.Array.Length can be called, but the Type does not
+                               // support invoking GetArrayRank, so test for that case first
+                               //
+                               if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)) {
+                                       if (!prepared)
+                                               EmitInstance (ec, false);
+                                       ec.ig.Emit (OpCodes.Ldlen);
+                                       ec.ig.Emit (OpCodes.Conv_I4);
+                                       return;
+                               }
+                       }
+
+                       Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, getter, null, loc, prepared, false);
+                       
+                       if (leave_copy) {
+                               ec.ig.Emit (OpCodes.Dup);
+                               if (!is_static) {
+                                       temp = new LocalTemporary (this.Type);
+                                       temp.Store (ec);
+                               }
+                       }
+               }
+
+               //
+               // Implements the IAssignMethod interface for assignments
+               //
+               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
+               {
+                       Expression my_source = source;
+
+                       prepared = prepare_for_load;
+                       
+                       if (prepared) {
+                               source.Emit (ec);
+                               if (leave_copy) {
+                                       ec.ig.Emit (OpCodes.Dup);
+                                       if (!is_static) {
+                                               temp = new LocalTemporary (this.Type);
+                                               temp.Store (ec);
+                                       }
+                               }
+                       } else if (leave_copy) {
+                               source.Emit (ec);
+                               if (!is_static) {
+                                       temp = new LocalTemporary (this.Type);
+                                       temp.Store (ec);
+                               }
+                               my_source = temp;
+                       }
+                       
+                       ArrayList args = new ArrayList (1);
+                       args.Add (new Argument (my_source, Argument.AType.Expression));
+                       
+                       Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, setter, args, loc, false, prepared);
+                       
+                       if (temp != null) {
+                               temp.Emit (ec);
+                               temp.Release (ec);
+                       }
+               }
+       }
+
+       /// <summary>
+       ///   Fully resolved expression that evaluates to an Event
+       /// </summary>
+       public class EventExpr : MemberExpr {
+               public readonly EventInfo EventInfo;
+
+               bool is_static;
+               MethodInfo add_accessor, remove_accessor;
+
+               internal static PtrHashtable AccessorTable = new PtrHashtable (); 
+               
+               public EventExpr (EventInfo ei, Location loc)
+               {
+                       EventInfo = ei;
+                       this.loc = loc;
+                       eclass = ExprClass.EventAccess;
+
+                       add_accessor = TypeManager.GetAddMethod (ei);
+                       remove_accessor = TypeManager.GetRemoveMethod (ei);
+                       if (add_accessor != null)
+                               AccessorTable [add_accessor] = ei;
+                       if (remove_accessor != null)
+                               AccessorTable [remove_accessor] = ei;
+                       
+                       if (add_accessor.IsStatic || remove_accessor.IsStatic)
+                               is_static = true;
+
+                       if (EventInfo is MyEventBuilder){
+                               MyEventBuilder eb = (MyEventBuilder) EventInfo;
+                               type = eb.EventType;
+                               eb.SetUsed ();
+                       } else
+                               type = EventInfo.EventHandlerType;
+               }
+
+               public override string Name {
+                       get {
+                               return EventInfo.Name;
+                       }
+               }
+
+               public override bool IsInstance {
+                       get {
+                               return !is_static;
+                       }
+               }
+
+               public override bool IsStatic {
+                       get {
+                               return is_static;
+                       }
+               }
+
+               public override Type DeclaringType {
+                       get {
+                               return EventInfo.DeclaringType;
+                       }
+               }
+
+               public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
+                                                               SimpleName original)
+               {
+                       //
+                       // If the event is local to this class, we transform ourselves into a FieldExpr
+                       //
+
+                       if (EventInfo.DeclaringType == ec.ContainerType ||
+                           TypeManager.IsNestedChildOf(ec.ContainerType, EventInfo.DeclaringType)) {
+                               MemberInfo mi = TypeManager.GetPrivateFieldOfEvent (EventInfo);
+
+                               if (mi != null) {
+                                       MemberExpr ml = (MemberExpr) ExprClassFromMemberInfo (ec.ContainerType, mi, loc);
+
+                                       if (ml == null) {
+                                               Report.Error (-200, loc, "Internal error!!");
+                                               return null;
+                                       }
+
+                                       InstanceExpression = null;
+                               
+                                       return ml.ResolveMemberAccess (ec, left, loc, original);
+                               }
+                       }
+
+                       return base.ResolveMemberAccess (ec, left, loc, original);
+               }
+
+
+               bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
+               {
+                       if (is_static) {
+                               InstanceExpression = null;
+                               return true;
+                       }
+
+                       if (InstanceExpression == null) {
+                               SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
+                               return false;
+                       }
+
+                       InstanceExpression = InstanceExpression.DoResolve (ec);
+                       if (InstanceExpression == null)
+                               return false;
+
+                       //
+                       // This is using the same mechanism as the CS1540 check in PropertyExpr.
+                       // However, in the Event case, we reported a CS0122 instead.
+                       //
+                       if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
+                           InstanceExpression.Type != ec.ContainerType &&
+                           ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) {
+                               Report.SymbolRelatedToPreviousError (EventInfo);
+                               ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
+                               return false;
+                       }
+
+                       return true;
+               }
+
+               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       return DoResolve (ec);
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       bool must_do_cs1540_check;
+                       if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check) &&
+                             IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
+                               Report.SymbolRelatedToPreviousError (EventInfo);
+                               ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
+                               return null;
+                       }
+
+                       if (!InstanceResolve (ec, must_do_cs1540_check))
+                               return null;
+                       
+                       return this;
+               }               
+
+               public override void Emit (EmitContext ec)
+               {
+                       if (InstanceExpression is This)
+                               Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=", GetSignatureForError ());
+                       else
+                               Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
+                                             "(except on the defining type)", Name);
+               }
+
+               public override string GetSignatureForError ()
+               {
+                       return TypeManager.CSharpSignature (EventInfo);
+               }
+
+               public void EmitAddOrRemove (EmitContext ec, Expression source)
+               {
+                       BinaryDelegate source_del = (BinaryDelegate) source;
+                       Expression handler = source_del.Right;
+                       
+                       Argument arg = new Argument (handler, Argument.AType.Expression);
+                       ArrayList args = new ArrayList ();
+                               
+                       args.Add (arg);
+                       
+                       if (source_del.IsAddition)
+                               Invocation.EmitCall (
+                                       ec, false, IsStatic, InstanceExpression, add_accessor, args, loc);
+                       else
+                               Invocation.EmitCall (
+                                       ec, false, IsStatic, InstanceExpression, remove_accessor, args, loc);
+               }
+       }
+
+       public class TemporaryVariable : Expression, IMemoryLocation
+       {
+               LocalInfo li;
+               Variable var;
+               
+               public TemporaryVariable (Type type, Location loc)
+               {
+                       this.type = type;
+                       this.loc = loc;
+                       eclass = ExprClass.Value;
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (li != null)
+                               return this;
+                       
+                       TypeExpr te = new TypeExpression (type, loc);
+                       li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
+                       if (!li.Resolve (ec))
+                               return null;
+
+                       if (ec.MustCaptureVariable (li)) {
+                               ScopeInfo scope = li.Block.CreateScopeInfo ();
+                               var = scope.AddLocal (li);
+                               type = var.Type;
+                       }
+                       
+                       return this;
+               }
+
+               public Variable Variable {
+                       get { return var != null ? var : li.Variable; }
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       Variable.EmitInstance (ec);
+                       Variable.Emit (ec);
+               }
+               
+               public void EmitLoadAddress (EmitContext ec)
+               {
+                       Variable.EmitInstance (ec);
+                       Variable.EmitAddressOf (ec);
+               }
+               
+               public void Store (EmitContext ec, Expression right_side)
+               {
+                       Variable.EmitInstance (ec);
+                       right_side.Emit (ec);
+                       Variable.EmitAssign (ec);
+               }
+               
+               public void EmitThis (EmitContext ec)
+               {
+                       Variable.EmitInstance (ec);
+               }
+               
+               public void EmitStore (EmitContext ec)
+               {
+                       Variable.EmitAssign (ec);
+               }
+               
+               public void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       EmitLoadAddress (ec);
+               }
+       }
+       
+}      
index d0ef7962bd8aff4ab5f3cc480a3de27416e44891..48ffb536930ed371971eca545d75e17f4e6a3a99 100644 (file)
@@ -3052,7 +3052,7 @@ namespace Mono.CSharp {
                        MethodInfo method;
                        Expression operator_group;
 
-                       operator_group = MethodLookup (ec, type, is_and ? "op_BitwiseAnd" : "op_BitwiseOr", loc);
+                       operator_group = MethodLookup (ec.ContainerType, type, is_and ? "op_BitwiseAnd" : "op_BitwiseOr", loc);
                        if (operator_group == null) {
                                Error19 ();
                                return null;
@@ -4852,9 +4852,23 @@ namespace Mono.CSharp {
                                        Report.Error (1620, loc, "Argument `{0}' must be passed with the `{1}' keyword",
                                                index, Parameter.GetModifierSignature (mod));
                        } else {
-                               Report.Error (1503, loc, "Argument {0}: Cannot convert from `{1}' to `{2}'",
-                                       index, Argument.FullDesc (a), expected_par.ParameterDesc (idx));
-                       }
+                               string p1 = Argument.FullDesc (a);
+                               string p2 = expected_par.ParameterDesc (idx);
+
+                               //
+                               // The parameter names are the same, most likely they come from different
+                               // assemblies.
+                               //
+                               if (p1 == p2){
+                                       Report.Error (1503, loc,
+                                                     "Argument {0}: Cannot conver from equally named types from different " +
+                                                     "assemblies {0} (from {1}) and {2} (from {3})",
+                                                     p1, a.Expr.Type.Assembly.FullName, p2,
+                                                     expected_par.ParameterType (idx).Assembly.FullName);
+                               } else
+                                       Report.Error (1503, loc, "Argument {0}: Cannot convert from `{1}' to `{2}'",
+                                                     index, p1, p2);
+                               }
                }
                
                public static bool VerifyArgumentsCompat (EmitContext ec, ArrayList Arguments,
diff --git a/mcs/mcs/namespace.cs b/mcs/mcs/namespace.cs
new file mode 100644 (file)
index 0000000..b92cf68
--- /dev/null
@@ -0,0 +1,1009 @@
+//
+// namespace.cs: Tracks namespaces
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//   Marek Safar (marek.safar@seznam.cz)
+//
+// (C) 2001 Ximian, Inc.
+//
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Reflection;
+
+namespace Mono.CSharp {
+
+       public class RootNamespace : Namespace {
+               static MethodInfo get_namespaces_method;
+
+               string alias_name;
+               Assembly referenced_assembly;
+
+               Hashtable all_namespaces;
+
+               static Hashtable root_namespaces;
+               public static GlobalRootNamespace Global;
+               
+               static RootNamespace ()
+               {
+                       get_namespaces_method = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance | BindingFlags.NonPublic);
+
+                       Reset ();
+               }
+
+               public static void Reset ()
+               {
+                       root_namespaces = new Hashtable ();
+                       Global = new GlobalRootNamespace ();
+                       root_namespaces ["global"] = Global;
+               }
+
+               protected RootNamespace (string alias_name, Assembly assembly)
+                       : base (null, String.Empty)
+               {
+                       this.alias_name = alias_name;
+                       referenced_assembly = assembly;
+
+                       all_namespaces = new Hashtable ();
+                       all_namespaces.Add ("", this);
+
+                       if (referenced_assembly != null)
+                               ComputeNamespaces (this.referenced_assembly);
+               }
+
+               public static void DefineRootNamespace (string name, Assembly assembly)
+               {
+                       if (name == "global") {
+                               // FIXME: Add proper error number
+                               Report.Error (-42, "Cannot define an external alias named `global'");
+                               return;
+                       }
+                       RootNamespace retval = GetRootNamespace (name);
+                       if (retval == null || retval.referenced_assembly != assembly)
+                               root_namespaces [name] = new RootNamespace (name, assembly);
+               }
+
+               public static RootNamespace GetRootNamespace (string name)
+               {
+                       return (RootNamespace) root_namespaces [name];
+               }
+
+               public virtual Type LookupTypeReflection (string name, Location loc)
+               {
+                       return GetTypeInAssembly (referenced_assembly, name);
+               }
+
+               public void RegisterNamespace (Namespace child)
+               {
+                       if (child != this)
+                               all_namespaces.Add (child.Name, child);
+               }
+
+               public bool IsNamespace (string name)
+               {
+                       return all_namespaces.Contains (name);
+               }
+
+               protected void EnsureNamespace (string dotted_name)
+               {
+                       if (dotted_name != null && dotted_name.Length != 0 && ! IsNamespace (dotted_name))
+                               GetNamespace (dotted_name, true);
+               }
+
+               protected void ComputeNamespaces (Assembly assembly)
+               {
+                       if (get_namespaces_method != null) {
+                               string [] namespaces = (string []) get_namespaces_method.Invoke (assembly, null);
+                               foreach (string ns in namespaces)
+                                       EnsureNamespace (ns);
+                               return;
+                       }
+
+                       foreach (Type t in assembly.GetExportedTypes ())
+                               EnsureNamespace (t.Namespace);
+               }
+               
+               protected static Type GetTypeInAssembly (Assembly assembly, string name)
+               {
+                       Type t = assembly.GetType (name);
+                       if (t == null)
+                               return null;
+
+                       if (t.IsPointer)
+                               throw new InternalErrorException ("Use GetPointerType() to get a pointer");
+
+                       TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
+                       if (ta == TypeAttributes.NestedPrivate)
+                               return null;
+
+                       if ((ta == TypeAttributes.NotPublic ||
+                            ta == TypeAttributes.NestedAssembly ||
+                            ta == TypeAttributes.NestedFamANDAssem) &&
+                           !TypeManager.IsFriendAssembly (t.Assembly))
+                               return null;
+
+                       return t;
+               }
+
+               public override string ToString ()
+               {
+                       return String.Format ("RootNamespace ({0}::)", alias_name);
+               }
+
+               public override string GetSignatureForError ()
+               {
+                       return alias_name + "::";
+               }
+       }
+
+       public class GlobalRootNamespace : RootNamespace {
+               Assembly [] assemblies;
+               Module [] modules;
+
+               public GlobalRootNamespace ()
+                       : base ("global", null)
+               {
+                       assemblies = new Assembly [0];
+               }
+
+               public Assembly [] Assemblies {
+                       get { return assemblies; }
+               }
+
+               public Module [] Modules {
+                       get { return modules; }
+               }
+
+               public void AddAssemblyReference (Assembly a)
+               {
+                       foreach (Assembly assembly in assemblies) {
+                               if (a == assembly)
+                                       return;
+                       }
+
+                       int top = assemblies.Length;
+                       Assembly [] n = new Assembly [top + 1];
+                       assemblies.CopyTo (n, 0);
+                       n [top] = a;
+                       assemblies = n;
+
+                       ComputeNamespaces (a);
+               }
+
+               public void AddModuleReference (Module m)
+               {
+                       int top = modules != null ? modules.Length : 0;
+                       Module [] n = new Module [top + 1];
+                       if (modules != null)
+                               modules.CopyTo (n, 0);
+                       n [top] = m;
+                       modules = n;
+
+                       if (m == CodeGen.Module.Builder)
+                               return;
+
+                       foreach (Type t in m.GetTypes ())
+                               EnsureNamespace (t.Namespace);
+               }
+
+               public override void Error_NamespaceDoesNotExist(DeclSpace ds, Location loc, string name)
+               {
+                       Report.Error (400, loc, "The type or namespace name `{0}' could not be found in the global namespace (are you missing an assembly reference?)",
+                               name);
+               }
+
+               public override Type LookupTypeReflection (string name, Location loc)
+               {
+                       Type found_type = null;
+               
+                       foreach (Assembly a in assemblies) {
+                               Type t = GetTypeInAssembly (a, name);
+                               if (t == null)
+                                       continue;
+                                       
+                               if (found_type == null) {
+                                       found_type = t;
+                                       continue;
+                               }
+
+                               Report.SymbolRelatedToPreviousError (found_type);
+                               Report.SymbolRelatedToPreviousError (t);
+                               Report.Error (433, loc, "The imported type `{0}' is defined multiple times", name);
+                                       
+                               return found_type;
+                       }
+
+                       if (modules != null) {
+                               foreach (Module module in modules) {
+                                       Type t = module.GetType (name);
+                                       if (t == null)
+                                               continue;
+
+                                       if (found_type == null) {
+                                               found_type = t;
+                                               continue;
+                                       }
+                                       
+                                       Report.SymbolRelatedToPreviousError (t);
+                                       Report.SymbolRelatedToPreviousError (found_type);
+                                       Report.Warning (436, 2, loc, "Ignoring imported type `{0}' since the current assembly already has a declaration with the same name",
+                                               TypeManager.CSharpName (t));
+                                       return t;
+                               }
+                       }
+
+                       return found_type;
+               }
+       }
+
+       /// <summary>
+       ///   Keeps track of the namespaces defined in the C# code.
+       ///
+       ///   This is an Expression to allow it to be referenced in the
+       ///   compiler parse/intermediate tree during name resolution.
+       /// </summary>
+       public class Namespace : FullNamedExpression {
+               
+               Namespace parent;
+               string fullname;
+               Hashtable namespaces;
+               IDictionary declspaces;
+               Hashtable cached_types;
+               RootNamespace root;
+
+               public readonly MemberName MemberName;
+
+               /// <summary>
+               ///   Constructor Takes the current namespace and the
+               ///   name.  This is bootstrapped with parent == null
+               ///   and name = ""
+               /// </summary>
+               public Namespace (Namespace parent, string name)
+               {
+                       // Expression members.
+                       this.eclass = ExprClass.Namespace;
+                       this.Type = null;
+                       this.loc = Location.Null;
+
+                       this.parent = parent;
+
+                       if (parent != null)
+                               this.root = parent.root;
+                       else
+                               this.root = this as RootNamespace;
+
+                       if (this.root == null)
+                               throw new InternalErrorException ("Root namespaces must be created using RootNamespace");
+                       
+                       string pname = parent != null ? parent.Name : "";
+                               
+                       if (pname == "")
+                               fullname = name;
+                       else
+                               fullname = parent.Name + "." + name;
+
+                       if (fullname == null)
+                               throw new InternalErrorException ("Namespace has a null fullname");
+
+                       if (parent != null && parent.MemberName != MemberName.Null)
+                               MemberName = new MemberName (parent.MemberName, name);
+                       else if (name.Length == 0)
+                               MemberName = MemberName.Null;
+                       else
+                               MemberName = new MemberName (name);
+
+                       namespaces = new Hashtable ();
+                       cached_types = new Hashtable ();
+
+                       root.RegisterNamespace (this);
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return this;
+               }
+
+               public virtual void Error_NamespaceDoesNotExist (DeclSpace ds, Location loc, string name)
+               {
+                       if (name.IndexOf ('`') > 0) {
+                               FullNamedExpression retval = Lookup (ds, SimpleName.RemoveGenericArity (name), loc);
+                               if (retval != null) {
+                                       Error_TypeArgumentsCannotBeUsed (retval.Type, loc, "type");
+                                       return;
+                               }
+                       } else {
+                               Type t = LookForAnyGenericType (name);
+                               if (t != null) {
+                                       Error_InvalidNumberOfTypeArguments (t, loc);
+                                       return;
+                               }
+                       }
+
+                       Report.Error (234, loc, "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?",
+                               name, FullName);
+               }
+
+               public static void Error_InvalidNumberOfTypeArguments (Type t, Location loc)
+               {
+                       Report.SymbolRelatedToPreviousError (t);
+                       Report.Error (305, loc, "Using the generic type `{0}' requires `{1}' type argument(s)",
+                               TypeManager.CSharpName(t), TypeManager.GetNumberOfTypeArguments(t).ToString());
+               }
+
+               public static void Error_TypeArgumentsCannotBeUsed(Type t, Location loc, string symbol)
+               {
+                       Report.SymbolRelatedToPreviousError(t);
+                       Report.Error(308, loc, "The non-generic {0} `{1}' cannot be used with the type argument(s)",
+                               symbol, TypeManager.CSharpName(t));
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       throw new InternalErrorException ("Expression tree referenced namespace " + fullname + " during Emit ()");
+               }
+
+               public override string GetSignatureForError ()
+               {
+                       return Name;
+               }
+               
+               public Namespace GetNamespace (string name, bool create)
+               {
+                       int pos = name.IndexOf ('.');
+
+                       Namespace ns;
+                       string first;
+                       if (pos >= 0)
+                               first = name.Substring (0, pos);
+                       else
+                               first = name;
+
+                       ns = (Namespace) namespaces [first];
+                       if (ns == null) {
+                               if (!create)
+                                       return null;
+
+                               ns = new Namespace (this, first);
+                               namespaces.Add (first, ns);
+                       }
+
+                       if (pos >= 0)
+                               ns = ns.GetNamespace (name.Substring (pos + 1), create);
+
+                       return ns;
+               }
+
+               TypeExpr LookupType (string name, Location loc)
+               {
+                       if (cached_types.Contains (name))
+                               return cached_types [name] as TypeExpr;
+
+                       Type t = null;
+                       if (declspaces != null) {
+                               DeclSpace tdecl = declspaces [name] as DeclSpace;
+                               if (tdecl != null) {
+                                       //
+                                       // Note that this is not:
+                                       //
+                                       //   t = tdecl.DefineType ()
+                                       //
+                                       // This is to make it somewhat more useful when a DefineType
+                                       // fails due to problems in nested types (more useful in the sense
+                                       // of fewer misleading error messages)
+                                       //
+                                       tdecl.DefineType ();
+                                       t = tdecl.TypeBuilder;
+                               }
+                       }
+                       string lookup = t != null ? t.FullName : (fullname.Length == 0 ? name : fullname + "." + name);
+                       Type rt = root.LookupTypeReflection (lookup, loc);
+                       if (t == null)
+                               t = rt;
+
+                       TypeExpr te = t == null ? null : new TypeExpression (t, Location.Null);
+                       cached_types [name] = te;
+                       return te;
+               }
+
+               ///
+               /// Used for better error reporting only
+               /// 
+               public Type LookForAnyGenericType (string typeName)
+               {
+                       if (declspaces == null)
+                               return null;
+
+                       typeName = SimpleName.RemoveGenericArity (typeName);
+
+                       foreach (DictionaryEntry de in declspaces) {
+                               string type_item = (string) de.Key;
+                               int pos = type_item.LastIndexOf ('`');
+                               if (pos == typeName.Length && String.Compare (typeName, 0, type_item, 0, pos) == 0)
+                                       return ((DeclSpace) de.Value).TypeBuilder;
+                       }
+                       return null;
+               }
+
+               public FullNamedExpression Lookup (DeclSpace ds, string name, Location loc)
+               {
+                       if (namespaces.Contains (name))
+                               return (Namespace) namespaces [name];
+
+                       TypeExpr te = LookupType (name, loc);
+                       if (te == null || !ds.CheckAccessLevel (te.Type))
+                               return null;
+
+                       return te;
+               }
+
+               public void AddDeclSpace (string name, DeclSpace ds)
+               {
+                       if (declspaces == null)
+                               declspaces = new HybridDictionary ();
+                       declspaces.Add (name, ds);
+               }
+
+               /// <summary>
+               ///   The qualified name of the current namespace
+               /// </summary>
+               public string Name {
+                       get { return fullname; }
+               }
+
+               public override string FullName {
+                       get { return fullname; }
+               }
+
+               /// <summary>
+               ///   The parent of this namespace, used by the parser to "Pop"
+               ///   the current namespace declaration
+               /// </summary>
+               public Namespace Parent {
+                       get { return parent; }
+               }
+
+               public override string ToString ()
+               {
+                       return String.Format ("Namespace ({0})", Name);
+               }
+       }
+
+       public class NamespaceEntry {
+               Namespace ns;
+               NamespaceEntry parent, implicit_parent;
+               SourceFile file;
+               int symfile_id;
+               Hashtable aliases;
+               ArrayList using_clauses;
+               public bool DeclarationFound = false;
+               bool UsingFound;
+
+               public readonly DeclSpace SlaveDeclSpace;
+
+               ListDictionary extern_aliases;
+
+               static ArrayList entries = new ArrayList ();
+
+               public static void Reset ()
+               {
+                       entries = new ArrayList ();
+               }
+
+               //
+               // This class holds the location where a using definition is
+               // done, and whether it has been used by the program or not.
+               //
+               // We use this to flag using clauses for namespaces that do not
+               // exist.
+               //
+               public class UsingEntry : IResolveContext {
+                       public readonly MemberName Name;
+                       readonly Expression Expr;
+                       readonly NamespaceEntry NamespaceEntry;
+                       readonly Location Location;
+                       
+                       public UsingEntry (NamespaceEntry entry, MemberName name, Location loc)
+                       {
+                               Name = name;
+                               Expr = name.GetTypeExpression ();
+                               NamespaceEntry = entry;
+                               Location = loc;
+                       }
+
+                       internal Namespace resolved;
+
+                       public Namespace Resolve ()
+                       {
+                               if (resolved != null)
+                                       return resolved;
+
+                               FullNamedExpression fne = Expr.ResolveAsTypeStep (this, false);
+                               if (fne == null) {
+                                       Error_NamespaceNotFound (Location, Name.ToString ());
+                                       return null;
+                               }
+
+                               resolved = fne as Namespace;
+                               if (resolved == null) {
+                                       Report.Error (138, Location,
+                                               "`{0} is a type not a namespace. A using namespace directive can only be applied to namespaces", Name.ToString ());
+                               }
+                               return resolved;
+                       }
+
+                       DeclSpace IResolveContext.DeclContainer {
+                               get { return NamespaceEntry.SlaveDeclSpace; }
+                       }
+
+                       DeclSpace IResolveContext.GenericDeclContainer {
+                               get { return NamespaceEntry.SlaveDeclSpace; }
+                       }
+
+                       bool IResolveContext.IsInObsoleteScope {
+                               get { return false; }
+                       }
+                       bool IResolveContext.IsInUnsafeScope {
+                               get { return false; }
+                       }
+               }
+
+               public abstract class AliasEntry {
+                       public readonly string Name;
+                       public readonly NamespaceEntry NamespaceEntry;
+                       public readonly Location Location;
+                       
+                       protected AliasEntry (NamespaceEntry entry, string name, Location loc)
+                       {
+                               Name = name;
+                               NamespaceEntry = entry;
+                               Location = loc;
+                       }
+                       
+                       protected FullNamedExpression resolved;
+                       bool error;
+
+                       public FullNamedExpression Resolve ()
+                       {
+                               if (resolved != null || error)
+                                       return resolved;
+                               resolved = DoResolve ();
+                               if (resolved == null)
+                                       error = true;
+                               return resolved;
+                       }
+
+                       protected abstract FullNamedExpression DoResolve ();
+               }
+
+               public class LocalAliasEntry : AliasEntry, IResolveContext {
+                       public readonly Expression Alias;
+                       
+                       public LocalAliasEntry (NamespaceEntry entry, string name, MemberName alias, Location loc) :
+                               base (entry, name, loc)
+                       {
+                               Alias = alias.GetTypeExpression ();
+                       }
+
+                       protected override FullNamedExpression DoResolve ()
+                       {
+                               resolved = Alias.ResolveAsTypeStep (this, false);
+                               if (resolved == null)
+                                       return null;
+
+                               if (resolved.Type != null) {
+                                       TypeAttributes attr = resolved.Type.Attributes & TypeAttributes.VisibilityMask;
+                                       if (attr == TypeAttributes.NestedPrivate || attr == TypeAttributes.NestedFamily ||
+                                               ((attr == TypeAttributes.NestedFamORAssem || attr == TypeAttributes.NestedAssembly) && 
+                                               TypeManager.LookupDeclSpace (resolved.Type) == null)) {
+                                               Expression.ErrorIsInaccesible (Alias.Location, Alias.ToString ());
+                                               return null;
+                                       }
+                               }
+
+                               return resolved;
+                       }
+
+                       DeclSpace IResolveContext.DeclContainer {
+                               get { return NamespaceEntry.SlaveDeclSpace; }
+                       }
+
+                       DeclSpace IResolveContext.GenericDeclContainer {
+                               get { return NamespaceEntry.SlaveDeclSpace; }
+                       }
+
+                       bool IResolveContext.IsInObsoleteScope {
+                               get { return false; }
+                       }
+                       bool IResolveContext.IsInUnsafeScope {
+                               get { return false; }
+                       }
+               }
+
+               public class ExternAliasEntry : AliasEntry {
+                       public ExternAliasEntry (NamespaceEntry entry, string name, Location loc) :
+                               base (entry, name, loc)
+                       {
+                       }
+
+                       protected override FullNamedExpression DoResolve ()
+                       {
+                               resolved = RootNamespace.GetRootNamespace (Name);
+                               if (resolved == null)
+                                       Report.Error (430, Location, "The extern alias '" + Name +
+                                                                       "' was not specified in a /reference option");
+
+                               return resolved;
+                       }
+               }
+
+               public NamespaceEntry (NamespaceEntry parent, SourceFile file, string name)
+               {
+                       this.parent = parent;
+                       this.file = file;
+                       entries.Add (this);
+                       this.ID = entries.Count;
+
+                       if (parent != null)
+                               ns = parent.NS.GetNamespace (name, true);
+                       else if (name != null)
+                               ns = RootNamespace.Global.GetNamespace (name, true);
+                       else
+                               ns = RootNamespace.Global;
+                       SlaveDeclSpace = new RootDeclSpace (this);
+               }
+
+               private NamespaceEntry (NamespaceEntry parent, SourceFile file, Namespace ns, bool slave)
+               {
+                       this.parent = parent;
+                       this.file = file;
+                       // no need to add self to 'entries', since we don't have any aliases or using entries.
+                       this.ID = -1;
+                       this.IsImplicit = true;
+                       this.ns = ns;
+                       this.SlaveDeclSpace = slave ? new RootDeclSpace (this) : null;
+               }
+
+               //
+               // According to section 16.3.1 (using-alias-directive), the namespace-or-type-name is
+               // resolved as if the immediately containing namespace body has no using-directives.
+               //
+               // Section 16.3.2 says that the same rule is applied when resolving the namespace-name
+               // in the using-namespace-directive.
+               //
+               // To implement these rules, the expressions in the using directives are resolved using 
+               // the "doppelganger" (ghostly bodiless duplicate).
+               //
+               NamespaceEntry doppelganger;
+               NamespaceEntry Doppelganger {
+                       get {
+                               if (!IsImplicit && doppelganger == null)
+                                       doppelganger = new NamespaceEntry (ImplicitParent, file, ns, true);
+                               return doppelganger;
+                       }
+               }
+
+               public readonly int ID;
+               public readonly bool IsImplicit;
+
+               public Namespace NS {
+                       get { return ns; }
+               }
+
+               public NamespaceEntry Parent {
+                       get { return parent; }
+               }
+
+               public NamespaceEntry ImplicitParent {
+                       get {
+                               if (parent == null)
+                                       return null;
+                               if (implicit_parent == null) {
+                                       implicit_parent = (parent.NS == ns.Parent)
+                                               ? parent
+                                               : new NamespaceEntry (parent, file, ns.Parent, false);
+                               }
+                               return implicit_parent;
+                       }
+               }
+
+               /// <summary>
+               ///   Records a new namespace for resolving name references
+               /// </summary>
+               public void Using (MemberName name, Location loc)
+               {
+                       if (DeclarationFound){
+                               Report.Error (1529, loc, "A using clause must precede all other namespace elements except extern alias declarations");
+                               return;
+                       }
+
+                       UsingFound = true;
+
+                       if (name.Equals (ns.MemberName))
+                               return;
+                       
+                       if (using_clauses == null)
+                               using_clauses = new ArrayList ();
+
+                       foreach (UsingEntry old_entry in using_clauses) {
+                               if (name.Equals (old_entry.Name)) {
+                                       Report.Warning (105, 3, loc, "The using directive for `{0}' appeared previously in this namespace", name.GetName ());
+                                       return;
+                               }
+                       }
+
+                       UsingEntry ue = new UsingEntry (Doppelganger, name, loc);
+                       using_clauses.Add (ue);
+               }
+
+               public void UsingAlias (string name, MemberName alias, Location loc)
+               {
+                       if (DeclarationFound){
+                               Report.Error (1529, loc, "A using clause must precede all other namespace elements except extern alias declarations");
+                               return;
+                       }
+
+                       UsingFound = true;
+
+                       if (aliases == null)
+                               aliases = new Hashtable ();
+
+                       if (aliases.Contains (name)) {
+                               AliasEntry ae = (AliasEntry) aliases [name];
+                               Report.SymbolRelatedToPreviousError (ae.Location, ae.Name);
+                               Report.Error (1537, loc, "The using alias `{0}' appeared previously in this namespace", name);
+                               return;
+                       }
+
+                       if (RootContext.Version == LanguageVersion.Default &&
+                           name == "global" && RootContext.WarningLevel >= 2)
+                               Report.Warning (440, 2, loc, "An alias named `global' will not be used when resolving 'global::';" +
+                                       " the global namespace will be used instead");
+
+                       // FIXME: get correct error number.  See if the above check can be merged
+                       if (extern_aliases != null && extern_aliases.Contains (name)) {
+                               AliasEntry ae = (AliasEntry) extern_aliases [name];
+                               Report.SymbolRelatedToPreviousError (ae.Location, ae.Name);
+                               Report.Error (1537, loc, "The using alias `{0}' appeared previously in this namespace", name);
+                               return;
+                       }
+
+                       aliases [name] = new LocalAliasEntry (Doppelganger, name, alias, loc);
+               }
+
+               public void UsingExternalAlias (string name, Location loc)
+               {
+                       if (UsingFound || DeclarationFound) {
+                               Report.Error (439, loc, "An extern alias declaration must precede all other elements");
+                               return;
+                       }
+                       
+                       // Share the extern_aliases field with the Doppelganger
+                       if (extern_aliases == null) {
+                               extern_aliases = new ListDictionary ();
+                               Doppelganger.extern_aliases = extern_aliases;
+                       }
+
+                       if (extern_aliases.Contains (name)) {
+                               AliasEntry ae = (AliasEntry) extern_aliases [name];
+                               Report.SymbolRelatedToPreviousError (ae.Location, ae.Name);
+                               Report.Error (1537, loc, "The using alias `{0}' appeared previously in this namespace", name);
+                               return;
+                       }
+
+                       if (name == "global") {
+                               Report.Error (1681, loc, "You cannot redefine the global extern alias");
+                               return;
+                       }
+
+                       // Register the alias in aliases and extern_aliases, since we need both of them
+                       // to keep things simple (different resolution scenarios)
+                       ExternAliasEntry alias = new ExternAliasEntry (Doppelganger, name, loc);
+                       extern_aliases [name] = alias;
+               }
+
+               public FullNamedExpression LookupNamespaceOrType (DeclSpace ds, string name, Location loc, bool ignore_cs0104)
+               {
+                       // Precondition: Only simple names (no dots) will be looked up with this function.
+                       FullNamedExpression resolved = null;
+                       for (NamespaceEntry curr_ns = this; curr_ns != null; curr_ns = curr_ns.ImplicitParent) {
+                               if ((resolved = curr_ns.Lookup (ds, name, loc, ignore_cs0104)) != null)
+                                       break;
+                       }
+                       return resolved;
+               }
+
+               static void Error_AmbiguousTypeReference (Location loc, string name, FullNamedExpression t1, FullNamedExpression t2)
+               {
+                       Report.Error (104, loc, "`{0}' is an ambiguous reference between `{1}' and `{2}'",
+                               name, t1.FullName, t2.FullName);
+               }
+
+               // Looks-up a alias named @name in this and surrounding namespace declarations
+               public FullNamedExpression LookupAlias (string name)
+               {
+                       AliasEntry entry = null;
+                       for (NamespaceEntry n = this; n != null; n = n.ImplicitParent) {
+                               if (n.extern_aliases != null && (entry = n.extern_aliases [name] as AliasEntry) != null)
+                                       break;
+                               if (n.aliases != null && (entry = n.aliases [name] as AliasEntry) != null)
+                                       break;
+                       }
+                       return entry == null ? null : entry.Resolve ();
+               }
+
+               private FullNamedExpression Lookup (DeclSpace ds, string name, Location loc, bool ignore_cs0104)
+               {
+                       //
+                       // Check whether it's in the namespace.
+                       //
+                       FullNamedExpression fne = NS.Lookup (ds, name, loc);
+                       if (fne != null)
+                               return fne;
+
+                       if (extern_aliases != null) {
+                               AliasEntry entry = extern_aliases [name] as AliasEntry;
+                               if (entry != null)
+                                       return entry.Resolve ();
+                       }
+                       
+                       if (IsImplicit)
+                               return null;
+                       
+                       //
+                       // Check aliases. 
+                       //
+                       if (aliases != null) {
+                               AliasEntry entry = aliases [name] as AliasEntry;
+                               if (entry != null)
+                                       return entry.Resolve ();
+                       }
+
+                       //
+                       // Check using entries.
+                       //
+                       FullNamedExpression match = null;
+                       foreach (Namespace using_ns in GetUsingTable ()) {
+                               match = using_ns.Lookup (ds, name, loc);
+                               if (match == null || !(match is TypeExpr))
+                                       continue;
+                               if (fne != null) {
+                                       if (!ignore_cs0104)
+                                               Error_AmbiguousTypeReference (loc, name, fne, match);
+                                       return null;
+                               }
+                               fne = match;
+                       }
+
+                       return fne;
+               }
+
+               // Our cached computation.
+               readonly Namespace [] empty_namespaces = new Namespace [0];
+               Namespace [] namespace_using_table;
+               Namespace [] GetUsingTable ()
+               {
+                       if (namespace_using_table != null)
+                               return namespace_using_table;
+
+                       if (using_clauses == null) {
+                               namespace_using_table = empty_namespaces;
+                               return namespace_using_table;
+                       }
+
+                       ArrayList list = new ArrayList (using_clauses.Count);
+
+                       foreach (UsingEntry ue in using_clauses) {
+                               Namespace using_ns = ue.Resolve ();
+                               if (using_ns == null)
+                                       continue;
+
+                               list.Add (using_ns);
+                       }
+
+                       namespace_using_table = new Namespace [list.Count];
+                       list.CopyTo (namespace_using_table, 0);
+                       return namespace_using_table;
+               }
+
+               readonly string [] empty_using_list = new string [0];
+
+               public int SymbolFileID {
+                       get {
+                               if (symfile_id == 0 && file.SourceFileEntry != null) {
+                                       int parent_id = parent == null ? 0 : parent.SymbolFileID;
+
+                                       string [] using_list = empty_using_list;
+                                       if (using_clauses != null) {
+                                               using_list = new string [using_clauses.Count];
+                                               for (int i = 0; i < using_clauses.Count; i++)
+                                                       using_list [i] = ((UsingEntry) using_clauses [i]).Name.ToString ();
+                                       }
+
+                                       symfile_id = CodeGen.SymbolWriter.DefineNamespace (ns.Name, file.SourceFileEntry, using_list, parent_id);
+                               }
+                               return symfile_id;
+                       }
+               }
+
+               static void MsgtryRef (string s)
+               {
+                       Console.WriteLine ("    Try using -r:" + s);
+               }
+
+               static void MsgtryPkg (string s)
+               {
+                       Console.WriteLine ("    Try using -pkg:" + s);
+               }
+
+               public static void Error_NamespaceNotFound (Location loc, string name)
+               {
+                       Report.Error (246, loc, "The type or namespace name `{0}' could not be found. Are you missing a using directive or an assembly reference?",
+                               name);
+
+                       switch (name) {
+                       case "Gtk": case "GtkSharp":
+                               MsgtryPkg ("gtk-sharp");
+                               break;
+
+                       case "Gdk": case "GdkSharp":
+                               MsgtryPkg ("gdk-sharp");
+                               break;
+
+                       case "Glade": case "GladeSharp":
+                               MsgtryPkg ("glade-sharp");
+                               break;
+
+                       case "System.Drawing":
+                       case "System.Web.Services":
+                       case "System.Web":
+                       case "System.Data":
+                       case "System.Windows.Forms":
+                               MsgtryRef (name);
+                               break;
+                       }
+               }
+
+               /// <summary>
+               ///   Used to validate that all the using clauses are correct
+               ///   after we are finished parsing all the files.  
+               /// </summary>
+               void VerifyUsing ()
+               {
+                       if (extern_aliases != null) {
+                               foreach (DictionaryEntry de in extern_aliases)
+                                       ((AliasEntry) de.Value).Resolve ();
+                       }               
+
+                       if (using_clauses != null) {
+                               foreach (UsingEntry ue in using_clauses)
+                                       ue.Resolve ();
+                       }
+
+                       if (aliases != null) {
+                               foreach (DictionaryEntry de in aliases)
+                                       ((AliasEntry) de.Value).Resolve ();
+                       }
+               }
+
+               /// <summary>
+               ///   Used to validate that all the using clauses are correct
+               ///   after we are finished parsing all the files.  
+               /// </summary>
+               static public void VerifyAllUsing ()
+               {
+                       foreach (NamespaceEntry entry in entries)
+                               entry.VerifyUsing ();
+               }
+
+               public string GetSignatureForError ()
+               {
+                       return ns.GetSignatureForError ();
+               }
+
+               public override string ToString ()
+               {
+                       return ns.ToString ();
+               }
+       }
+}
diff --git a/mcs/mcs/report.cs b/mcs/mcs/report.cs
new file mode 100644 (file)
index 0000000..f8b8725
--- /dev/null
@@ -0,0 +1,759 @@
+//
+// report.cs: report errors and warnings.
+//
+// Author: Miguel de Icaza (miguel@ximian.com)
+//         Marek Safar (marek.safar@seznam.cz)         
+//
+// (C) 2001 Ximian, Inc. (http://www.ximian.com)
+//
+
+using System;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Diagnostics;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace Mono.CSharp {
+
+       /// <summary>
+       ///   This class is used to report errors and warnings t te user.
+       /// </summary>
+       public class Report {
+               /// <summary>  
+               ///   Errors encountered so far
+               /// </summary>
+               static public int Errors;
+
+               /// <summary>  
+               ///   Warnings encountered so far
+               /// </summary>
+               static public int Warnings;
+
+               /// <summary>  
+               ///   Whether errors should be throw an exception
+               /// </summary>
+               static public bool Fatal;
+               
+               /// <summary>  
+               ///   Whether warnings should be considered errors
+               /// </summary>
+               static public bool WarningsAreErrors;
+
+               /// <summary>  
+               ///   Whether to dump a stack trace on errors. 
+               /// </summary>
+               static public bool Stacktrace;
+
+               static public TextWriter Stderr = Console.Error;
+               
+               //
+               // If the 'expected' error code is reported then the
+                // compilation succeeds.
+               //
+               // Used for the test suite to excercise the error codes
+               //
+               static int expected_error = 0;
+
+               //
+               // Keeps track of the warnings that we are ignoring
+               //
+               public static Hashtable warning_ignore_table;
+
+               static Hashtable warning_regions_table;
+
+               /// <summary>
+               /// List of symbols related to reported error/warning. You have to fill it before error/warning is reported.
+               /// </summary>
+               static StringCollection extra_information = new StringCollection ();
+
+               // 
+               // IF YOU ADD A NEW WARNING YOU HAVE TO ADD ITS ID HERE
+               //
+               public static readonly int[] AllWarnings = new int[] {
+                       28, 67, 78,
+                       105, 108, 109, 114, 162, 164, 168, 169, 183, 184, 197,
+                       219, 251, 252, 253, 278, 282,
+                       419, 420, 429, 436, 440, 465, 467, 469,
+                       612, 618, 626, 628, 642, 649, 652, 658, 659, 660, 661, 665, 672, 675,
+                       1030,
+                       1522, 1570, 1571, 1572, 1573, 1574, 1580, 1581, 1584, 1587, 1589, 1590, 1591, 1592,
+                       1616, 1633, 1634, 1635, 1690, 1691, 1692,
+                       1717, 1718, 1720,
+                       1901,
+                       2002, 2023,
+                       3005, 3012, 3018, 3019, 3021, 3022, 3023, 3026, 3027,
+#if GMCS_SOURCE
+                       402, 414, 693, 1058, 1700, 3024
+#endif
+               };
+
+               static Report ()
+               {
+                       // Just to be sure that binary search is working
+                       Array.Sort (AllWarnings);
+               }
+
+               public static void Reset ()
+               {
+                       Errors = Warnings = 0;
+                       WarningsAreErrors = false;
+                       warning_ignore_table = null;
+                       warning_regions_table = null;
+               }
+
+               abstract class AbstractMessage {
+
+                       static void Check (int code)
+                       {
+                               if (code == expected_error) {
+                                       Environment.Exit (0);
+                               }
+                       }
+
+                       public abstract bool IsWarning { get; }
+
+                       public abstract string MessageType { get; }
+
+                       public virtual void Print (int code, string location, string text)
+                       {
+                               if (code < 0)
+                                       code = 8000-code;
+
+                               StringBuilder msg = new StringBuilder ();
+                               if (location.Length != 0) {
+                                       msg.Append (location);
+                                       msg.Append (' ');
+                               }
+                               msg.AppendFormat ("{0} CS{1:0000}: {2}", MessageType, code, text);
+                               Stderr.WriteLine (msg.ToString ());
+
+                               foreach (string s in extra_information) 
+                                       Stderr.WriteLine (s + MessageType + ")");
+
+                               extra_information.Clear ();
+
+                               if (Stacktrace)
+                                       Console.WriteLine (FriendlyStackTrace (new StackTrace (true)));
+
+                               if (Fatal) {
+                                       if (!IsWarning || WarningsAreErrors)
+                                               throw new Exception (text);
+                               }
+
+                               Check (code);
+                       }
+
+                       public virtual void Print (int code, Location location, string text)
+                       {
+                               Print (code, location.IsNull ? "" : location.ToString (), text);
+                       }
+               }
+
+               sealed class WarningMessage : AbstractMessage {
+                       Location loc = Location.Null;
+                       readonly int Level;
+
+                       public WarningMessage (int level)
+                       {
+                               Level = level;
+                       }
+
+                       public override bool IsWarning {
+                               get { return true; }
+                       }
+
+                       bool IsEnabled (int code)
+                       {
+                               if (RootContext.WarningLevel < Level)
+                                       return false;
+
+                               if (warning_ignore_table != null) {
+                                       if (warning_ignore_table.Contains (code)) {
+                                               return false;
+                                       }
+                               }
+
+                               if (warning_regions_table == null || loc.Equals (Location.Null))
+                                       return true;
+
+                               WarningRegions regions = (WarningRegions)warning_regions_table [loc.Name];
+                               if (regions == null)
+                                       return true;
+
+                               return regions.IsWarningEnabled (code, loc.Row);
+                       }
+
+                       public override void Print(int code, string location, string text)
+                       {
+                               if (!IsEnabled (code)) {
+                                       extra_information.Clear ();
+                                       return;
+                               }
+
+                               if (WarningsAreErrors) {
+                                       new ErrorMessage ().Print (code, location, text);
+                                       return;
+                               }
+
+                               Warnings++;
+                               base.Print (code, location, text);
+                       }
+
+                       public override void Print(int code, Location location, string text)
+                       {
+                               loc = location;
+                               base.Print (code, location, text);
+                       }
+
+                       public override string MessageType {
+                               get {
+                                       return "warning";
+                               }
+                       }
+               }
+
+               sealed class ErrorMessage : AbstractMessage {
+
+                       public override void Print(int code, string location, string text)
+                       {
+                               Errors++;
+                               base.Print (code, location, text);
+                       }
+
+                       public override bool IsWarning {
+                               get { return false; }
+                       }
+
+                       public override string MessageType {
+                               get {
+                                       return "error";
+                               }
+                       }
+
+               }
+
+               public static void FeatureIsNotStandardized (Location loc, string feature)
+               {
+                       Report.Error (1644, loc, "Feature `{0}' cannot be used because it is not part of the standardized ISO C# language specification", feature);
+               }
+               
+               public static string FriendlyStackTrace (Exception e)
+               {
+                       return FriendlyStackTrace (new StackTrace (e, true));
+               }
+               
+               static string FriendlyStackTrace (StackTrace t)
+               {               
+                       StringBuilder sb = new StringBuilder ();
+                       
+                       bool foundUserCode = false;
+                       
+                       for (int i = 0; i < t.FrameCount; i++) {
+                               StackFrame f = t.GetFrame (i);
+                               MethodBase mb = f.GetMethod ();
+                               
+                               if (!foundUserCode && mb.ReflectedType == typeof (Report))
+                                       continue;
+                               
+                               foundUserCode = true;
+                               
+                               sb.Append ("\tin ");
+                               
+                               if (f.GetFileLineNumber () > 0)
+                                       sb.AppendFormat ("(at {0}:{1}) ", f.GetFileName (), f.GetFileLineNumber ());
+                               
+                               sb.AppendFormat ("{0}.{1} (", mb.ReflectedType.Name, mb.Name);
+                               
+                               bool first = true;
+                               foreach (ParameterInfo pi in mb.GetParameters ()) {
+                                       if (!first)
+                                               sb.Append (", ");
+                                       first = false;
+                                       
+                                       sb.Append (TypeManager.CSharpName (pi.ParameterType));
+                               }
+                               sb.Append (")\n");
+                       }
+       
+                       return sb.ToString ();
+               }
+
+               public static void StackTrace ()
+               {
+                       Console.WriteLine (FriendlyStackTrace (new StackTrace (true)));
+               }
+
+               public static bool IsValidWarning (int code)
+               {       
+                       return Array.BinarySearch (AllWarnings, code) >= 0;
+               }
+                       
+               static public void RuntimeMissingSupport (Location loc, string feature) 
+               {
+                       Report.Error (-88, loc, "Your .NET Runtime does not support `{0}'. Please use the latest Mono runtime instead.", feature);
+               }
+
+               /// <summary>
+               /// In most error cases is very useful to have information about symbol that caused the error.
+               /// Call this method before you call Report.Error when it makes sense.
+               /// </summary>
+               static public void SymbolRelatedToPreviousError (Location loc, string symbol)
+               {
+                       SymbolRelatedToPreviousError (loc.ToString (), symbol);
+               }
+
+               static public void SymbolRelatedToPreviousError (MemberInfo mi)
+               {
+                       Type dt = TypeManager.DropGenericTypeArguments (mi.DeclaringType);
+                       DeclSpace temp_ds = TypeManager.LookupDeclSpace (dt);
+                       if (temp_ds == null) {
+                               SymbolRelatedToPreviousError (dt.Assembly.Location, TypeManager.GetFullNameSignature (mi));
+                       } else {
+                               MethodBase mb = mi as MethodBase;
+                               if (mb != null) {
+                                       mb = TypeManager.DropGenericMethodArguments (mb);
+                                       IMethodData md = TypeManager.GetMethod (mb);
+                                       SymbolRelatedToPreviousError (md.Location, md.GetSignatureForError ());
+                                       return;
+                               }
+
+                               MemberCore mc = temp_ds.GetDefinition (mi.Name);
+                               SymbolRelatedToPreviousError (mc);
+                       }
+               }
+
+               static public void SymbolRelatedToPreviousError (MemberCore mc)
+               {
+                       SymbolRelatedToPreviousError (mc.Location, mc.GetSignatureForError ());
+               }
+
+               static public void SymbolRelatedToPreviousError (Type type)
+               {
+                       type = TypeManager.DropGenericTypeArguments (type);
+
+                       if (TypeManager.IsGenericParameter (type)) {
+                               TypeParameter tp = TypeManager.LookupTypeParameter (type);
+                               if (tp != null) {
+                                       SymbolRelatedToPreviousError (tp.Location, "");
+                                       return;
+                               }
+                       }
+
+                       if (type is TypeBuilder) {
+                               DeclSpace temp_ds = TypeManager.LookupDeclSpace (type);
+                               SymbolRelatedToPreviousError (temp_ds.Location, TypeManager.CSharpName (type));
+                       } else if (type.HasElementType) {
+                               SymbolRelatedToPreviousError (type.GetElementType ());
+                       } else {
+                               SymbolRelatedToPreviousError (type.Assembly.Location, TypeManager.CSharpName (type));
+                       }
+               }
+
+               static void SymbolRelatedToPreviousError (string loc, string symbol)
+               {
+                       extra_information.Add (String.Format ("{0} (Location of the symbol related to previous ", loc));
+               }
+
+               public static void ExtraInformation (Location loc, string msg)
+               {
+                       extra_information.Add (String.Format ("{0} {1}", loc, msg));
+               }
+
+               public static WarningRegions RegisterWarningRegion (Location location)
+               {
+                       if (warning_regions_table == null)
+                               warning_regions_table = new Hashtable ();
+
+                       WarningRegions regions = (WarningRegions)warning_regions_table [location.Name];
+                       if (regions == null) {
+                               regions = new WarningRegions ();
+                               warning_regions_table.Add (location.Name, regions);
+                       }
+                       return regions;
+               }
+
+               static public void Warning (int code, int level, Location loc, string message)
+               {
+                       WarningMessage w = new WarningMessage (level);
+                       w.Print (code, loc, message);
+               }
+
+               static public void Warning (int code, int level, Location loc, string format, string arg)
+               {
+                       WarningMessage w = new WarningMessage (level);
+                       w.Print (code, loc, String.Format (format, arg));
+               }
+
+               static public void Warning (int code, int level, Location loc, string format, string arg1, string arg2)
+               {
+                       WarningMessage w = new WarningMessage (level);
+                       w.Print (code, loc, String.Format (format, arg1, arg2));
+               }
+
+               static public void Warning (int code, int level, Location loc, string format, params string[] args)
+               {
+                       WarningMessage w = new WarningMessage (level);
+                       w.Print (code, loc, String.Format (format, args));
+               }
+
+               static public void Warning (int code, int level, string message)
+               {
+                       Warning (code, level, Location.Null, message);
+               }
+
+               static public void Warning (int code, int level, string format, string arg)
+               {
+                       Warning (code, level, Location.Null, format, arg);
+               }
+
+               static public void Warning (int code, int level, string format, string arg1, string arg2)
+               {
+                       Warning (code, level, Location.Null, format, arg1, arg2);
+               }
+
+               static public void Warning (int code, int level, string format, params string[] args)
+               {
+                       Warning (code, level, Location.Null, String.Format (format, args));
+               }
+
+               static public void Error (int code, Location loc, string error)
+               {
+                       new ErrorMessage ().Print (code, loc, error);
+               }
+
+               static public void Error (int code, Location loc, string format, string arg)
+               {
+                       new ErrorMessage ().Print (code, loc, String.Format (format, arg));
+               }
+
+               static public void Error (int code, Location loc, string format, string arg1, string arg2)
+               {
+                       new ErrorMessage ().Print (code, loc, String.Format (format, arg1, arg2));
+               }
+
+               static public void Error (int code, Location loc, string format, params string[] args)
+               {
+                       Error (code, loc, String.Format (format, args));
+               }
+
+               static public void Error (int code, string error)
+               {
+                       Error (code, Location.Null, error);
+               }
+
+               static public void Error (int code, string format, string arg)
+               {
+                       Error (code, Location.Null, format, arg);
+               }
+
+               static public void Error (int code, string format, string arg1, string arg2)
+               {
+                       Error (code, Location.Null, format, arg1, arg2);
+               }
+
+               static public void Error (int code, string format, params string[] args)
+               {
+                       Error (code, Location.Null, String.Format (format, args));
+               }
+
+               static public void SetIgnoreWarning (int code)
+               {
+                       if (warning_ignore_table == null)
+                               warning_ignore_table = new Hashtable ();
+
+                       warning_ignore_table [code] = true;
+               }
+               
+               static public int ExpectedError {
+                       set {
+                               expected_error = value;
+                       }
+                       get {
+                               return expected_error;
+                       }
+               }
+
+               public static int DebugFlags = 0;
+
+               [Conditional ("MCS_DEBUG")]
+               static public void Debug (string message, params object[] args)
+               {
+                       Debug (4, message, args);
+               }
+                       
+               [Conditional ("MCS_DEBUG")]
+               static public void Debug (int category, string message, params object[] args)
+               {
+                       if ((category & DebugFlags) == 0)
+                               return;
+
+                       StringBuilder sb = new StringBuilder (message);
+
+                       if ((args != null) && (args.Length > 0)) {
+                               sb.Append (": ");
+
+                               bool first = true;
+                               foreach (object arg in args) {
+                                       if (first)
+                                               first = false;
+                                       else
+                                               sb.Append (", ");
+                                       if (arg == null)
+                                               sb.Append ("null");
+                                       else if (arg is ICollection)
+                                               sb.Append (PrintCollection ((ICollection) arg));
+                                       else
+                                               sb.Append (arg);
+                               }
+                       }
+
+                       Console.WriteLine (sb.ToString ());
+               }
+
+               static public string PrintCollection (ICollection collection)
+               {
+                       StringBuilder sb = new StringBuilder ();
+
+                       sb.Append (collection.GetType ());
+                       sb.Append ("(");
+
+                       bool first = true;
+                       foreach (object o in collection) {
+                               if (first)
+                                       first = false;
+                               else
+                                       sb.Append (", ");
+                               sb.Append (o);
+                       }
+
+                       sb.Append (")");
+                       return sb.ToString ();
+               }
+       }
+
+       public enum TimerType {
+               FindMembers     = 0,
+               TcFindMembers   = 1,
+               MemberLookup    = 2,
+               CachedLookup    = 3,
+               CacheInit       = 4,
+               MiscTimer       = 5,
+               CountTimers     = 6
+       }
+
+       public enum CounterType {
+               FindMembers     = 0,
+               MemberCache     = 1,
+               MiscCounter     = 2,
+               CountCounters   = 3
+       }
+
+       public class Timer
+       {
+               static DateTime[] timer_start;
+               static TimeSpan[] timers;
+               static long[] timer_counters;
+               static long[] counters;
+
+               static Timer ()
+               {
+                       timer_start = new DateTime [(int) TimerType.CountTimers];
+                       timers = new TimeSpan [(int) TimerType.CountTimers];
+                       timer_counters = new long [(int) TimerType.CountTimers];
+                       counters = new long [(int) CounterType.CountCounters];
+
+                       for (int i = 0; i < (int) TimerType.CountTimers; i++) {
+                               timer_start [i] = DateTime.Now;
+                               timers [i] = TimeSpan.Zero;
+                       }
+               }
+
+               [Conditional("TIMER")]
+               static public void IncrementCounter (CounterType which)
+               {
+                       ++counters [(int) which];
+               }
+
+               [Conditional("TIMER")]
+               static public void StartTimer (TimerType which)
+               {
+                       timer_start [(int) which] = DateTime.Now;
+               }
+
+               [Conditional("TIMER")]
+               static public void StopTimer (TimerType which)
+               {
+                       timers [(int) which] += DateTime.Now - timer_start [(int) which];
+                       ++timer_counters [(int) which];
+               }
+
+               [Conditional("TIMER")]
+               static public void ShowTimers ()
+               {
+                       ShowTimer (TimerType.FindMembers, "- FindMembers timer");
+                       ShowTimer (TimerType.TcFindMembers, "- TypeContainer.FindMembers timer");
+                       ShowTimer (TimerType.MemberLookup, "- MemberLookup timer");
+                       ShowTimer (TimerType.CachedLookup, "- CachedLookup timer");
+                       ShowTimer (TimerType.CacheInit, "- Cache init");
+                       ShowTimer (TimerType.MiscTimer, "- Misc timer");
+
+                       ShowCounter (CounterType.FindMembers, "- Find members");
+                       ShowCounter (CounterType.MemberCache, "- Member cache");
+                       ShowCounter (CounterType.MiscCounter, "- Misc counter");
+               }
+
+               static public void ShowCounter (CounterType which, string msg)
+               {
+                       Console.WriteLine ("{0} {1}", counters [(int) which], msg);
+               }
+
+               static public void ShowTimer (TimerType which, string msg)
+               {
+                       Console.WriteLine (
+                               "[{0:00}:{1:000}] {2} (used {3} times)",
+                               (int) timers [(int) which].TotalSeconds,
+                               timers [(int) which].Milliseconds, msg,
+                               timer_counters [(int) which]);
+               }
+       }
+
+       public class InternalErrorException : Exception {
+               public InternalErrorException (Location loc, string text, Exception e)
+                       : base (loc + " " + text, e)
+               {
+               }
+
+               public InternalErrorException ()
+                       : base ("Internal error")
+               {
+               }
+
+               public InternalErrorException (string message)
+                       : base (message)
+               {
+               }
+
+               public InternalErrorException (string message, params object[] args)
+                       : base (String.Format (message, args))
+               { }
+       }
+
+       /// <summary>
+       /// Handles #pragma warning
+       /// </summary>
+       public class WarningRegions {
+
+               abstract class PragmaCmd
+               {
+                       public int Line;
+
+                       protected PragmaCmd (int line)
+                       {
+                               Line = line;
+                       }
+
+                       public abstract bool IsEnabled (int code, bool previous);
+               }
+               
+               class Disable : PragmaCmd
+               {
+                       int code;
+                       public Disable (int line, int code)
+                               : base (line)
+                       {
+                               this.code = code;
+                       }
+
+                       public override bool IsEnabled (int code, bool previous)
+                       {
+                               return this.code == code ? false : previous;
+                       }
+               }
+
+               class DisableAll : PragmaCmd
+               {
+                       public DisableAll (int line)
+                               : base (line) {}
+
+                       public override bool IsEnabled(int code, bool previous)
+                       {
+                               return false;
+                       }
+               }
+
+               class Enable : PragmaCmd
+               {
+                       int code;
+                       public Enable (int line, int code)
+                               : base (line)
+                       {
+                               this.code = code;
+                       }
+
+                       public override bool IsEnabled(int code, bool previous)
+                       {
+                               return this.code == code ? true : previous;
+                       }
+               }
+
+               class EnableAll : PragmaCmd
+               {
+                       public EnableAll (int line)
+                               : base (line) {}
+
+                       public override bool IsEnabled(int code, bool previous)
+                       {
+                               return true;
+                       }
+               }
+
+
+               ArrayList regions = new ArrayList ();
+
+               public void WarningDisable (int line)
+               {
+                       regions.Add (new DisableAll (line));
+               }
+
+               public void WarningDisable (Location location, int code)
+               {
+                       if (CheckWarningCode (code, location))
+                               regions.Add (new Disable (location.Row, code));
+               }
+
+               public void WarningEnable (int line)
+               {
+                       regions.Add (new EnableAll (line));
+               }
+
+               public void WarningEnable (Location location, int code)
+               {
+                       if (CheckWarningCode (code, location))
+                               regions.Add (new Enable (location.Row, code));
+               }
+
+               public bool IsWarningEnabled (int code, int src_line)
+               {
+                       bool result = true;
+                       foreach (PragmaCmd pragma in regions) {
+                               if (src_line < pragma.Line)
+                                       break;
+
+                               result = pragma.IsEnabled (code, result);
+                       }
+                       return result;
+               }
+
+               static bool CheckWarningCode (int code, Location loc)
+               {
+                       if (Report.IsValidWarning (code))
+                               return true;
+
+                       Report.Warning (1691, 1, loc, "`{0}' is not a valid warning number", code.ToString ());
+                       return false;
+               }
+       }
+}