Implemented PipeSecurity. GetAccessControl, SetAccessControl, and ACL-containing...
[mono.git] / mcs / mcs / parameter.cs
index 8ff4815d4c61ecb51fdcfbd1d35ee58057b0afa6..365f876f0aa4f318f21cd34f114b7a1703dd8d66 100644 (file)
@@ -8,13 +8,21 @@
 //
 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
 // Copyright 2003-2008 Novell, Inc. 
+// Copyright 2011 Xamarin Inc
 //
 //
 using System;
+using System.Text;
+
+#if STATIC
+using MetaType = IKVM.Reflection.Type;
+using IKVM.Reflection;
+using IKVM.Reflection.Emit;
+#else
+using MetaType = System.Type;
 using System.Reflection;
 using System.Reflection.Emit;
-using System.Text;
-using System.Linq;
+#endif
 
 namespace Mono.CSharp {
 
@@ -110,34 +118,6 @@ namespace Mono.CSharp {
                }
        }
 
-       /// <summary>
-       /// Class for applying custom attributes on the implicit parameter type
-       /// of the 'set' method in properties, and the 'add' and 'remove' methods in events.
-       /// </summary>
-       /// 
-       // TODO: should use more code from Parameter.ApplyAttributeBuilder
-       public class ImplicitParameter : ParameterBase {
-               public ImplicitParameter (MethodBuilder mb)
-               {
-                       builder = mb.DefineParameter (1, ParameterAttributes.None, "value");                    
-               }
-
-               public override AttributeTargets AttributeTargets {
-                       get {
-                               return AttributeTargets.Parameter;
-                       }
-               }
-
-               /// <summary>
-               /// Is never called
-               /// </summary>
-               public override string[] ValidAttributeTargets {
-                       get {
-                               return null;
-                       }
-               }
-       }
-
        public class ImplicitLambdaParameter : Parameter
        {
                public ImplicitLambdaParameter (string name, Location loc)
@@ -174,7 +154,7 @@ namespace Mono.CSharp {
 
                        var ac = parameter_type as ArrayContainer;
                        if (ac == null || ac.Rank != 1) {
-                               ec.Compiler.Report.Error (225, Location, "The params parameter must be a single dimensional array");
+                               ec.Module.Compiler.Report.Error (225, Location, "The params parameter must be a single dimensional array");
                                return null;
                        }
 
@@ -229,20 +209,23 @@ namespace Mono.CSharp {
                [Flags]
                public enum Modifier : byte {
                        NONE    = 0,
-                       REF     = REFMASK | ISBYREF,
-                       OUT     = OUTMASK | ISBYREF,
-                       PARAMS  = 4,
-                       // This is a flag which says that it's either REF or OUT.
-                       ISBYREF = 8,
-                       REFMASK = 32,
-                       OUTMASK = 64,
-                       This    = 128
+                       PARAMS  = 1 << 0,
+                       REF = 1 << 1,
+                       OUT = 1 << 2,
+                       This = 1 << 3,
+                       CallerMemberName = 1 << 4,
+                       CallerLineNumber = 1 << 5,
+                       CallerFilePath = 1 << 6,
+
+                       RefOutMask = REF | OUT,
+                       ModifierMask = PARAMS | REF | OUT | This,
+                       CallerMask = CallerMemberName | CallerLineNumber | CallerFilePath
                }
 
-               static string[] attribute_targets = new string [] { "param" };
+               static readonly string[] attribute_targets = new string[] { "param" };
 
                FullNamedExpression texpr;
-               readonly Modifier modFlags;
+               Modifier modFlags;
                string name;
                Expression default_expr;
                protected TypeSpec parameter_type;
@@ -251,9 +234,8 @@ namespace Mono.CSharp {
                public bool HasAddressTaken;
 
                TemporaryVariableReference expr_tree_variable;
-               static TypeExpr parameter_expr_tree_type;
 
-               HoistedVariable hoisted_variant;
+               HoistedParameter hoisted_variant;
 
                public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
                {
@@ -268,25 +250,53 @@ namespace Mono.CSharp {
 
                #region Properties
 
-               public Expression DefaultValue {
+               public Expression DefaultExpression {
                        get {
                                return default_expr;
                        }
+               }
+
+               public DefaultParameterValueExpression DefaultValue {
+                       get {
+                               return default_expr as DefaultParameterValueExpression;
+                       }
                        set {
                                default_expr = value;
                        }
                }
 
+               Expression IParameterData.DefaultValue {
+                       get {
+                               var expr = default_expr as DefaultParameterValueExpression;
+                               return expr == null ? default_expr : expr.Child;
+                       }
+               }
+
+               bool HasOptionalExpression {
+                       get {
+                               return default_expr is DefaultParameterValueExpression;
+                       }
+               }
+
                public Location Location {
                        get {
                                return loc;
                        }
                }
 
+               public Modifier ParameterModifier {
+                       get {
+                               return modFlags;
+                       }
+               }
+
                public TypeSpec Type {
                        get {
                                return parameter_type;
                        }
+                       set {
+                               parameter_type = value;
+                       }
                }
 
                public FullNamedExpression TypeExpression  {
@@ -315,7 +325,7 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       if (a.Type == pa.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
+                       if (a.Type == pa.Out && (ModFlags & Modifier.REF) != 0 &&
                            !OptAttributes.Contains (pa.In)) {
                                a.Report.Error (662, a.Location,
                                        "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
@@ -324,37 +334,30 @@ namespace Mono.CSharp {
 
                        if (a.Type == pa.CLSCompliant) {
                                a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
-                       }
-
-                       if (HasDefaultValue && (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter)) {
-                               a.Report.Error (1745, a.Location,
-                                       "Cannot specify `{0}' attribute on optional parameter `{1}'",
-                                       TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
-                               return;
-                       }
-
-                       if (a.Type == pa.DefaultParameterValue) {
-                               TypeSpec arg_type;
-                               var c = a.GetParameterDefaultValue (out arg_type);
-                               if (c == null) {
-                                       if (parameter_type == TypeManager.object_type) {
-                                               a.Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
-                                                       arg_type.GetSignatureForError ());
-                                       } else {
-                                               a.Report.Error (1909, a.Location, "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
-                                                       parameter_type.GetSignatureForError ()); ;
-                                       }
+                       } else if (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter) {
+                               if (HasOptionalExpression) {
+                                       a.Report.Error (1745, a.Location,
+                                               "Cannot specify `{0}' attribute on optional parameter `{1}'",
+                                               TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
+                               }
 
+                               if (a.Type == pa.DefaultParameterValue)
                                        return;
+                       } else if (a.Type == pa.CallerMemberNameAttribute) {
+                               if ((modFlags & Modifier.CallerMemberName) == 0) {
+                                       a.Report.Error (4022, a.Location,
+                                               "The CallerMemberName attribute can only be applied to parameters with default value");
+                               }
+                       } else if (a.Type == pa.CallerLineNumberAttribute) {
+                               if ((modFlags & Modifier.CallerLineNumber) == 0) {
+                                       a.Report.Error (4020, a.Location,
+                                               "The CallerLineNumber attribute can only be applied to parameters with default value");
+                               }
+                       } else if (a.Type == pa.CallerFilePathAttribute) {
+                               if ((modFlags & Modifier.CallerFilePath) == 0) {
+                                       a.Report.Error (4021, a.Location,
+                                               "The CallerFilePath attribute can only be applied to parameters with default value");
                                }
-
-                               if (arg_type == parameter_type || parameter_type == TypeManager.object_type || 
-                                       (c.IsNull && TypeManager.IsReferenceType (parameter_type) && !TypeManager.IsGenericParameter (parameter_type)))
-                                       builder.SetConstant (c.GetValue ());
-                               else
-                                       a.Report.Error (1908, a.Location, "The type of the default value should match the type of the parameter");
-
-                               return;
                        }
 
                        base.ApplyAttributeBuilder (a, ctor, cdata, pa);
@@ -368,11 +371,6 @@ namespace Mono.CSharp {
                        return member.IsAccessibleAs (parameter_type);
                }
 
-               public static void Reset ()
-               {
-                       parameter_expr_tree_type = null;
-               }
-
                // <summary>
                //   Resolve is used in method definitions
                // </summary>
@@ -384,126 +382,160 @@ namespace Mono.CSharp {
                        if (attributes != null)
                                attributes.AttachTo (this, rc);
 
-                       var expr = texpr.ResolveAsTypeTerminal (rc, false);
-                       if (expr == null)
+                       parameter_type = texpr.ResolveAsType (rc);
+                       if (parameter_type == null)
                                return null;
 
                        this.idx = index;
-                       texpr = expr;
-                       parameter_type = texpr.Type;
-       
-                       if ((modFlags & Parameter.Modifier.ISBYREF) != 0 &&
-                               TypeManager.IsSpecialType (parameter_type)) {
-                               rc.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
+
+                       if ((modFlags & Parameter.Modifier.RefOutMask) != 0 && parameter_type.IsSpecialRuntimeType) {
+                               rc.Module.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
                                        GetSignatureForError ());
                                return null;
                        }
 
                        TypeManager.CheckTypeVariance (parameter_type,
-                               (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant,
+                               (modFlags & Parameter.Modifier.RefOutMask) != 0 ? Variance.None : Variance.Contravariant,
                                rc);
 
                        if (parameter_type.IsStatic) {
-                               rc.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
+                               rc.Module.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
                                        texpr.GetSignatureForError ());
                                return parameter_type;
                        }
 
-                       if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || parameter_type == InternalType.Dynamic)) {
-                               rc.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
+                       if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)) {
+                               rc.Module.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
                                        TypeManager.CSharpName (parameter_type));
                        }
 
                        return parameter_type;
                }
 
+               void ResolveCallerAttributes (ResolveContext rc)
+               {
+                       var pa = rc.Module.PredefinedAttributes;
+                       TypeSpec caller_type;
+
+                       foreach (var attr in attributes.Attrs) {
+                               var atype = attr.ResolveType ();
+                               if (atype == null)
+                                       continue;
+
+                               if (atype == pa.CallerMemberNameAttribute) {
+                                       caller_type = rc.BuiltinTypes.String;
+                                       if (caller_type != parameter_type && !Convert.ImplicitReferenceConversionExists (caller_type, parameter_type)) {
+                                               rc.Report.Error (4019, attr.Location,
+                                                       "The CallerMemberName attribute cannot be applied because there is no standard conversion from `{0}' to `{1}'",
+                                                       caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ());
+                                       }
+
+                                       modFlags |= Modifier.CallerMemberName;
+                                       continue;
+                               }
+
+                               if (atype == pa.CallerLineNumberAttribute) {
+                                       caller_type = rc.BuiltinTypes.Int;
+                                       if (caller_type != parameter_type && !Convert.ImplicitNumericConversionExists (caller_type, parameter_type)) {
+                                               rc.Report.Error (4017, attr.Location,
+                                                       "The CallerMemberName attribute cannot be applied because there is no standard conversion from `{0}' to `{1}'",
+                                                       caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ());
+                                       }
+
+                                       modFlags |= Modifier.CallerLineNumber;
+                                       continue;
+                               }
+
+                               if (atype == pa.CallerFilePathAttribute) {
+                                       caller_type = rc.BuiltinTypes.String;
+                                       if (caller_type != parameter_type && !Convert.ImplicitReferenceConversionExists (caller_type, parameter_type)) {
+                                               rc.Report.Error (4018, attr.Location,
+                                                       "The CallerFilePath attribute cannot be applied because there is no standard conversion from `{0}' to `{1}'",
+                                                       caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ());
+                                       }
+
+                                       modFlags |= Modifier.CallerFilePath;
+                                       continue;
+                               }
+                       }
+               }
+
                public void ResolveDefaultValue (ResolveContext rc)
                {
                        //
                        // Default value was specified using an expression
                        //
                        if (default_expr != null) {
-                               default_expr = ResolveDefaultExpression (rc);
+                               ((DefaultParameterValueExpression)default_expr).Resolve (rc, this);
+                               if (attributes != null)
+                                       ResolveCallerAttributes (rc);
+
                                return;
                        }
 
                        if (attributes == null)
                                return;
-                       
-                       var pa = attributes.Search (rc.Compiler.PredefinedAttributes.OptionalParameter);
-                       if (pa == null)
-                               return;
-
-                       //
-                       // Default value was specified using an attribute
-                       //
-                       attributes.Attrs.Remove (pa);
-
-                       TypeSpec expr_type = null;
-                       pa = attributes.Search (rc.Compiler.PredefinedAttributes.DefaultParameterValue);
-                       if (pa != null) {
-                               attributes.Attrs.Remove (pa);
-                               default_expr = pa.GetParameterDefaultValue (out expr_type);
-                       } else {
-                               default_expr = EmptyExpression.MissingValue;
-                       }
-
-                       if (default_expr == null) {
-                               if (expr_type == null)
-                                       expr_type = parameter_type;
-
-                               default_expr = new DefaultValueExpression (new TypeExpression (expr_type, Location), Location);
-                       }
 
-                       default_expr = default_expr.Resolve (rc);
-               }
-
-               Expression ResolveDefaultExpression (ResolveContext rc)
-               {
-                       default_expr = default_expr.Resolve (rc);
-                       if (default_expr == null)
-                               return null;
+                       var pa = rc.Module.PredefinedAttributes;
+                       var def_attr = attributes.Search (pa.DefaultParameterValue);
+                       if (def_attr != null) {
+                               if (def_attr.Resolve () == null)
+                                       return;
 
-                       if (!(default_expr is Constant || default_expr is DefaultValueExpression || (default_expr is New && ((New)default_expr).IsDefaultStruct))) {
-                               rc.Compiler.Report.Error (1736, default_expr.Location,
-                                       "The expression being assigned to optional parameter `{0}' must be a constant or default value",
-                                       Name);
+                               var default_expr_attr = def_attr.GetParameterDefaultValue ();
+                               if (default_expr_attr == null)
+                                       return;
 
-                               return null;
-                       }
+                               var dpa_rc = def_attr.CreateResolveContext ();
+                               default_expr = default_expr_attr.Resolve (dpa_rc);
 
-                       if (default_expr.Type == parameter_type)
-                               return default_expr;
+                               if (default_expr is BoxedCast)
+                                       default_expr = ((BoxedCast) default_expr).Child;
 
-                       var res = Convert.ImplicitConversionStandard (rc, default_expr, parameter_type, default_expr.Location);
-                       if (res != null) {
-                               if (TypeManager.IsNullableType (parameter_type) && res is Nullable.Wrap) {
-                                       Nullable.Wrap wrap = (Nullable.Wrap) res;
-                                       res = wrap.Child;
-                                       if (!(res is Constant)) {
-                                               rc.Compiler.Report.Error (1770, default_expr.Location,
-                                                       "The expression being assigned to nullable optional parameter `{0}' must be default value",
-                                                       Name);
-                                               return null;
+                               Constant c = default_expr as Constant;
+                               if (c == null) {
+                                       if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
+                                               rc.Report.Error (1910, default_expr.Location,
+                                                       "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
+                                                       default_expr.Type.GetSignatureForError ());
+                                       } else {
+                                               rc.Report.Error (1909, default_expr.Location,
+                                                       "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
+                                                       default_expr.Type.GetSignatureForError ()); ;
                                        }
-                               }
 
-                               if (!default_expr.IsNull && TypeManager.IsReferenceType (parameter_type) && parameter_type != TypeManager.string_type) {
-                                       rc.Compiler.Report.Error (1763, default_expr.Location,
-                                               "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
-                                               Name, GetSignatureForError ());
+                                       default_expr = null;
+                                       return;
+                               }
 
-                                       return null;
+                               if (TypeSpecComparer.IsEqual (default_expr.Type, parameter_type) ||
+                                       (default_expr is NullConstant && TypeSpec.IsReferenceType (parameter_type) && !parameter_type.IsGenericParameter) ||
+                                       parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
+                                       return;
                                }
 
-                               return res;
+                               //
+                               // LAMESPEC: Some really weird csc behaviour which we have to mimic
+                               // User operators returning same type as parameter type are considered
+                               // valid for this attribute only
+                               //
+                               // struct S { public static implicit operator S (int i) {} }
+                               //
+                               // void M ([DefaultParameterValue (3)]S s)
+                               //
+                               var expr = Convert.ImplicitUserConversion (dpa_rc, default_expr, parameter_type, loc);
+                               if (expr != null && TypeSpecComparer.IsEqual (expr.Type, parameter_type)) {
+                                       return;
+                               }
+                               
+                               rc.Report.Error (1908, default_expr.Location, "The type of the default value should match the type of the parameter");
+                               return;
                        }
 
-                       rc.Compiler.Report.Error (1750, Location,
-                               "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
-                               TypeManager.CSharpName (default_expr.Type), GetSignatureForError ());
-
-                       return null;
+                       var opt_attr = attributes.Search (pa.OptionalParameter);
+                       if (opt_attr != null) {
+                               default_expr = EmptyExpression.MissingValue;
+                       }
                }
 
                public bool HasDefaultValue {
@@ -517,7 +549,7 @@ namespace Mono.CSharp {
                //
                // Hoisted parameter variant
                //
-               public HoistedVariable HoistedVariant {
+               public HoistedParameter HoistedVariant {
                        get {
                                return hoisted_variant;
                        }
@@ -535,17 +567,17 @@ namespace Mono.CSharp {
                        set { name = value; }
                }
 
-               ParameterAttributes Attributes {
-                       get { return ParametersCompiled.GetParameterAttribute (modFlags) |
-                               (HasDefaultValue ? ParameterAttributes.Optional : ParameterAttributes.None); }
-               }
-
                public override AttributeTargets AttributeTargets {
                        get {
                                return AttributeTargets.Parameter;
                        }
                }
 
+               public void Error_DuplicateName (Report r)
+               {
+                       r.Error (100, Location, "The parameter name `{0}' is a duplicate", Name);
+               }
+
                public virtual string GetSignatureForError ()
                {
                        string type_name;
@@ -582,7 +614,7 @@ namespace Mono.CSharp {
                        if (parameter_type.IsCLSCompliant ())
                                return;
 
-                       ctx.Compiler.Report.Warning (3001, 1, Location,
+                       ctx.Module.Compiler.Report.Warning (3001, 1, Location,
                                "Argument type `{0}' is not CLS-compliant", parameter_type.GetSignatureForError ());
                }
 
@@ -591,10 +623,14 @@ namespace Mono.CSharp {
                        if (builder != null)
                                throw new InternalErrorException ("builder already exists");
 
+                       var pattrs = ParametersCompiled.GetParameterAttribute (modFlags);
+                       if (HasOptionalExpression)
+                               pattrs |= ParameterAttributes.Optional;
+
                        if (mb == null)
-                               builder = cb.DefineParameter (index, Attributes, Name);
+                               builder = cb.DefineParameter (index, pattrs, Name);
                        else
-                               builder = mb.DefineParameter (index, Attributes, Name);
+                               builder = mb.DefineParameter (index, pattrs, Name);
 
                        if (OptAttributes != null)
                                OptAttributes.Emit ();
@@ -604,21 +640,29 @@ namespace Mono.CSharp {
                                // Emit constant values for true constants only, the other
                                // constant-like expressions will rely on default value expression
                                //
-                               Constant c = default_expr as Constant;
+                               var def_value = DefaultValue;
+                               Constant c = def_value != null ? def_value.Child as Constant : default_expr as Constant;
                                if (c != null) {
-                                       if (default_expr.Type == TypeManager.decimal_type) {
-                                               builder.SetCustomAttribute (Const.CreateDecimalConstantAttribute (c, pa));
+                                       if (c.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
+                                               pa.DecimalConstant.EmitAttribute (builder, (decimal) c.GetValue (), c.Location);
                                        } else {
-                                               builder.SetConstant (c.GetTypedValue ());
+                                               builder.SetConstant (c.GetValue ());
                                        }
+                               } else if (default_expr.Type.IsStruct) {
+                                       //
+                                       // Handles special case where default expression is used with value-type
+                                       //
+                                       // void Foo (S s = default (S)) {}
+                                       //
+                                       builder.SetConstant (null);
                                }
                        }
 
                        if (parameter_type != null) {
-                               if (parameter_type == InternalType.Dynamic) {
+                               if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
                                        pa.Dynamic.EmitAttribute (builder);
                                } else if (parameter_type.HasDynamicElement) {
-                                       pa.Dynamic.EmitAttribute (builder, parameter_type);
+                                       pa.Dynamic.EmitAttribute (builder, parameter_type, Location);
                                }
                        }
                }
@@ -634,56 +678,35 @@ namespace Mono.CSharp {
 
                public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec)
                {
-                       if ((modFlags & Modifier.ISBYREF) != 0)
+                       if ((modFlags & Modifier.RefOutMask) != 0)
                                ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
 
                        expr_tree_variable = TemporaryVariableReference.Create (ResolveParameterExpressionType (ec, Location).Type, ec.CurrentBlock.ParametersBlock, Location);
                        expr_tree_variable = (TemporaryVariableReference) expr_tree_variable.Resolve (ec);
 
                        Arguments arguments = new Arguments (2);
-                       arguments.Add (new Argument (new TypeOf (
-                               new TypeExpression (parameter_type, Location), Location)));
-                       arguments.Add (new Argument (new StringConstant (Name, Location)));
+                       arguments.Add (new Argument (new TypeOf (parameter_type, Location)));
+                       arguments.Add (new Argument (new StringConstant (ec.BuiltinTypes, Name, Location)));
                        return new SimpleAssign (ExpressionTreeVariableReference (),
                                Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location));
                }
 
                public void Emit (EmitContext ec)
                {
-                       int arg_idx = idx;
-                       if (!ec.IsStatic)
-                               arg_idx++;
-
-                       ParameterReference.EmitLdArg (ec, arg_idx);
+                       ec.EmitArgumentLoad (idx);
                }
 
                public void EmitAssign (EmitContext ec)
                {
-                       int arg_idx = idx;
-                       if (!ec.IsStatic)
-                               arg_idx++;
-
-                       if (arg_idx <= 255)
-                               ec.Emit (OpCodes.Starg_S, (byte) arg_idx);
-                       else
-                               ec.Emit (OpCodes.Starg, arg_idx);
+                       ec.EmitArgumentStore (idx);
                }
 
                public void EmitAddressOf (EmitContext ec)
                {
-                       int arg_idx = idx;
-
-                       if (!ec.IsStatic)
-                               arg_idx++;
-
-                       bool is_ref = (ModFlags & Modifier.ISBYREF) != 0;
-                       if (is_ref) {
-                               ParameterReference.EmitLdArg (ec, arg_idx);
+                       if ((ModFlags & Modifier.RefOutMask) != 0) {
+                               ec.EmitArgumentLoad (idx);
                        } else {
-                               if (arg_idx <= 255)
-                                       ec.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
-                               else
-                                       ec.Emit (OpCodes.Ldarga, arg_idx);
+                               ec.EmitArgumentAddress (idx);
                        }
                }
 
@@ -697,19 +720,8 @@ namespace Mono.CSharp {
                //
                public static TypeExpr ResolveParameterExpressionType (IMemberContext ec, Location location)
                {
-                       if (parameter_expr_tree_type != null)
-                               return parameter_expr_tree_type;
-
-                       TypeSpec p_type = TypeManager.parameter_expression_type;
-                       if (p_type == null) {
-                               p_type = TypeManager.CoreLookupType (ec.Compiler, "System.Linq.Expressions", "ParameterExpression", MemberKind.Class, true);
-                               TypeManager.parameter_expression_type = p_type;
-                       }
-
-                       parameter_expr_tree_type = new TypeExpression (p_type, location).
-                               ResolveAsTypeTerminal (ec, false);
-
-                       return parameter_expr_tree_type;
+                       TypeSpec p_type = ec.Module.PredefinedTypes.ParameterExpression.Resolve ();
+                       return new TypeExpression (p_type, location);
                }
 
                public void Warning_UselessOptionalParameter (Report Report)
@@ -756,7 +768,7 @@ namespace Mono.CSharp {
                }
 
                public Parameter.Modifier ModFlags {
-                       get { return modifiers & ~Parameter.Modifier.This; }
+                       get { return modifiers; }
                }
 
                public string Name {
@@ -805,30 +817,30 @@ namespace Mono.CSharp {
 
                public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
                {
-                       return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
+                       return (modFlags & Parameter.Modifier.OUT) != 0 ?
                                ParameterAttributes.Out : ParameterAttributes.None;
                }
 
                // Very expensive operation
-               public Type[] GetMetaInfo ()
+               public MetaType[] GetMetaInfo ()
                {
-                       Type[] types;
+                       MetaType[] types;
                        if (has_arglist) {
                                if (Count == 1)
-                                       return Type.EmptyTypes;
+                                       return MetaType.EmptyTypes;
 
-                               types = new Type [Count - 1];
+                               types = new MetaType[Count - 1];
                        } else {
                                if (Count == 0)
-                                       return Type.EmptyTypes;
+                                       return MetaType.EmptyTypes;
 
-                               types = new Type [Count];
+                               types = new MetaType[Count];
                        }
 
                        for (int i = 0; i < types.Length; ++i) {
                                types[i] = Types[i].GetMetaInfo ();
 
-                               if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0)
+                               if ((FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) == 0)
                                        continue;
 
                                // TODO MemberCache: Should go to MetaInfo getter
@@ -851,6 +863,26 @@ namespace Mono.CSharp {
                        return -1;
                }
 
+               public string GetSignatureForDocumentation ()
+               {
+                       if (IsEmpty)
+                               return string.Empty;
+
+                       StringBuilder sb = new StringBuilder ("(");
+                       for (int i = 0; i < Count; ++i) {
+                               if (i != 0)
+                                       sb.Append (",");
+
+                               sb.Append (types [i].GetSignatureForDocumentation ());
+
+                               if ((parameters[i].ModFlags & Parameter.Modifier.RefOutMask) != 0)
+                                       sb.Append ("@");
+                       }
+                       sb.Append (")");
+
+                       return sb.ToString ();
+               }
+
                public string GetSignatureForError ()
                {
                        return GetSignatureForError ("(", ")", Count);
@@ -1024,7 +1056,7 @@ namespace Mono.CSharp {
                // TODO: This does not fit here, it should go to different version of AParametersCollection
                // as the underlying type is not Parameter and some methods will fail to cast
                //
-               public static AParametersCollection CreateFullyResolved (TypeSpec[] types)
+               public static AParametersCollection CreateFullyResolved (params TypeSpec[] types)
                {
                        var pd = new ParameterData [types.Length];
                        for (int i = 0; i < pd.Length; ++i)
@@ -1040,6 +1072,17 @@ namespace Mono.CSharp {
                                null);
                }
 
+               public void CheckConstraints (IMemberContext mc)
+               {
+                       foreach (Parameter p in parameters) {
+                               //
+                               // It's null for compiler generated types or special types like __arglist
+                               //
+                               if (p.TypeExpression != null)
+                                       ConstraintChecker.Check (mc, p.Type, p.TypeExpression.Location);
+                       }
+               }
+
                //
                // Returns non-zero value for equal CLS parameter signatures
                //
@@ -1051,8 +1094,7 @@ namespace Mono.CSharp {
                                var a_type = a.Types[i];
                                var b_type = b.Types[i];
                                if (TypeSpecComparer.Override.IsEqual (a_type, b_type)) {
-                                       const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
-                                       if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
+                                       if ((a.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (b.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask))
                                                res |= 1;
 
                                        continue;
@@ -1128,6 +1170,20 @@ namespace Mono.CSharp {
                        return parameters;
                }
 
+               //
+               // Parameters checks for members which don't have a block
+               //
+               public void CheckParameters (MemberCore member)
+               {
+                       for (int i = 0; i < parameters.Length; ++i) {
+                               var name = parameters[i].Name;
+                               for (int ii = i + 1; ii < parameters.Length; ++ii) {
+                                       if (parameters[ii].Name == name)
+                                               this[ii].Error_DuplicateName (member.Compiler.Report);
+                               }
+                       }
+               }
+
                public bool Resolve (IMemberContext ec)
                {
                        if (types != null)
@@ -1153,16 +1209,18 @@ namespace Mono.CSharp {
 
                public void ResolveDefaultValues (MemberCore m)
                {
-                       var count = parameters.Length;
+                       ResolveContext rc = null;
+                       for (int i = 0; i < parameters.Length; ++i) {
+                               Parameter p = (Parameter) parameters [i];
 
-                       //
-                       // Try not to enter default values resolution if there are not any
-                       //
-                       if (parameters[count - 1].HasDefaultValue || (HasParams && count > 1 && parameters[count - 2].HasDefaultValue) ||
-                               ((Parameter) parameters[count - 1]).OptAttributes != null) {
-                               var rc = new ResolveContext (m);
-                               for (int i = 0; i < count; ++i) {
-                                       this [i].ResolveDefaultValue (rc);
+                               //
+                               // Try not to enter default values resolution if there are is not any default value possible
+                               //
+                               if (p.HasDefaultValue || p.OptAttributes != null) {
+                                       if (rc == null)
+                                               rc = new ResolveContext (m);
+
+                                       p.ResolveDefaultValue (rc);
                                }
                        }
                }
@@ -1176,7 +1234,7 @@ namespace Mono.CSharp {
 
                        MethodBuilder mb = builder as MethodBuilder;
                        ConstructorBuilder cb = builder as ConstructorBuilder;
-                       var pa = mc.Compiler.PredefinedAttributes;
+                       var pa = mc.Module.PredefinedAttributes;
 
                        for (int i = 0; i < Count; i++) {
                                this [i].ApplyAttributes (mb, cb, i + 1, pa);
@@ -1201,7 +1259,7 @@ namespace Mono.CSharp {
                                // Each parameter expression is stored to local variable
                                // to save some memory when referenced later.
                                //
-                               StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
+                               StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec), Location.Null);
                                if (se.Resolve (ec)) {
                                        ec.CurrentBlock.AddScopeStatement (new TemporaryVariableReference.Declarator (p.ExpressionTreeVariableReference ()));
                                        ec.CurrentBlock.AddScopeStatement (se);
@@ -1226,4 +1284,79 @@ namespace Mono.CSharp {
                        return p;
                }
        }
+
+       //
+       // Default parameter value expression. We need this wrapper to handle
+       // default parameter values of folded constants (e.g. indexer parameters).
+       // The expression is resolved only once but applied to two methods which
+       // both share reference to this expression and we ensure that resolving
+       // this expression always returns same instance
+       //
+       public class DefaultParameterValueExpression : CompositeExpression
+       {
+               public DefaultParameterValueExpression (Expression expr)
+                       : base (expr)
+               {
+               }
+
+               protected override Expression DoResolve (ResolveContext rc)
+               {
+                       return base.DoResolve (rc);
+               }
+
+               public void Resolve (ResolveContext rc, Parameter p)
+               {
+                       var expr = Resolve (rc);
+                       if (expr == null)
+                               return;
+
+                       expr = Child;
+
+                       if (!(expr is Constant || expr is DefaultValueExpression || (expr is New && ((New) expr).IsDefaultStruct))) {
+                               rc.Report.Error (1736, Location,
+                                       "The expression being assigned to optional parameter `{0}' must be a constant or default value",
+                                       p.Name);
+
+                               return;
+                       }
+
+                       var parameter_type = p.Type;
+                       if (type == parameter_type)
+                               return;
+
+                       var res = Convert.ImplicitConversionStandard (rc, expr, parameter_type, Location);
+                       if (res != null) {
+                               if (parameter_type.IsNullableType && res is Nullable.Wrap) {
+                                       Nullable.Wrap wrap = (Nullable.Wrap) res;
+                                       res = wrap.Child;
+                                       if (!(res is Constant)) {
+                                               rc.Report.Error (1770, Location,
+                                                       "The expression being assigned to nullable optional parameter `{0}' must be default value",
+                                                       p.Name);
+                                               return;
+                                       }
+                               }
+
+                               if (!expr.IsNull && TypeSpec.IsReferenceType (parameter_type) && parameter_type.BuiltinType != BuiltinTypeSpec.Type.String) {
+                                       rc.Report.Error (1763, Location,
+                                               "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
+                                               p.Name, parameter_type.GetSignatureForError ());
+
+                                       return;
+                               }
+
+                               this.expr = res;
+                               return;
+                       }
+
+                       rc.Report.Error (1750, Location,
+                               "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
+                               type.GetSignatureForError (), parameter_type.GetSignatureForError ());
+               }
+               
+               public override object Accept (StructuralVisitor visitor)
+               {
+                       return visitor.Visit (this);
+               }
+       }
 }