X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fparameter.cs;h=a6c5c63da7c0b41811e27bc1af73a1f09de97f86;hb=0c2bb8157f43826a57c39b863a1d67e3aef1b7b2;hp=1630f78b4b6cdc01ef646694841d8a386592facd;hpb=2058902bc891bb7b09977062256a11dc38bad058;p=mono.git diff --git a/mcs/mcs/parameter.cs b/mcs/mcs/parameter.cs index 1630f78b4b6..a6c5c63da7c 100644 --- a/mcs/mcs/parameter.cs +++ b/mcs/mcs/parameter.cs @@ -30,10 +30,10 @@ namespace Mono.CSharp { { } - public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb) + public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa) { #if !NET_2_0 - if (a.Type == TypeManager.marshal_as_attr_type) { + if (a.Type == pa.MarshalAs) { UnmanagedMarshal marshal = a.GetMarshal (this); if (marshal != null) { builder.SetMarshal (marshal); @@ -70,9 +70,9 @@ namespace Mono.CSharp { } } - public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb) + public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa) { - if (a.Type == TypeManager.cls_compliant_attribute_type) { + if (a.Type == pa.CLSCompliant) { Report.Warning (3023, 1, a.Location, "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead"); } @@ -80,7 +80,7 @@ namespace Mono.CSharp { if (builder == null) return; - base.ApplyAttributeBuilder (a, cb); + base.ApplyAttributeBuilder (a, cb, pa); } public override AttributeTargets AttributeTargets { @@ -115,7 +115,7 @@ namespace Mono.CSharp { public ImplicitParameter (MethodBuilder mb): base (null) { - builder = mb.DefineParameter (1, ParameterAttributes.None, ""); + builder = mb.DefineParameter (1, ParameterAttributes.None, "value"); } public override AttributeTargets AttributeTargets { @@ -183,21 +183,7 @@ namespace Mono.CSharp { public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index) { base.ApplyAttributes (mb, cb, index); - - CustomAttributeBuilder ca = TypeManager.param_array_attr; - if (ca == null) { - ConstructorInfo ci = TypeManager.GetPredefinedConstructor (TypeManager.param_array_type, Location, Type.EmptyTypes); - if (ci == null) - return; - - ca = new CustomAttributeBuilder (ci, new object [0]); - if (ca == null) - return; - - TypeManager.param_array_attr = ca; - } - - builder.SetCustomAttribute (ca); + PredefinedAttributes.Get.ParamArray.EmitAttribute (builder, Location); } } @@ -231,7 +217,9 @@ namespace Mono.CSharp { public interface IParameterData { + Expression DefaultValue { get; } bool HasExtensionMethodModifier { get; } + bool HasDefaultValue { get; } Parameter.Modifier ModFlags { get; } string Name { get; } } @@ -259,6 +247,7 @@ namespace Mono.CSharp { protected FullNamedExpression TypeName; readonly Modifier modFlags; string name; + Expression default_expr; protected Type parameter_type; public readonly Location Location; int idx; @@ -282,31 +271,37 @@ namespace Mono.CSharp { TypeName = type; } - public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb) + public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa) { - if (a.Type == TypeManager.in_attribute_type && ModFlags == Modifier.OUT) { + if (a.Type == pa.In && ModFlags == Modifier.OUT) { Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute"); return; } - if (a.Type == TypeManager.param_array_type) { + if (a.Type == pa.ParamArray) { Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead"); return; } - if (a.Type == TypeManager.out_attribute_type && (ModFlags & Modifier.REF) == Modifier.REF && - TypeManager.in_attribute_type != null && !OptAttributes.Contains (TypeManager.in_attribute_type)) { + if (a.Type == PredefinedAttributes.Get.Out && (ModFlags & Modifier.REF) == Modifier.REF && + !OptAttributes.Contains (pa.In)) { Report.Error (662, a.Location, "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither"); return; } - if (a.Type == TypeManager.cls_compliant_attribute_type) { + if (a.Type == pa.CLSCompliant) { Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead"); } - // TypeManager.default_parameter_value_attribute_type is null if !NET_2_0, or if System.dll is not referenced - if (a.Type == TypeManager.default_parameter_value_attribute_type) { + if (HasDefaultValue && (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter)) { + 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) { object val = a.GetParameterDefaultValue (); if (val != null) { Type t = val.GetType (); @@ -315,10 +310,10 @@ namespace Mono.CSharp { if (!t.IsArray) t = TypeManager.type_type; - Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultValue attribute", + Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute", TypeManager.CSharpName (t)); } else { - Report.Error (1909, a.Location, "The DefaultValue attribute is not applicable on parameters of type `{0}'", + Report.Error (1909, a.Location, "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'", TypeManager.CSharpName (parameter_type)); ; } return; @@ -334,7 +329,7 @@ namespace Mono.CSharp { return; } - base.ApplyAttributeBuilder (a, cb); + base.ApplyAttributeBuilder (a, cb, pa); } public virtual bool CheckAccessibility (InterfaceMemberBase member) @@ -354,20 +349,54 @@ namespace Mono.CSharp { // // Resolve is used in method definitions // - public virtual Type Resolve (IResolveContext ec) + public virtual Type Resolve (IResolveContext rc) { // HACK: to resolve attributes correctly - this.resolve_context = ec; + this.resolve_context = rc; if (parameter_type != null) return parameter_type; - TypeExpr texpr = TypeName.ResolveAsTypeTerminal (ec, false); + TypeExpr texpr = TypeName.ResolveAsTypeTerminal (rc, false); if (texpr == null) return null; parameter_type = texpr.Type; + // Ignore all checks for dummy members + AbstractPropertyEventMethod pem = rc as AbstractPropertyEventMethod; + if (pem != null && pem.IsDummy) + return parameter_type; + + if (default_expr != null) { + EmitContext ec = new EmitContext (rc, rc.GenericDeclContainer, Location, null, parameter_type, 0); + default_expr = default_expr.Resolve (ec); + if (default_expr != null) { + Constant value = default_expr as Constant; + if (value == null) { + if (default_expr != null && !(default_expr is DefaultValueExpression)) { + Report.Error (1736, default_expr.Location, "The expression being assigned to optional parameter `{0}' must be constant", + Name); + default_expr = null; + } + } else { + Constant c = value.ConvertImplicitly (parameter_type); + if (c == null) { + if (parameter_type == TypeManager.object_type) { + Report.Error (1763, Location, + "Optional parameter `{0}' of type `{1}' can only be initialized with `null'", + Name, GetSignatureForError ()); + } else { + Report.Error (1750, Location, + "Optional parameter value `{0}' cannot be converted to parameter type `{1}'", + value.GetValue (), GetSignatureForError ()); + } + default_expr = null; + } + } + } + } + if ((modFlags & Parameter.Modifier.ISBYREF) != 0 && TypeManager.IsSpecialType (parameter_type)) { Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'", @@ -375,12 +404,12 @@ namespace Mono.CSharp { return null; } -#if GMCS_SOURCE - TypeParameterExpr tparam = texpr as TypeParameterExpr; - if (tparam != null) { + TypeManager.CheckTypeVariance (parameter_type, + (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant, + rc as MemberCore); + + if (texpr is TypeParameterExpr) return parameter_type; - } -#endif if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) { Report.Error (721, Location, "`{0}': static types cannot be used as parameters", @@ -401,6 +430,10 @@ namespace Mono.CSharp { this.idx = idx; } + public bool HasDefaultValue { + get { return default_expr != null; } + } + public bool HasExtensionMethodModifier { get { return (modFlags & Modifier.This) != 0; } } @@ -415,7 +448,8 @@ namespace Mono.CSharp { } ParameterAttributes Attributes { - get { return Parameters.GetParameterAttribute (modFlags); } + get { return ParametersCompiled.GetParameterAttribute (modFlags) | + (HasDefaultValue ? ParameterAttributes.Optional : ParameterAttributes.None); } } public override AttributeTargets AttributeTargets { @@ -472,6 +506,21 @@ namespace Mono.CSharp { if (OptAttributes != null) OptAttributes.Emit (); + + if (HasDefaultValue) { + // + // Emit constant values for true constants only, the other + // constant-like expressions will rely on default value expression + // + Constant c = default_expr as Constant; + if (c != null) { + if (default_expr.Type == TypeManager.decimal_type) { + builder.SetCustomAttribute (Const.CreateDecimalConstantAttribute (c)); + } else { + builder.SetConstant (c.GetValue ()); + } + } + } } public override string[] ValidAttributeTargets { @@ -493,6 +542,11 @@ namespace Mono.CSharp { public ExpressionStatement CreateExpressionTreeVariable (EmitContext ec) { + // + // A parameter is not hoisted when used directly as ET + // + HoistedVariableReference = null; + if ((modFlags & Modifier.ISBYREF) != 0) Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier"); @@ -511,6 +565,11 @@ namespace Mono.CSharp { Expression.CreateExpressionFactoryCall ("Parameter", null, arguments, Location)); } + public Expression DefaultValue { + get { return default_expr; } + set { default_expr = value; } + } + public void Emit (EmitContext ec) { int arg_idx = idx; @@ -541,10 +600,7 @@ namespace Mono.CSharp { bool is_ref = (ModFlags & Modifier.ISBYREF) != 0; if (is_ref) { - if (arg_idx <= 255) - ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx); - else - ec.ig.Emit (OpCodes.Ldarg, arg_idx); + ParameterReference.EmitLdArg (ec.ig, arg_idx); } else { if (arg_idx <= 255) ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx); @@ -577,6 +633,13 @@ namespace Mono.CSharp { return parameter_expr_tree_type; } + + public void Warning_UselessOptionalParameter () + { + Report.Warning (1066, 1, Location, + "The default value specified for optional parameter `{0}' will never be used", + Name); + } } // @@ -586,6 +649,7 @@ namespace Mono.CSharp { { readonly string name; readonly Parameter.Modifier modifiers; + readonly Expression default_value; public ParameterData (string name, Parameter.Modifier modifiers) { @@ -593,12 +657,26 @@ namespace Mono.CSharp { this.modifiers = modifiers; } + public ParameterData (string name, Parameter.Modifier modifiers, Expression defaultValue) + : this (name, modifiers) + { + this.default_value = defaultValue; + } + #region IParameterData Members + public Expression DefaultValue { + get { return default_value; } + } + public bool HasExtensionMethodModifier { get { return (modifiers & Parameter.Modifier.This) != 0; } } + public bool HasDefaultValue { + get { return default_value != null; } + } + public Parameter.Modifier ModFlags { get { return modifiers & ~Parameter.Modifier.This; } } @@ -762,9 +840,9 @@ namespace Mono.CSharp { // // A collection of imported or resolved parameters // - public class ParametersCollection : AParametersCollection + public class ParametersImported : AParametersCollection { - ParametersCollection (AParametersCollection param, Type[] types) + ParametersImported (AParametersCollection param, Type[] types) { this.parameters = param.FixedParameters; this.types = types; @@ -772,7 +850,7 @@ namespace Mono.CSharp { has_params = param.HasParams; } - ParametersCollection (IParameterData [] parameters, Type [] types, MethodBase method, bool hasParams) + ParametersImported (IParameterData [] parameters, Type [] types, MethodBase method, bool hasParams) { this.parameters = parameters; this.types = types; @@ -788,7 +866,7 @@ namespace Mono.CSharp { has_params = hasParams; } - public ParametersCollection (IParameterData [] param, Type[] types) + public ParametersImported (IParameterData [] param, Type[] types) { this.parameters = param; this.types = types; @@ -817,7 +895,7 @@ namespace Mono.CSharp { types [i] = TypeManager.TypeToCoreType (t); } - return new ParametersCollection (param, types); + return new ParametersImported (param, types); } // @@ -827,19 +905,22 @@ namespace Mono.CSharp { { if (pi.Length == 0) { if (method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0) - return new ParametersCollection (new IParameterData [0], Type.EmptyTypes, method, false); + return new ParametersImported (new IParameterData [0], Type.EmptyTypes, method, false); - return Parameters.EmptyReadOnlyParameters; + return ParametersCompiled.EmptyReadOnlyParameters; } Type [] types = new Type [pi.Length]; IParameterData [] par = new IParameterData [pi.Length]; bool is_params = false; + PredefinedAttribute extension_attr = PredefinedAttributes.Get.Extension; + PredefinedAttribute param_attr = PredefinedAttributes.Get.ParamArray; for (int i = 0; i < types.Length; i++) { types [i] = TypeManager.TypeToCoreType (pi [i].ParameterType); ParameterInfo p = pi [i]; Parameter.Modifier mod = 0; + Expression default_value = null; if (types [i].IsByRef) { if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out) mod = Parameter.Modifier.OUT; @@ -850,48 +931,63 @@ namespace Mono.CSharp { // Strip reference wrapping // types [i] = TypeManager.GetElementType (types [i]); - } else if (i == 0 && TypeManager.extension_attribute_type != null && method != null && method.IsStatic && + } else if (i == 0 && extension_attr.IsDefined && method != null && method.IsStatic && (method.DeclaringType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute && - method.IsDefined (TypeManager.extension_attribute_type, false)) { + method.IsDefined (extension_attr.Type, false)) { mod = Parameter.Modifier.This; - } else if (i >= pi.Length - 2 && types [i].IsArray) { - if (p.IsDefined (TypeManager.param_array_type, false)) { - mod = Parameter.Modifier.PARAMS; - is_params = true; + } else { + if (i >= pi.Length - 2) { + if (types[i].IsArray) { + if (p.IsDefined (param_attr.Type, false)) { + mod = Parameter.Modifier.PARAMS; + is_params = true; + } + } else if (types[i] == TypeManager.runtime_argument_handle_type) { + par[i] = new ArglistParameter (Location.Null); + continue; + } + } + + if (!is_params && p.IsOptional) { + if (p.DefaultValue == Missing.Value) + default_value = EmptyExpression.Null; + else + default_value = Constant.CreateConstant (types[i], p.DefaultValue, Location.Null); } } - par [i] = new ParameterData (p.Name, mod); + par [i] = new ParameterData (p.Name, mod, default_value); } return method != null ? - new ParametersCollection (par, types, method, is_params) : - new ParametersCollection (par, types); + new ParametersImported (par, types, method, is_params) : + new ParametersImported (par, types); } } /// /// Represents the methods parameters /// - public class Parameters : AParametersCollection { - public static readonly Parameters EmptyReadOnlyParameters = new Parameters (); + public class ParametersCompiled : AParametersCollection + { + public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled (); // Used by C# 2.0 delegates - public static readonly Parameters Undefined = new Parameters (); + public static readonly ParametersCompiled Undefined = new ParametersCompiled (); - private Parameters () + private ParametersCompiled () { parameters = new Parameter [0]; types = Type.EmptyTypes; } - private Parameters (Parameter [] parameters, Type [] types) + private ParametersCompiled (Parameter [] parameters, Type [] types) { this.parameters = parameters; this.types = types; } - public Parameters (params Parameter[] parameters) + public ParametersCompiled (params Parameter[] parameters) { if (parameters == null) throw new ArgumentException ("Use EmptyReadOnlyParameters"); @@ -921,23 +1017,23 @@ namespace Mono.CSharp { } } - public Parameters (Parameter [] parameters, bool has_arglist) : + public ParametersCompiled (Parameter [] parameters, bool has_arglist) : this (parameters) { this.has_arglist = has_arglist; } - public static Parameters CreateFullyResolved (Parameter p, Type type) + public static ParametersCompiled CreateFullyResolved (Parameter p, Type type) { - return new Parameters (new Parameter [] { p }, new Type [] { type }); + return new ParametersCompiled (new Parameter [] { p }, new Type [] { type }); } - public static Parameters CreateFullyResolved (Parameter[] parameters, Type[] types) + public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, Type[] types) { - return new Parameters (parameters, types); + return new ParametersCompiled (parameters, types); } - public static Parameters MergeGenerated (Parameters userParams, bool checkConflicts, Parameter compilerParams, Type compilerTypes) + public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, Type compilerTypes) { return MergeGenerated (userParams, checkConflicts, new Parameter [] { compilerParams }, @@ -947,7 +1043,7 @@ namespace Mono.CSharp { // // Use this method when you merge compiler generated parameters with user parameters // - public static Parameters MergeGenerated (Parameters userParams, bool checkConflicts, Parameter[] compilerParams, Type[] compilerTypes) + public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, Type[] compilerTypes) { Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length]; userParams.FixedParameters.CopyTo(all_params, 0); @@ -978,7 +1074,7 @@ namespace Mono.CSharp { ++last_filled; } - Parameters parameters = new Parameters (all_params, all_types); + ParametersCompiled parameters = new ParametersCompiled (all_params, all_types); parameters.has_params = userParams.has_params; return parameters; } @@ -1005,7 +1101,7 @@ namespace Mono.CSharp { { if (types != null) return true; - + types = new Type [Count]; bool ok = true; @@ -1086,9 +1182,9 @@ namespace Mono.CSharp { "[]", initializers, loc); } - public Parameters Clone () + public ParametersCompiled Clone () { - Parameters p = (Parameters) MemberwiseClone (); + ParametersCompiled p = (ParametersCompiled) MemberwiseClone (); p.parameters = new IParameterData [parameters.Length]; for (int i = 0; i < Count; ++i)