X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fparameter.cs;h=275f1013e8b9dfb533215ddeaeb466e4d4a8faf9;hb=631d194f74cdf9feb8684931805a813d3e6fb40a;hp=1f2cefd501ad09e674e5667086f23b6a07fd63fa;hpb=d9a7a4eab0d357d408f47939421f7dd723852134;p=mono.git diff --git a/mcs/mcs/parameter.cs b/mcs/mcs/parameter.cs index 1f2cefd501a..275f1013e8b 100644 --- a/mcs/mcs/parameter.cs +++ b/mcs/mcs/parameter.cs @@ -213,15 +213,19 @@ namespace Mono.CSharp { 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 readonly string[] attribute_targets = new string[] { "param" }; + static readonly string[] attribute_targets = new [] { "param" }; FullNamedExpression texpr; - readonly Modifier modFlags; + Modifier modFlags; string name; Expression default_expr; protected TypeSpec parameter_type; @@ -231,7 +235,7 @@ namespace Mono.CSharp { TemporaryVariableReference expr_tree_variable; - HoistedVariable hoisted_variant; + HoistedParameter hoisted_variant; public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc) { @@ -330,17 +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 (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter) { + } 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); + a.Type.GetSignatureForError ().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"); + } } base.ApplyAttributeBuilder (a, ctor, cdata, pa); @@ -354,6 +371,15 @@ namespace Mono.CSharp { return member.IsAccessibleAs (parameter_type); } + bool IsValidCallerContext (MemberCore memberContext) + { + var m = memberContext as Method; + if (m != null) + return !m.IsPartialImplementation; + + return true; + } + // // Resolve is used in method definitions // @@ -377,7 +403,7 @@ namespace Mono.CSharp { return null; } - TypeManager.CheckTypeVariance (parameter_type, + VarianceDecl.CheckTypeVariance (parameter_type, (modFlags & Parameter.Modifier.RefOutMask) != 0 ? Variance.None : Variance.Contravariant, rc); @@ -389,12 +415,104 @@ namespace Mono.CSharp { 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)); + parameter_type.GetSignatureForError ()); } return parameter_type; } + void ResolveCallerAttributes (ResolveContext rc) + { + var pa = rc.Module.PredefinedAttributes; + TypeSpec caller_type; + Attribute callerMemberName = null, callerFilePath = null; + + foreach (var attr in attributes.Attrs) { + var atype = attr.ResolveTypeForComparison (); + 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 ()); + } + + if (!IsValidCallerContext (rc.CurrentMemberDefinition)) { + rc.Report.Warning (4026, 1, attr.Location, + "The CallerMemberName applied to parameter `{0}' will have no effect because it applies to a member that is used in context that do not allow optional arguments", + name); + } + + modFlags |= Modifier.CallerMemberName; + callerMemberName = attr; + continue; + } + + if (atype == pa.CallerLineNumberAttribute) { + caller_type = rc.BuiltinTypes.Int; + if (caller_type != parameter_type && !Convert.ImplicitStandardConversionExists (new IntConstant (caller_type, int.MaxValue, Location.Null), parameter_type)) { + rc.Report.Error (4017, attr.Location, + "The CallerLineNumberAttribute attribute cannot be applied because there is no standard conversion from `{0}' to `{1}'", + caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ()); + } + + if (!IsValidCallerContext (rc.CurrentMemberDefinition)) { + rc.Report.Warning (4024, 1, attr.Location, + "The CallerLineNumberAttribute applied to parameter `{0}' will have no effect because it applies to a member that is used in context that do not allow optional arguments", + name); + } + + 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 ()); + } + + if (!IsValidCallerContext (rc.CurrentMemberDefinition)) { + rc.Report.Warning (4025, 1, attr.Location, + "The CallerFilePath applied to parameter `{0}' will have no effect because it applies to a member that is used in context that do not allow optional arguments", + name); + } + + modFlags |= Modifier.CallerFilePath; + callerFilePath = attr; + continue; + } + } + + if ((modFlags & Modifier.CallerLineNumber) != 0) { + if (callerMemberName != null) { + rc.Report.Warning (7081, 1, callerMemberName.Location, + "The CallerMemberNameAttribute applied to parameter `{0}' will have no effect. It is overridden by the CallerLineNumberAttribute", + Name); + } + + if (callerFilePath != null) { + rc.Report.Warning (7082, 1, callerFilePath.Location, + "The CallerFilePathAttribute applied to parameter `{0}' will have no effect. It is overridden by the CallerLineNumberAttribute", + name); + } + } + + if ((modFlags & Modifier.CallerMemberName) != 0) { + if (callerFilePath != null) { + rc.Report.Warning (7080, 1, callerFilePath.Location, + "The CallerMemberNameAttribute applied to parameter `{0}' will have no effect. It is overridden by the CallerFilePathAttribute", + name); + } + + } + } + public void ResolveDefaultValue (ResolveContext rc) { // @@ -402,6 +520,9 @@ namespace Mono.CSharp { // if (default_expr != null) { ((DefaultParameterValueExpression)default_expr).Resolve (rc, this); + if (attributes != null) + ResolveCallerAttributes (rc); + return; } @@ -409,7 +530,6 @@ namespace Mono.CSharp { return; var pa = rc.Module.PredefinedAttributes; - var def_attr = attributes.Search (pa.DefaultParameterValue); if (def_attr != null) { if (def_attr.Resolve () == null) @@ -434,7 +554,7 @@ namespace Mono.CSharp { } else { rc.Report.Error (1909, default_expr.Location, "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'", - default_expr.Type.GetSignatureForError ()); ; + default_expr.Type.GetSignatureForError ()); } default_expr = null; @@ -443,7 +563,8 @@ namespace Mono.CSharp { 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) { + parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object || + parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { return; } @@ -482,7 +603,7 @@ namespace Mono.CSharp { // // Hoisted parameter variant // - public HoistedVariable HoistedVariant { + public HoistedParameter HoistedVariant { get { return hoisted_variant; } @@ -515,7 +636,7 @@ namespace Mono.CSharp { { string type_name; if (parameter_type != null) - type_name = TypeManager.CSharpName (parameter_type); + type_name = parameter_type.GetSignatureForError (); else type_name = texpr.GetSignatureForError (); @@ -568,7 +689,7 @@ namespace Mono.CSharp { if (OptAttributes != null) OptAttributes.Emit (); - if (HasDefaultValue) { + if (HasDefaultValue && default_expr.Type != null) { // // Emit constant values for true constants only, the other // constant-like expressions will rely on default value expression @@ -581,9 +702,9 @@ namespace Mono.CSharp { } else { builder.SetConstant (c.GetValue ()); } - } else if (default_expr.Type.IsStruct) { + } else if (default_expr.Type.IsStruct || default_expr.Type.IsGenericParameter) { // - // Handles special case where default expression is used with value-type + // Handles special case where default expression is used with value-type or type parameter // // void Foo (S s = default (S)) {} // @@ -657,6 +778,11 @@ namespace Mono.CSharp { return new TypeExpression (p_type, location); } + public void SetIndex (int index) + { + idx = index; + } + public void Warning_UselessOptionalParameter (Report Report) { Report.Warning (1066, 1, Location, @@ -750,7 +876,7 @@ 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; } @@ -833,6 +959,19 @@ namespace Mono.CSharp { return sb.ToString (); } + public static bool HasSameParameterDefaults (AParametersCollection a, AParametersCollection b) + { + if (a == null) + return b == null; + + for (int i = 0; i < a.Count; ++i) { + if (a.FixedParameters [i].HasDefaultValue != b.FixedParameters [i].HasDefaultValue) + return false; + } + + return true; + } + public bool HasArglist { get { return has_arglist; } } @@ -865,9 +1004,14 @@ namespace Mono.CSharp { if (inflated_param == types[i]) continue; - default_value |= FixedParameters[i] is DefaultValueExpression; + default_value |= FixedParameters[i].HasDefaultValue; inflated_types = new TypeSpec[types.Length]; - Array.Copy (types, inflated_types, types.Length); + Array.Copy (types, inflated_types, types.Length); + } else { + if (inflated_param == types[i]) + continue; + + default_value |= FixedParameters[i].HasDefaultValue; } inflated_types[i] = inflated_param; @@ -878,13 +1022,42 @@ namespace Mono.CSharp { var clone = (AParametersCollection) MemberwiseClone (); clone.types = inflated_types; + + // + // Default expression is original expression from the parameter + // declaration context which can be of nested enum in generic class type. + // In such case we end up with expression type of G.E and e.g. parameter + // type of G.E and conversion would fail without inflate in this + // context. + // if (default_value) { + clone.parameters = new IParameterData[Count]; for (int i = 0; i < Count; ++i) { - var dve = clone.FixedParameters[i] as DefaultValueExpression; - if (dve != null) { - throw new NotImplementedException ("net"); - // clone.FixedParameters [i].DefaultValue = new DefaultValueExpression (); - } + var fp = FixedParameters[i]; + clone.FixedParameters[i] = fp; + + if (!fp.HasDefaultValue) + continue; + + var expr = fp.DefaultValue; + + if (inflated_types[i] == expr.Type) + continue; + + var c = expr as Constant; + if (c != null) { + // + // It may fail we are inflating before type validation is done + // + c = Constant.ExtractConstantFromValue (inflated_types[i], c.GetValue (), expr.Location); + if (c == null) + expr = new DefaultValueExpression (new TypeExpression (inflated_types[i], expr.Location), expr.Location); + else + expr = c; + } else if (expr is DefaultValueExpression) + expr = new DefaultValueExpression (new TypeExpression (inflated_types[i], expr.Location), expr.Location); + + clone.FixedParameters[i] = new ParameterData (fp.Name, fp.ModFlags, expr); } } @@ -896,11 +1069,11 @@ namespace Mono.CSharp { if (types == null || types [pos] == null) return ((Parameter)FixedParameters [pos]).GetSignatureForError (); - string type = TypeManager.CSharpName (types [pos]); + string type = types [pos].GetSignatureForError (); if (FixedParameters [pos].HasExtensionMethodModifier) return "this " + type; - Parameter.Modifier mod = FixedParameters [pos].ModFlags; + var mod = FixedParameters[pos].ModFlags & Parameter.Modifier.ModifierMask; if (mod == 0) return type; @@ -985,6 +1158,23 @@ namespace Mono.CSharp { return new ParametersCompiled (parameters, types); } + public static ParametersCompiled Prefix (ParametersCompiled parameters, Parameter p, TypeSpec type) + { + var ptypes = new TypeSpec [parameters.Count + 1]; + ptypes [0] = type; + Array.Copy (parameters.Types, 0, ptypes, 1, parameters.Count); + + var param = new Parameter [ptypes.Length]; + param [0] = p; + for (int i = 0; i < parameters.Count; ++i) { + var pi = parameters [i]; + param [i + 1] = pi; + pi.SetIndex (i + 1); + } + + return ParametersCompiled.CreateFullyResolved (param, ptypes); + } + // // 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 @@ -1146,6 +1336,9 @@ namespace Mono.CSharp { for (int i = 0; i < parameters.Length; ++i) { Parameter p = (Parameter) parameters [i]; + if (p.Type != null) + p.Type.CheckObsoleteness (m, p.Location); + // // Try not to enter default values resolution if there are is not any default value possible // @@ -1232,23 +1425,22 @@ namespace Mono.CSharp { { } - protected override Expression DoResolve (ResolveContext rc) - { - return base.DoResolve (rc); - } - public void Resolve (ResolveContext rc, Parameter p) { var expr = Resolve (rc); - if (expr == null) + if (expr == null) { + this.expr = ErrorExpression.Instance; 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); + if (!(expr is Constant || expr is DefaultValueExpression || (expr is New && ((New) expr).IsGeneratedStructConstructor))) { + if (!(expr is ErrorExpression)) { + rc.Report.Error (1736, Location, + "The expression being assigned to optional parameter `{0}' must be a constant or default value", + p.Name); + } return; } @@ -1285,6 +1477,8 @@ namespace Mono.CSharp { rc.Report.Error (1750, Location, "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'", type.GetSignatureForError (), parameter_type.GetSignatureForError ()); + + this.expr = ErrorExpression.Instance; } public override object Accept (StructuralVisitor visitor)