X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fparameter.cs;h=a6c5c63da7c0b41811e27bc1af73a1f09de97f86;hb=0c2bb8157f43826a57c39b863a1d67e3aef1b7b2;hp=2ab3ad676c9a8298a591ee33f1e8fbd96c434e9a;hpb=64c394f419b4971075030ecf5d455d08b229ce6e;p=mono.git diff --git a/mcs/mcs/parameter.cs b/mcs/mcs/parameter.cs index 2ab3ad676c9..a6c5c63da7c 100644 --- a/mcs/mcs/parameter.cs +++ b/mcs/mcs/parameter.cs @@ -4,10 +4,10 @@ // 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) +// Dual licensed under the terms of the MIT X11 or GNU GPL // +// Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) +// Copyright 2003-2008 Novell, Inc. // // using System; @@ -30,17 +30,18 @@ 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.marshal_as_attr_type) { +#if !NET_2_0 + if (a.Type == pa.MarshalAs) { UnmanagedMarshal marshal = a.GetMarshal (this); if (marshal != null) { builder.SetMarshal (marshal); } return; } - - if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) { +#endif + if (a.HasSecurityAttribute) { a.Error_InvalidSecurityParent (); return; } @@ -69,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"); } @@ -79,7 +80,7 @@ namespace Mono.CSharp { if (builder == null) return; - base.ApplyAttributeBuilder (a, cb); + base.ApplyAttributeBuilder (a, cb, pa); } public override AttributeTargets AttributeTargets { @@ -114,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 { @@ -139,57 +140,94 @@ namespace Mono.CSharp { } } + public class ImplicitLambdaParameter : Parameter + { + public ImplicitLambdaParameter (string name, Location loc) + : base (null, name, Modifier.NONE, null, loc) + { + } + + public override Type Resolve (IResolveContext ec) + { + if (parameter_type == null) + throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set", + Name); + + return parameter_type; + } + + public Type Type { + set { parameter_type = value; } + } + } + public class ParamsParameter : Parameter { - public ParamsParameter (Expression type, string name, Attributes attrs, Location loc): + public ParamsParameter (FullNamedExpression type, string name, Attributes attrs, Location loc): base (type, name, Parameter.Modifier.PARAMS, attrs, loc) { } - public override bool Resolve (IResolveContext ec) + public override Type Resolve (IResolveContext ec) { - if (!base.Resolve (ec)) - return false; + if (base.Resolve (ec) == null) + return null; if (!parameter_type.IsArray || parameter_type.GetArrayRank () != 1) { Report.Error (225, Location, "The params parameter must be a single dimensional array"); - return false; + return null; } - return true; + + return parameter_type; } public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index) { base.ApplyAttributes (mb, cb, index); - - CustomAttributeBuilder a = new CustomAttributeBuilder ( - TypeManager.ConsParamArrayAttribute, new object [0]); - - builder.SetCustomAttribute (a); + PredefinedAttributes.Get.ParamArray.EmitAttribute (builder, Location); } } public class ArglistParameter : Parameter { - // Doesn't have proper type because it's never choosed for better conversion - public ArglistParameter () : - base (typeof (ArglistParameter), "", Parameter.Modifier.ARGLIST, null, Location.Null) + // Doesn't have proper type because it's never chosen for better conversion + public ArglistParameter (Location loc) : + base (null, String.Empty, Parameter.Modifier.ARGLIST, null, loc) + { + } + + public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index) { + // Nothing to do } - public override bool Resolve (IResolveContext ec) + public override bool CheckAccessibility (InterfaceMemberBase member) { return true; } + public override Type Resolve (IResolveContext ec) + { + return typeof (ArglistParameter); + } + public override string GetSignatureForError () { return "__arglist"; } } - /// - /// Represents a single method parameter - /// - public class Parameter : ParameterBase { + public interface IParameterData + { + Expression DefaultValue { get; } + bool HasExtensionMethodModifier { get; } + bool HasDefaultValue { get; } + Parameter.Modifier ModFlags { get; } + string Name { get; } + } + + // + // Parameter information created by parser + // + public class Parameter : ParameterBase, IParameterData, ILocalVariable { [Flags] public enum Modifier : byte { NONE = 0, @@ -206,67 +244,64 @@ namespace Mono.CSharp { static string[] attribute_targets = new string [] { "param" }; - public Expression TypeName; - public Modifier modFlags; - public string Name; - public bool IsCaptured; + protected FullNamedExpression TypeName; + readonly Modifier modFlags; + string name; + Expression default_expr; protected Type parameter_type; public readonly Location Location; + int idx; + public bool HasAddressTaken; IResolveContext resolve_context; + LocalVariableReference expr_tree_variable; + static TypeExpr parameter_expr_tree_type; - Variable var; - public Variable Variable { - get { return var; } - } + public HoistedVariable HoistedVariableReference; -#if GMCS_SOURCE - GenericConstraints constraints; -#endif - - public Parameter (Expression type, string name, Modifier mod, Attributes attrs, Location loc) + public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc) : base (attrs) { - Name = name; - modFlags = mod; - TypeName = type; - Location = loc; - } + if (type == TypeManager.system_void_expr) + Report.Error (1536, loc, "Invalid parameter type `void'"); - public Parameter (Type type, string name, Modifier mod, Attributes attrs, Location loc) - : base (attrs) - { - Name = name; + this.name = name; modFlags = mod; - parameter_type = type; Location = loc; + 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 && - !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 - 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 (); @@ -275,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; @@ -286,7 +321,7 @@ namespace Mono.CSharp { } if (parameter_type == TypeManager.object_type || - (val == null && !TypeManager.IsValueType (parameter_type)) || + (val == null && !TypeManager.IsGenericParameter (parameter_type) && TypeManager.IsReferenceType (parameter_type)) || (val != null && TypeManager.TypeToCoreType (val.GetType ()) == parameter_type)) builder.SetConstant (val); else @@ -294,7 +329,15 @@ namespace Mono.CSharp { return; } - base.ApplyAttributeBuilder (a, cb); + base.ApplyAttributeBuilder (a, cb, pa); + } + + public virtual bool CheckAccessibility (InterfaceMemberBase member) + { + if (parameter_type == null || TypeManager.IsGenericParameter (parameter_type)) + return true; + + return member.IsAccessibleAs (parameter_type); } public override IResolveContext ResolveContext { @@ -306,70 +349,89 @@ namespace Mono.CSharp { // // Resolve is used in method definitions // - public virtual bool Resolve (IResolveContext ec) + public virtual Type Resolve (IResolveContext rc) { - if (parameter_type != null) - return true; + // HACK: to resolve attributes correctly + this.resolve_context = rc; - this.resolve_context = ec; + if (parameter_type != null) + return parameter_type; - TypeExpr texpr = TypeName.ResolveAsTypeTerminal (ec, false); + TypeExpr texpr = TypeName.ResolveAsTypeTerminal (rc, false); if (texpr == null) - return false; + return null; parameter_type = texpr.Type; -#if GMCS_SOURCE - TypeParameterExpr tparam = texpr as TypeParameterExpr; - if (tparam != null) { - constraints = tparam.TypeParameter.Constraints; - return true; - } -#endif + // Ignore all checks for dummy members + AbstractPropertyEventMethod pem = rc as AbstractPropertyEventMethod; + if (pem != null && pem.IsDummy) + return parameter_type; - if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) { - Report.Error (721, Location, "`{0}': static types cannot be used as parameters", - texpr.GetSignatureForError ()); - return false; + 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 (parameter_type == TypeManager.void_type){ - Report.Error (1536, Location, "Invalid parameter type 'void'"); - return false; + if ((modFlags & Parameter.Modifier.ISBYREF) != 0 && + TypeManager.IsSpecialType (parameter_type)) { + Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'", + GetSignatureForError ()); + return null; } - if ((modFlags & Parameter.Modifier.ISBYREF) != 0){ - if (parameter_type == TypeManager.typed_reference_type || - parameter_type == TypeManager.arg_iterator_type){ - Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'", - GetSignatureForError ()); - return false; - } + TypeManager.CheckTypeVariance (parameter_type, + (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant, + rc as MemberCore); + + if (texpr is TypeParameterExpr) + return parameter_type; + + if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) { + 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) { Report.Error (1103, Location, "The type of extension method cannot be `{0}'", TypeManager.CSharpName (parameter_type)); - return false; } - - return true; + + return parameter_type; } - public void ResolveVariable (ToplevelBlock toplevel, int idx) + public void ResolveVariable (int idx) { - if (toplevel.RootScope != null) - var = toplevel.RootScope.GetCapturedParameter (this); - if (var == null) - var = new ParameterVariable (this, idx); + this.idx = idx; } - public Type ExternalType () - { - if ((modFlags & Parameter.Modifier.ISBYREF) != 0) - return TypeManager.GetReferenceType (parameter_type); - - return parameter_type; + public bool HasDefaultValue { + get { return default_expr != null; } } public bool HasExtensionMethodModifier { @@ -380,45 +442,16 @@ namespace Mono.CSharp { get { return modFlags & ~Modifier.This; } } - public Type ParameterType { - get { - return parameter_type; - } - } - -#if GMCS_SOURCE - public GenericConstraints GenericConstraints { - get { - return constraints; - } + public string Name { + get { return name; } + set { name = value; } } -#endif ParameterAttributes Attributes { - get { - return (modFlags & Modifier.OUT) == Modifier.OUT ? - ParameterAttributes.Out : ParameterAttributes.None; - } + get { return ParametersCompiled.GetParameterAttribute (modFlags) | + (HasDefaultValue ? ParameterAttributes.Optional : ParameterAttributes.None); } } - // TODO: should be removed !!!!!!! - public static ParameterAttributes GetParameterAttributes (Modifier mod) - { - int flags = ((int) mod) & ~((int) Parameter.Modifier.ISBYREF); - switch ((Modifier) flags) { - case Modifier.NONE: - return ParameterAttributes.None; - case Modifier.REF: - return ParameterAttributes.None; - case Modifier.OUT: - return ParameterAttributes.Out; - case Modifier.PARAMS: - return 0; - } - - return ParameterAttributes.None; - } - public override AttributeTargets AttributeTargets { get { return AttributeTargets.Parameter; @@ -435,7 +468,7 @@ namespace Mono.CSharp { string mod = GetModifierSignature (modFlags); if (mod.Length > 0) - return String.Concat (mod, ' ', type_name); + return String.Concat (mod, " ", type_name); return type_name; } @@ -443,41 +476,51 @@ namespace Mono.CSharp { public static string GetModifierSignature (Modifier mod) { switch (mod) { - case Modifier.OUT: - return "out"; - case Modifier.PARAMS: - return "params"; - case Modifier.REF: - return "ref"; - case Modifier.ARGLIST: - return "__arglist"; - case Modifier.This: - return "this"; - default: - return ""; + case Modifier.OUT: + return "out"; + case Modifier.PARAMS: + return "params"; + case Modifier.REF: + return "ref"; + case Modifier.This: + return "this"; + default: + return ""; } } public void IsClsCompliant () { - if (AttributeTester.IsClsCompliant (ExternalType ())) + if (AttributeTester.IsClsCompliant (parameter_type)) return; - Report.Error (3001, Location, "Argument type `{0}' is not CLS-compliant", GetSignatureForError ()); + Report.Warning (3001, 1, Location, "Argument type `{0}' is not CLS-compliant", GetSignatureForError ()); } public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index) { -#if !GMCS_SOURCE || !MS_COMPATIBLE - // TODO: It should use mb.DefineGenericParameters if (mb == null) builder = cb.DefineParameter (index, Attributes, Name); - else + else builder = mb.DefineParameter (index, Attributes, Name); -#endif 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 { @@ -486,269 +529,601 @@ namespace Mono.CSharp { } } - protected class ParameterVariable : Variable + public Parameter Clone () { - public readonly Parameter Parameter; - public readonly int Idx; - public readonly bool IsRef; - - public ParameterVariable (Parameter par, int idx) - { - this.Parameter = par; - this.Idx = idx; - this.IsRef = (par.ModFlags & Parameter.Modifier.ISBYREF) != 0; + Parameter p = (Parameter) MemberwiseClone (); + if (attributes != null) { + p.attributes = attributes.Clone (); + p.attributes.AttachTo (p); } - public override Type Type { - get { return Parameter.ParameterType; } - } + return p; + } - public override bool HasInstance { - get { return false; } - } + public ExpressionStatement CreateExpressionTreeVariable (EmitContext ec) + { + // + // A parameter is not hoisted when used directly as ET + // + HoistedVariableReference = null; - public override bool NeedsTemporary { - get { return false; } - } + if ((modFlags & Modifier.ISBYREF) != 0) + Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier"); - public override void EmitInstance (EmitContext ec) - { - } + LocalInfo variable = ec.CurrentBlock.AddTemporaryVariable ( + ResolveParameterExpressionType (ec, Location), Location); + variable.Resolve (ec); - public override void Emit (EmitContext ec) - { - int arg_idx = Idx; - if (!ec.MethodIsStatic) - arg_idx++; + expr_tree_variable = new LocalVariableReference ( + ec.CurrentBlock, variable.Name, Location, variable, false); - ParameterReference.EmitLdArg (ec.ig, arg_idx); - } + ArrayList arguments = new ArrayList (2); + arguments.Add (new Argument (new TypeOf ( + new TypeExpression (parameter_type, Location), Location))); + arguments.Add (new Argument (new StringConstant (Name, Location))); + return new SimpleAssign (ExpressionTreeVariableReference (), + 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; + if (!ec.IsStatic) + arg_idx++; + + ParameterReference.EmitLdArg (ec.ig, arg_idx); + } - public override void EmitAssign (EmitContext ec) - { - int arg_idx = Idx; - if (!ec.MethodIsStatic) - arg_idx++; + public void EmitAssign (EmitContext ec) + { + int arg_idx = idx; + if (!ec.IsStatic) + arg_idx++; + + if (arg_idx <= 255) + ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx); + else + ec.ig.Emit (OpCodes.Starg, arg_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.ig, arg_idx); + } else { if (arg_idx <= 255) - ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx); + ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx); else - ec.ig.Emit (OpCodes.Starg, arg_idx); + ec.ig.Emit (OpCodes.Ldarga, arg_idx); } + } - public override void EmitAddressOf (EmitContext ec) - { - int arg_idx = Idx; + public Expression ExpressionTreeVariableReference () + { + return expr_tree_variable; + } - if (!ec.MethodIsStatic) - arg_idx++; + // + // System.Linq.Expressions.ParameterExpression type + // + public static TypeExpr ResolveParameterExpressionType (EmitContext ec, Location location) + { + if (parameter_expr_tree_type != null) + return parameter_expr_tree_type; - if (IsRef) { - if (arg_idx <= 255) - ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx); - else - ec.ig.Emit (OpCodes.Ldarg, arg_idx); - } else { - if (arg_idx <= 255) - ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx); - else - ec.ig.Emit (OpCodes.Ldarga, arg_idx); - } + Type p_type = TypeManager.parameter_expression_type; + if (p_type == null) { + p_type = TypeManager.CoreLookupType ("System.Linq.Expressions", "ParameterExpression", Kind.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; } - public Parameter Clone () + public void Warning_UselessOptionalParameter () { - Parameter p = new Parameter (TypeName, Name, ModFlags, attributes, Location); - p.parameter_type = parameter_type; + Report.Warning (1066, 1, Location, + "The default value specified for optional parameter `{0}' will never be used", + Name); + } + } - return p; + // + // Imported or resolved parameter information + // + public class ParameterData : IParameterData + { + readonly string name; + readonly Parameter.Modifier modifiers; + readonly Expression default_value; + + public ParameterData (string name, Parameter.Modifier modifiers) + { + this.name = name; + 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; } + } + + public string Name { + get { return name; } + } + + #endregion } - /// - /// Represents the methods parameters - /// - public class Parameters : ParameterData { + public abstract class AParametersCollection + { + protected bool has_arglist; + protected bool has_params; + // Null object pattern - public Parameter [] FixedParameters; - public readonly bool HasArglist; - Type [] types; - int count; + protected IParameterData [] parameters; + protected Type [] types; - public static readonly Parameters EmptyReadOnlyParameters = new Parameters (); - static readonly Parameter ArgList = new ArglistParameter (); + public int Count { + get { return parameters.Length; } + } -#if GMCS_SOURCE - public readonly TypeParameter[] TypeParameters; -#endif + public Type ExtensionMethodType { + get { + if (Count == 0) + return null; - private Parameters () - { - FixedParameters = new Parameter[0]; - types = new Type [0]; + return FixedParameters [0].HasExtensionMethodModifier ? + types [0] : null; + } + } + + public IParameterData [] FixedParameters { + get { + return parameters; + } } - public Parameters (Parameter[] parameters, Type[] types) + public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags) { - FixedParameters = parameters; - this.types = types; - count = types.Length; + return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ? + ParameterAttributes.Out : ParameterAttributes.None; } - - public Parameters (Parameter[] parameters) + + public Type [] GetEmitTypes () { - if (parameters == null) - throw new ArgumentException ("Use EmptyReadOnlyPatameters"); + Type [] types = null; + if (has_arglist) { + if (Count == 1) + return Type.EmptyTypes; + + types = new Type [Count - 1]; + Array.Copy (Types, types, types.Length); + } + + for (int i = 0; i < Count; ++i) { + if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0) + continue; + + if (types == null) + types = (Type []) Types.Clone (); + + types [i] = TypeManager.GetReferenceType (types [i]); + } + + if (types == null) + types = Types; - FixedParameters = parameters; - count = parameters.Length; + return types; } - public Parameters (Parameter[] parameters, bool has_arglist): - this (parameters) + public string GetSignatureForError () { - HasArglist = has_arglist; + StringBuilder sb = new StringBuilder ("("); + for (int i = 0; i < Count; ++i) { + if (i != 0) + sb.Append (", "); + sb.Append (ParameterDesc (i)); + } + sb.Append (')'); + return sb.ToString (); } - /// - /// Use this method when you merge compiler generated argument with user arguments - /// - public static Parameters MergeGenerated (Parameters userParams, params Parameter[] compilerParams) + public bool HasArglist { + get { return has_arglist; } + } + + public bool HasExtensionMethodType { + get { + if (Count == 0) + return false; + + return FixedParameters [0].HasExtensionMethodModifier; + } + } + + public bool HasParams { + get { return has_params; } + } + + public bool IsEmpty { + get { return parameters.Length == 0; } + } + + public string ParameterDesc (int pos) { - Parameter[] all_params = new Parameter [userParams.count + compilerParams.Length]; - Type[] all_types = new Type[all_params.Length]; - userParams.FixedParameters.CopyTo(all_params, 0); - userParams.Types.CopyTo (all_types, 0); + if (types == null || types [pos] == null) + return ((Parameter)FixedParameters [pos]).GetSignatureForError (); - int last_filled = userParams.Count; - foreach (Parameter p in compilerParams) { - for (int i = 0; i < last_filled; ++i) { - while (p.Name == all_params [i].Name) { - p.Name = '_' + p.Name; + string type = TypeManager.CSharpName (types [pos]); + if (FixedParameters [pos].HasExtensionMethodModifier) + return "this " + type; + + Parameter.Modifier mod = FixedParameters [pos].ModFlags & ~Parameter.Modifier.ARGLIST; + if (mod == 0) + return type; + + return Parameter.GetModifierSignature (mod) + " " + type; + } + + public Type[] Types { + get { return types; } + set { types = value; } + } + +#if MS_COMPATIBLE + public AParametersCollection InflateTypes (Type[] genArguments, Type[] argTypes) + { + AParametersCollection p = (AParametersCollection) MemberwiseClone (); // Clone (); + + for (int i = 0; i < Count; ++i) { + if (types[i].IsGenericType) { + Type[] gen_arguments_open = new Type[types[i].GetGenericTypeDefinition ().GetGenericArguments ().Length]; + Type[] gen_arguments = types[i].GetGenericArguments (); + for (int ii = 0; ii < gen_arguments_open.Length; ++ii) { + if (gen_arguments[ii].IsGenericParameter) { + Type t = argTypes[gen_arguments[ii].GenericParameterPosition]; + gen_arguments_open[ii] = t; + } else + gen_arguments_open[ii] = gen_arguments[ii]; } + + p.types[i] = types[i].GetGenericTypeDefinition ().MakeGenericType (gen_arguments_open); + continue; + } + + if (types[i].IsGenericParameter) { + Type gen_argument = argTypes[types[i].GenericParameterPosition]; + p.types[i] = gen_argument; + continue; } - all_params [last_filled] = p; - all_types [last_filled] = p.ParameterType; - ++last_filled; } - - return new Parameters (all_params, all_types); + + return p; + } +#endif + } + + // + // A collection of imported or resolved parameters + // + public class ParametersImported : AParametersCollection + { + ParametersImported (AParametersCollection param, Type[] types) + { + this.parameters = param.FixedParameters; + this.types = types; + has_arglist = param.HasArglist; + has_params = param.HasParams; } - public bool Empty { - get { - return count == 0; + ParametersImported (IParameterData [] parameters, Type [] types, MethodBase method, bool hasParams) + { + this.parameters = parameters; + this.types = types; + has_arglist = (method.CallingConvention & CallingConventions.VarArgs) != 0; + if (has_arglist) { + this.parameters = new IParameterData [parameters.Length + 1]; + parameters.CopyTo (this.parameters, 0); + this.parameters [parameters.Length] = new ArglistParameter (Location.Null); + this.types = new Type [types.Length + 1]; + types.CopyTo (this.types, 0); + this.types [types.Length] = TypeManager.arg_iterator_type; } + has_params = hasParams; } - public int Count { - get { - return HasArglist ? count + 1 : count; - } + public ParametersImported (IParameterData [] param, Type[] types) + { + this.parameters = param; + this.types = types; + } + + public static AParametersCollection Create (MethodBase method) + { + return Create (method.GetParameters (), method); } // - // The property can be used after parameter types were resolved. + // Generic method parameters importer, param is shared between all instances // - public Type ExtensionMethodType { - get { - if (count == 0) - return null; + public static AParametersCollection Create (AParametersCollection param, MethodBase method) + { + if (param.IsEmpty) + return param; - return FixedParameters [0].HasExtensionMethodModifier ? - types [0] : null; + ParameterInfo [] pi = method.GetParameters (); + Type [] types = new Type [pi.Length]; + for (int i = 0; i < types.Length; i++) { + Type t = pi [i].ParameterType; + if (t.IsByRef) + t = TypeManager.GetElementType (t); + + types [i] = TypeManager.TypeToCoreType (t); } + + return new ParametersImported (param, types); } - public bool HasExtensionMethodType { - get { - if (count == 0) - return false; + // + // Imports SRE parameters + // + public static AParametersCollection Create (ParameterInfo [] pi, MethodBase method) + { + if (pi.Length == 0) { + if (method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0) + return new ParametersImported (new IParameterData [0], Type.EmptyTypes, method, false); - return FixedParameters [0].HasExtensionMethodModifier; + 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; + else + mod = Parameter.Modifier.REF; + + // + // Strip reference wrapping + // + types [i] = TypeManager.GetElementType (types [i]); + } else if (i == 0 && extension_attr.IsDefined && method != null && method.IsStatic && + (method.DeclaringType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute && + method.IsDefined (extension_attr.Type, false)) { + mod = Parameter.Modifier.This; + } 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, default_value); + } + + return method != null ? + new ParametersImported (par, types, method, is_params) : + new ParametersImported (par, types); } + } + /// + /// Represents the methods parameters + /// + public class ParametersCompiled : AParametersCollection + { + public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled (); + + // Used by C# 2.0 delegates + public static readonly ParametersCompiled Undefined = new ParametersCompiled (); - bool VerifyArgs () + private ParametersCompiled () { - if (count < 2) - return true; + parameters = new Parameter [0]; + types = Type.EmptyTypes; + } + + private ParametersCompiled (Parameter [] parameters, Type [] types) + { + this.parameters = parameters; + this.types = types; + } + + public ParametersCompiled (params Parameter[] parameters) + { + if (parameters == null) + throw new ArgumentException ("Use EmptyReadOnlyParameters"); + + this.parameters = parameters; + int count = parameters.Length; + + if (count == 0) + return; + + if (count == 1) { + has_params = (parameters [0].ModFlags & Parameter.Modifier.PARAMS) != 0; + return; + } for (int i = 0; i < count; i++){ - string base_name = FixedParameters [i].Name; + string base_name = parameters [i].Name; + has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0; + for (int j = i + 1; j < count; j++){ - if (base_name != FixedParameters [j].Name) + if (base_name != parameters [j].Name) continue; - Report.Error (100, FixedParameters [i].Location, - "The parameter name `{0}' is a duplicate", base_name); - return false; + ErrorDuplicateName (parameters [i]); + i = j; } } - return true; + } + + public ParametersCompiled (Parameter [] parameters, bool has_arglist) : + this (parameters) + { + this.has_arglist = has_arglist; } + public static ParametersCompiled CreateFullyResolved (Parameter p, Type type) + { + return new ParametersCompiled (new Parameter [] { p }, new Type [] { type }); + } - /// - /// Returns the paramenter information based on the name - /// - public Parameter GetParameterByName (string name, out int idx) + public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, Type[] types) { - idx = 0; + return new ParametersCompiled (parameters, types); + } - if (count == 0) - return null; + public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, Type compilerTypes) + { + return MergeGenerated (userParams, checkConflicts, + new Parameter [] { compilerParams }, + new Type [] { compilerTypes }); + } - int i = 0; + // + // Use this method when you merge compiler generated parameters with user parameters + // + 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); - foreach (Parameter par in FixedParameters){ - if (par.Name == name){ - idx = i; - return par; + Type [] all_types; + if (userParams.types != null) { + all_types = new Type [all_params.Length]; + userParams.Types.CopyTo (all_types, 0); + } else { + all_types = null; + } + + int last_filled = userParams.Count; + int index = 0; + foreach (Parameter p in compilerParams) { + for (int i = 0; i < last_filled; ++i) { + while (p.Name == all_params [i].Name) { + if (checkConflicts && i < userParams.Count) { + Report.Error (316, userParams [i].Location, + "The parameter name `{0}' conflicts with a compiler generated name", p.Name); + } + p.Name = '_' + p.Name; + } } - i++; + all_params [last_filled] = p; + if (all_types != null) + all_types [last_filled] = compilerTypes [index++]; + ++last_filled; } - return null; + + ParametersCompiled parameters = new ParametersCompiled (all_params, all_types); + parameters.has_params = userParams.has_params; + return parameters; + } + + protected virtual void ErrorDuplicateName (Parameter p) + { + Report.Error (100, p.Location, "The parameter name `{0}' is a duplicate", p.Name); } - public Parameter GetParameterByName (string name) + /// + /// Returns the parameter information based on the name + /// + public int GetParameterIndexByName (string name) { - int idx; + for (int idx = 0; idx < Count; ++idx) { + if (parameters [idx].Name == name) + return idx; + } - return GetParameterByName (name, out idx); + return -1; } - + public bool Resolve (IResolveContext ec) { if (types != null) return true; - - types = new Type [count]; - if (!VerifyArgs ()) - return false; - + types = new Type [Count]; + bool ok = true; Parameter p; for (int i = 0; i < FixedParameters.Length; ++i) { - p = FixedParameters [i]; - if (!p.Resolve (ec)) { + p = this [i]; + Type t = p.Resolve (ec); + if (t == null) { ok = false; continue; } - types [i] = p.ExternalType (); + + types [i] = t; } return ok; } - public void ResolveVariable (ToplevelBlock toplevel) + public void ResolveVariable () { for (int i = 0; i < FixedParameters.Length; ++i) { - Parameter p = FixedParameters [i]; - p.ResolveVariable (toplevel, i); + this [i].ResolveVariable (i); } } @@ -766,14 +1141,14 @@ namespace Mono.CSharp { // the argument names. public void ApplyAttributes (MethodBase builder) { - if (count == 0) + if (Count == 0) return; MethodBuilder mb = builder as MethodBuilder; ConstructorBuilder cb = builder as ConstructorBuilder; - for (int i = 0; i < FixedParameters.Length; i++) { - FixedParameters [i].ApplyAttributes (mb, cb, i + 1); + for (int i = 0; i < Count; i++) { + this [i].ApplyAttributes (mb, cb, i + 1); } } @@ -783,90 +1158,39 @@ namespace Mono.CSharp { p.IsClsCompliant (); } - public string GetSignatureForError () - { - StringBuilder sb = new StringBuilder ("("); - if (count > 0) { - for (int i = 0; i < FixedParameters.Length; ++i) { - sb.Append (FixedParameters[i].GetSignatureForError ()); - if (i < FixedParameters.Length - 1) - sb.Append (", "); - } - } - - if (HasArglist) { - if (sb.Length > 1) - sb.Append (", "); - sb.Append ("__arglist"); - } - - sb.Append (')'); - return sb.ToString (); - } - - public Type[] Types { - get { - return types; - } + public Parameter this [int pos] { + get { return (Parameter) parameters [pos]; } } - public Parameter this [int pos] + public Expression CreateExpressionTree (EmitContext ec, Location loc) { - get { - if (pos >= count && (HasArglist || HasParams)) { - if (HasArglist && (pos == 0 || pos >= count)) - return ArgList; - pos = count - 1; - } - - return FixedParameters [pos]; - } - } - - #region ParameterData Members - - public Type ParameterType (int pos) - { - return this [pos].ExternalType (); - } - - public bool HasParams { - get { - if (count == 0) - return false; - - for (int i = count; i != 0; --i) { - if ((FixedParameters [i - 1].ModFlags & Parameter.Modifier.PARAMS) != 0) - return true; - } - return false; + ArrayList initializers = new ArrayList (Count); + foreach (Parameter p in FixedParameters) { + // + // Each parameter expression is stored to local variable + // to save some memory when referenced later. + // + StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec)); + if (se.Resolve (ec)) + ec.CurrentBlock.AddScopeStatement (se); + + initializers.Add (p.ExpressionTreeVariableReference ()); } - } - public string ParameterName (int pos) - { - return this [pos].Name; + return new ArrayCreation ( + Parameter.ResolveParameterExpressionType (ec, loc), + "[]", initializers, loc); } - public string ParameterDesc (int pos) + public ParametersCompiled Clone () { - return this [pos].GetSignatureForError (); - } + ParametersCompiled p = (ParametersCompiled) MemberwiseClone (); - public Parameter.Modifier ParameterModifier (int pos) - { - return this [pos].ModFlags; - } + p.parameters = new IParameterData [parameters.Length]; + for (int i = 0; i < Count; ++i) + p.parameters [i] = this [i].Clone (); - public Parameters Clone () - { - Parameter [] parameters_copy = new Parameter [FixedParameters.Length]; - int i = 0; - foreach (Parameter p in FixedParameters) - parameters_copy [i++] = p.Clone (); - return new Parameters (parameters_copy, HasArglist); + return p; } - - #endregion } }