using System;
using System.Reflection;
using System.Reflection.Emit;
-using System.Collections;
using System.Text;
+using System.Linq;
namespace Mono.CSharp {
/// <summary>
/// Abstract Base class for parameters of a method.
/// </summary>
- public abstract class ParameterBase : Attributable {
-
+ public abstract class ParameterBase : Attributable
+ {
protected ParameterBuilder builder;
- protected ParameterBase (Attributes attrs)
- : base (attrs)
- {
- }
-
- public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
+ public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
{
-#if !NET_2_0
+#if false
if (a.Type == pa.MarshalAs) {
UnmanagedMarshal marshal = a.GetMarshal (this);
if (marshal != null) {
return;
}
- builder.SetCustomAttribute (cb);
+ if (a.Type == pa.Dynamic) {
+ a.Error_MisusedDynamicAttribute ();
+ return;
+ }
+
+ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
+ }
+
+ public ParameterBuilder Builder {
+ get {
+ return builder;
+ }
}
public override bool IsClsComplianceRequired()
/// <summary>
/// Class for applying custom attributes on the return type
/// </summary>
- public class ReturnParameter : ParameterBase {
- public ReturnParameter (MethodBuilder mb, Location location):
- base (null)
+ public class ReturnParameter : ParameterBase
+ {
+ MemberCore method;
+
+ // TODO: merge method and mb
+ public ReturnParameter (MemberCore method, MethodBuilder mb, Location location)
{
+ this.method = method;
try {
builder = mb.DefineParameter (0, ParameterAttributes.None, "");
}
catch (ArgumentOutOfRangeException) {
- Report.RuntimeMissingSupport (location, "custom attributes on the return type");
+ method.Compiler.Report.RuntimeMissingSupport (location, "custom attributes on the return type");
}
}
- public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
+ public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
{
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");
+ method.Compiler.Report.Warning (3023, 1, a.Location,
+ "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
}
// This occurs after Warning -28
if (builder == null)
return;
- base.ApplyAttributeBuilder (a, cb, pa);
+ base.ApplyAttributeBuilder (a, ctor, cdata, pa);
}
public override AttributeTargets AttributeTargets {
}
}
- public override IResolveContext ResolveContext {
- get {
- throw new NotSupportedException ();
- }
- }
-
/// <summary>
/// Is never called
/// </summary>
///
// TODO: should use more code from Parameter.ApplyAttributeBuilder
public class ImplicitParameter : ParameterBase {
- public ImplicitParameter (MethodBuilder mb):
- base (null)
+ public ImplicitParameter (MethodBuilder mb)
{
builder = mb.DefineParameter (1, ParameterAttributes.None, "value");
}
}
}
- public override IResolveContext ResolveContext {
- get {
- throw new NotSupportedException ();
- }
- }
-
/// <summary>
/// Is never called
/// </summary>
{
}
- public override Type Resolve (IResolveContext ec)
+ public override TypeSpec Resolve (IMemberContext ec, int index)
{
if (parameter_type == null)
throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set",
Name);
+ base.idx = index;
return parameter_type;
}
- public Type Type {
+ public TypeSpec Type {
set { parameter_type = value; }
}
}
{
}
- public override Type Resolve (IResolveContext ec)
+ public override TypeSpec Resolve (IMemberContext ec, int index)
{
- if (base.Resolve (ec) == null)
+ if (base.Resolve (ec, index) == null)
return null;
- if (!parameter_type.IsArray || parameter_type.GetArrayRank () != 1) {
- Report.Error (225, Location, "The params parameter must be a single dimensional array");
+ 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");
return null;
}
public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
{
base.ApplyAttributes (mb, cb, index);
- PredefinedAttributes.Get.ParamArray.EmitAttribute (builder, Location);
+ PredefinedAttributes.Get.ParamArray.EmitAttribute (builder);
}
}
public class ArglistParameter : Parameter {
// 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)
+ base (null, String.Empty, Parameter.Modifier.NONE, null, loc)
{
+ parameter_type = InternalType.Arglist;
}
public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
return true;
}
- public override Type Resolve (IResolveContext ec)
+ public override TypeSpec Resolve (IMemberContext ec, int index)
{
- return typeof (ArglistParameter);
- }
-
- public override string GetSignatureForError ()
- {
- return "__arglist";
+ return parameter_type;
}
}
public interface IParameterData
{
+ Expression DefaultValue { get; }
bool HasExtensionMethodModifier { get; }
+ bool HasDefaultValue { get; }
Parameter.Modifier ModFlags { get; }
string Name { get; }
}
PARAMS = 4,
// This is a flag which says that it's either REF or OUT.
ISBYREF = 8,
- ARGLIST = 16,
REFMASK = 32,
OUTMASK = 64,
This = 128
static string[] attribute_targets = new string [] { "param" };
- protected FullNamedExpression TypeName;
+ FullNamedExpression texpr;
readonly Modifier modFlags;
string name;
Expression default_expr;
- protected Type parameter_type;
+ protected TypeSpec parameter_type;
public readonly Location Location;
- int idx;
+ protected int idx;
public bool HasAddressTaken;
- IResolveContext resolve_context;
- LocalVariableReference expr_tree_variable;
+ Expression expr_tree_variable;
static TypeExpr parameter_expr_tree_type;
- public HoistedVariable HoistedVariableReference;
+ HoistedVariable hoisted_variant;
public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
- : base (attrs)
{
- if (type == TypeManager.system_void_expr)
- Report.Error (1536, loc, "Invalid parameter type `void'");
-
this.name = name;
modFlags = mod;
Location = loc;
- TypeName = type;
+ texpr = type;
+
+ // Only assign, attributes will be attached during resolve
+ base.attributes = attrs;
}
- public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Expression defaultValue, Location loc)
- : this (type, name, mod, attrs, loc)
- {
- default_expr = defaultValue;
+#region Properties
+ public FullNamedExpression TypeExpression {
+ get {
+ return texpr;
+ }
}
+#endregion
- public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
+ public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
{
if (a.Type == pa.In && ModFlags == Modifier.OUT) {
- Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
+ a.Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
return;
}
if (a.Type == pa.ParamArray) {
- Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
+ a.Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
return;
}
if (a.Type == PredefinedAttributes.Get.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
!OptAttributes.Contains (pa.In)) {
- Report.Error (662, a.Location,
+ a.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 == pa.CLSCompliant) {
- Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
+ 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)) {
- Report.Error (1745, a.Location,
+ 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) {
- object val = a.GetParameterDefaultValue ();
- if (val != null) {
- Type t = val.GetType ();
- if (t.IsArray || TypeManager.IsSubclassOf (t, TypeManager.type_type)) {
- if (parameter_type == TypeManager.object_type) {
- if (!t.IsArray)
- t = TypeManager.type_type;
-
- 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 DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
- TypeManager.CSharpName (parameter_type)); ;
- }
- return;
+ 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 ()); ;
}
+
+ return;
}
- if (parameter_type == TypeManager.object_type ||
- (val == null && !TypeManager.IsGenericParameter (parameter_type) && TypeManager.IsReferenceType (parameter_type)) ||
- (val != null && TypeManager.TypeToCoreType (val.GetType ()) == parameter_type))
- builder.SetConstant (val);
+ 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
- Report.Error (1908, a.Location, "The type of the default value should match the type of the parameter");
+ a.Report.Error (1908, a.Location, "The type of the default value should match the type of the parameter");
+
return;
}
- base.ApplyAttributeBuilder (a, cb, pa);
+ base.ApplyAttributeBuilder (a, ctor, cdata, pa);
}
public virtual bool CheckAccessibility (InterfaceMemberBase member)
return member.IsAccessibleAs (parameter_type);
}
- public override IResolveContext ResolveContext {
- get {
- return resolve_context;
- }
+ public static void Reset ()
+ {
+ parameter_expr_tree_type = null;
}
// <summary>
// Resolve is used in method definitions
// </summary>
- public virtual Type Resolve (IResolveContext rc)
+ public virtual TypeSpec Resolve (IMemberContext rc, int index)
{
- // HACK: to resolve attributes correctly
- this.resolve_context = rc;
-
if (parameter_type != null)
return parameter_type;
- TypeExpr texpr = TypeName.ResolveAsTypeTerminal (rc, false);
- if (texpr == null)
+ if (attributes != null)
+ attributes.AttachTo (this, rc);
+
+ var expr = texpr.ResolveAsTypeTerminal (rc, false);
+ if (expr == null)
return null;
+ this.idx = index;
+ texpr = expr;
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.DeclContainer, 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)
- Report.Error (1736, default_expr.Location, "The expression being assigned to optional parameter `{0}' must be constant",
- Name);
- } else {
- Constant c = value.ConvertImplicitly (parameter_type);
- if (c == null)
- Report.Error (1750, Location,
- "Optional parameter value `{0}' cannot be converted to parameter type `{1}'",
- value.GetValue (), GetSignatureForError ());
-
- // value = c;
- }
-
- default_expr = value;
- }
- }
-
+
if ((modFlags & Parameter.Modifier.ISBYREF) != 0 &&
TypeManager.IsSpecialType (parameter_type)) {
- Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
+ rc.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,
- rc as MemberCore);
+ rc);
- 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",
+ if (parameter_type.IsStatic) {
+ rc.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) {
- Report.Error (1103, Location, "The type of extension method cannot be `{0}'",
+ 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}'",
TypeManager.CSharpName (parameter_type));
}
return parameter_type;
}
- public void ResolveVariable (int idx)
+ public void ResolveDefaultValue (ResolveContext rc)
+ {
+ if (default_expr != null)
+ default_expr = ResolveDefaultExpression (rc);
+ }
+
+ Expression ResolveDefaultExpression (ResolveContext rc)
{
- this.idx = idx;
+ default_expr = default_expr.Resolve (rc);
+ if (default_expr == null)
+ return null;
+
+ if (!(default_expr is Constant || default_expr is DefaultValueExpression)) {
+ if (TypeManager.IsNullableType (parameter_type)) {
+ rc.Compiler.Report.Error (1770, default_expr.Location,
+ "The expression being assigned to nullable optional parameter `{0}' must be default value",
+ Name);
+ } else {
+ rc.Compiler.Report.Error (1736, default_expr.Location,
+ "The expression being assigned to optional parameter `{0}' must be a constant or default value",
+ Name);
+ }
+
+ return null;
+ }
+
+ if (TypeManager.IsEqual (default_expr.Type, parameter_type))
+ return default_expr;
+
+ if (TypeManager.IsNullableType (parameter_type)) {
+ if (Convert.ImplicitNulableConversion (rc, default_expr, parameter_type) != null)
+ return default_expr;
+ } else {
+ var res = Convert.ImplicitConversionStandard (rc, default_expr, parameter_type, default_expr.Location);
+ if (res != null) {
+ 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 ());
+
+ return null;
+ }
+
+ return res;
+ }
+ }
+
+ 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;
}
public bool HasDefaultValue {
get { return (modFlags & Modifier.This) != 0; }
}
+ //
+ // Hoisted parameter variant
+ //
+ public HoistedVariable HoistedVariant {
+ get {
+ return hoisted_variant;
+ }
+ set {
+ hoisted_variant = value;
+ }
+ }
+
public Modifier ModFlags {
get { return modFlags & ~Modifier.This; }
}
if (parameter_type != null)
type_name = TypeManager.CSharpName (parameter_type);
else
- type_name = TypeName.GetSignatureForError ();
+ type_name = texpr.GetSignatureForError ();
string mod = GetModifierSignature (modFlags);
if (mod.Length > 0)
}
}
- public void IsClsCompliant ()
+ public void IsClsCompliant (IMemberContext ctx)
{
- if (AttributeTester.IsClsCompliant (parameter_type))
+ if (parameter_type.IsCLSCompliant ())
return;
- Report.Warning (3001, 1, Location, "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
+ ctx.Compiler.Report.Warning (3001, 1, Location,
+ "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
}
public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
OptAttributes.Emit ();
if (HasDefaultValue) {
- Constant c = (Constant) default_expr;
- if (default_expr.Type == TypeManager.decimal_type) {
- builder.SetCustomAttribute (Const.CreateDecimalConstantAttribute (c));
- } else {
- builder.SetConstant (c.GetValue ());
+ //
+ // 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.GetTypedValue ());
+ }
+ }
+ }
+
+ if (parameter_type == InternalType.Dynamic) {
+ PredefinedAttributes.Get.Dynamic.EmitAttribute (builder);
+ } else {
+ var trans_flags = TypeManager.HasDynamicTypeUsed (parameter_type);
+ if (trans_flags != null) {
+ var pa = PredefinedAttributes.Get.DynamicTransform;
+ if (pa.Constructor != null || pa.ResolveConstructor (Location, ArrayContainer.MakeType (TypeManager.bool_type))) {
+ builder.SetCustomAttribute (
+ new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
+ }
}
}
}
public Parameter Clone ()
{
Parameter p = (Parameter) MemberwiseClone ();
- if (attributes != null) {
+ if (attributes != null)
p.attributes = attributes.Clone ();
- p.attributes.AttachTo (p);
- }
return p;
}
- public ExpressionStatement CreateExpressionTreeVariable (EmitContext ec)
+ public ExpressionStatement CreateExpressionTreeVariable (BlockContext 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");
-
- LocalInfo variable = ec.CurrentBlock.AddTemporaryVariable (
- ResolveParameterExpressionType (ec, Location), Location);
- variable.Resolve (ec);
+ ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
- expr_tree_variable = new LocalVariableReference (
- ec.CurrentBlock, variable.Name, Location, variable, false);
+ expr_tree_variable = new TemporaryVariable (ResolveParameterExpressionType (ec, Location).Type, Location);
+ expr_tree_variable = expr_tree_variable.Resolve (ec);
- ArrayList arguments = new ArrayList (2);
+ 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)));
return new SimpleAssign (ExpressionTreeVariableReference (),
- Expression.CreateExpressionFactoryCall ("Parameter", null, arguments, Location));
+ Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location));
+ }
+
+ public Expression DefaultValue {
+ get { return default_expr; }
+ set { default_expr = value; }
}
public void Emit (EmitContext ec)
if (!ec.IsStatic)
arg_idx++;
- ParameterReference.EmitLdArg (ec.ig, arg_idx);
+ ParameterReference.EmitLdArg (ec, arg_idx);
}
public void EmitAssign (EmitContext ec)
arg_idx++;
if (arg_idx <= 255)
- ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
+ ec.Emit (OpCodes.Starg_S, (byte) arg_idx);
else
- ec.ig.Emit (OpCodes.Starg, arg_idx);
+ ec.Emit (OpCodes.Starg, arg_idx);
}
public void EmitAddressOf (EmitContext ec)
bool is_ref = (ModFlags & Modifier.ISBYREF) != 0;
if (is_ref) {
- ParameterReference.EmitLdArg (ec.ig, arg_idx);
+ ParameterReference.EmitLdArg (ec, arg_idx);
} else {
if (arg_idx <= 255)
- ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
+ ec.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
else
- ec.ig.Emit (OpCodes.Ldarga, arg_idx);
+ ec.Emit (OpCodes.Ldarga, arg_idx);
}
}
//
// System.Linq.Expressions.ParameterExpression type
//
- public static TypeExpr ResolveParameterExpressionType (EmitContext ec, Location location)
+ public static TypeExpr ResolveParameterExpressionType (IMemberContext ec, Location location)
{
if (parameter_expr_tree_type != null)
return parameter_expr_tree_type;
- Type p_type = TypeManager.parameter_expression_type;
+ TypeSpec p_type = TypeManager.parameter_expression_type;
if (p_type == null) {
- p_type = TypeManager.CoreLookupType ("System.Linq.Expressions", "ParameterExpression", Kind.Class, true);
+ p_type = TypeManager.CoreLookupType (ec.Compiler, "System.Linq.Expressions", "ParameterExpression", MemberKind.Class, true);
TypeManager.parameter_expression_type = p_type;
}
return parameter_expr_tree_type;
}
+
+ public void Warning_UselessOptionalParameter (Report Report)
+ {
+ Report.Warning (1066, 1, Location,
+ "The default value specified for optional parameter `{0}' will never be used",
+ Name);
+ }
}
//
{
readonly string name;
readonly Parameter.Modifier modifiers;
+ readonly Expression default_value;
public ParameterData (string name, Parameter.Modifier modifiers)
{
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; }
}
// Null object pattern
protected IParameterData [] parameters;
- protected Type [] types;
+ protected TypeSpec [] types;
+
+ public CallingConventions CallingConvention {
+ get {
+ return has_arglist ?
+ CallingConventions.VarArgs :
+ CallingConventions.Standard;
+ }
+ }
public int Count {
get { return parameters.Length; }
}
- public Type ExtensionMethodType {
+ public TypeSpec ExtensionMethodType {
get {
if (Count == 0)
return null;
ParameterAttributes.Out : ParameterAttributes.None;
}
- public Type [] GetEmitTypes ()
+ // Very expensive operation
+ public Type[] GetMetaInfo ()
{
- Type [] types = null;
+ Type[] types;
if (has_arglist) {
if (Count == 1)
return Type.EmptyTypes;
types = new Type [Count - 1];
- Array.Copy (Types, types, types.Length);
+ } else {
+ if (Count == 0)
+ return Type.EmptyTypes;
+
+ types = new Type [Count];
}
- for (int i = 0; i < Count; ++i) {
+ for (int i = 0; i < types.Length; ++i) {
+ types[i] = Types[i].GetMetaInfo ();
+
if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0)
continue;
- if (types == null)
- types = (Type []) Types.Clone ();
-
- types [i] = TypeManager.GetReferenceType (types [i]);
+ // TODO MemberCache: Should go to MetaInfo getter
+ types [i] = types [i].MakeByRefType ();
}
- if (types == null)
- types = Types;
-
return types;
}
+ //
+ // Returns the parameter information based on the name
+ //
+ public int GetParameterIndexByName (string name)
+ {
+ for (int idx = 0; idx < Count; ++idx) {
+ if (parameters [idx].Name == name)
+ return idx;
+ }
+
+ return -1;
+ }
+
public string GetSignatureForError ()
{
- StringBuilder sb = new StringBuilder ("(");
- for (int i = 0; i < Count; ++i) {
+ return GetSignatureForError ("(", ")", Count);
+ }
+
+ public string GetSignatureForError (string start, string end, int count)
+ {
+ StringBuilder sb = new StringBuilder (start);
+ for (int i = 0; i < count; ++i) {
if (i != 0)
sb.Append (", ");
sb.Append (ParameterDesc (i));
}
- sb.Append (')');
+ sb.Append (end);
return sb.ToString ();
}
get { return parameters.Length == 0; }
}
+ public AParametersCollection Inflate (TypeParameterInflator inflator)
+ {
+ TypeSpec[] inflated_types = null;
+ bool default_value = false;
+
+ for (int i = 0; i < Count; ++i) {
+ var inflated_param = inflator.Inflate (types[i]);
+ if (inflated_types == null) {
+ if (inflated_param == types[i])
+ continue;
+
+ default_value |= FixedParameters[i] is DefaultValueExpression;
+ inflated_types = new TypeSpec[types.Length];
+ Array.Copy (types, inflated_types, types.Length);
+ }
+
+ inflated_types[i] = inflated_param;
+ }
+
+ if (inflated_types == null)
+ return this;
+
+ var clone = (AParametersCollection) MemberwiseClone ();
+ clone.types = inflated_types;
+ if (default_value) {
+ 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 ();
+ }
+ }
+ }
+
+ return clone;
+ }
+
public string ParameterDesc (int pos)
{
if (types == null || types [pos] == null)
if (FixedParameters [pos].HasExtensionMethodModifier)
return "this " + type;
- Parameter.Modifier mod = FixedParameters [pos].ModFlags & ~Parameter.Modifier.ARGLIST;
+ Parameter.Modifier mod = FixedParameters [pos].ModFlags;
if (mod == 0)
return type;
return Parameter.GetModifierSignature (mod) + " " + type;
}
- public Type[] Types {
+ public TypeSpec[] 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;
- }
- }
-
- return p;
- }
-#endif
}
//
//
public class ParametersImported : AParametersCollection
{
- ParametersImported (AParametersCollection param, Type[] types)
+ ParametersImported (AParametersCollection param, TypeSpec[] types)
{
this.parameters = param.FixedParameters;
this.types = types;
has_params = param.HasParams;
}
- ParametersImported (IParameterData [] parameters, Type [] types, MethodBase method, bool hasParams)
+ ParametersImported (IParameterData [] parameters, TypeSpec [] types, bool hasArglist, 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;
+ this.has_arglist = hasArglist;
+ this.has_params = hasParams;
}
- public ParametersImported (IParameterData [] param, Type[] types)
+ public ParametersImported (IParameterData [] param, TypeSpec[] types)
{
this.parameters = param;
this.types = types;
}
- public static AParametersCollection Create (MethodBase method)
+ public static AParametersCollection Create (TypeSpec parent, MethodBase method)
{
- return Create (method.GetParameters (), method);
+ return Create (parent, method.GetParameters (), method);
}
//
- // Generic method parameters importer, param is shared between all instances
+ // Imports System.Reflection parameters
//
- public static AParametersCollection Create (AParametersCollection param, MethodBase method)
+ public static AParametersCollection Create (TypeSpec parent, ParameterInfo [] pi, MethodBase method)
{
- if (param.IsEmpty)
- return param;
-
- 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);
- }
-
- //
- // 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);
+ int varargs = method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0 ? 1 : 0;
+ if (pi.Length == 0 && varargs == 0)
return ParametersCompiled.EmptyReadOnlyParameters;
- }
- Type [] types = new Type [pi.Length];
- IParameterData [] par = new IParameterData [pi.Length];
+ TypeSpec [] types = new TypeSpec [pi.Length + varargs];
+ IParameterData [] par = new IParameterData [pi.Length + varargs];
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);
-
+ for (int i = 0; i < pi.Length; i++) {
ParameterInfo p = pi [i];
Parameter.Modifier mod = 0;
- if (types [i].IsByRef) {
+ Expression default_value = null;
+ if (p.ParameterType.IsByRef) {
if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out)
mod = Parameter.Modifier.OUT;
else
//
// 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)) {
+ types [i] = Import.ImportType (p.ParameterType.GetElementType ());
+ } else if (i == 0 && method.IsStatic && parent.IsStatic && // TODO: parent.Assembly.IsExtension &&
+ HasExtensionAttribute (method)) {
mod = Parameter.Modifier.This;
- } else if (i >= pi.Length - 2) {
- if (types[i].IsArray) {
- if (p.IsDefined (param_attr.Type, false)) {
+ types[i] = Import.ImportType (p.ParameterType);
+ } else {
+ types[i] = Import.ImportType (p.ParameterType);
+
+ if (i >= pi.Length - 2 && types[i] is ArrayContainer) {
+ var cattrs = CustomAttributeData.GetCustomAttributes (p);
+ if (cattrs != null && cattrs.Any (l => l.Constructor.DeclaringType == typeof (ParamArrayAttribute))) {
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) {
+ object value = p.DefaultValue;
+ if (value == Missing.Value) {
+ default_value = EmptyExpression.Null;
+ } else if (value == null) {
+ default_value = new NullLiteral (Location.Null);
+ } else {
+ default_value = Constant.CreateConstant (null, Import.ImportType (value.GetType ()), value, Location.Null);
+ }
}
}
- par [i] = new ParameterData (p.Name, mod);
+ par [i] = new ParameterData (p.Name, mod, default_value);
+ }
+
+ if (varargs != 0) {
+ par [par.Length - 1] = new ArglistParameter (Location.Null);
+ types [types.Length - 1] = InternalType.Arglist;
}
return method != null ?
- new ParametersImported (par, types, method, is_params) :
+ new ParametersImported (par, types, varargs != 0, is_params) :
new ParametersImported (par, types);
}
+
+ static bool HasExtensionAttribute (MethodBase mb)
+ {
+ var all_attributes = CustomAttributeData.GetCustomAttributes (mb);
+ foreach (var attr in all_attributes) {
+ var dt = attr.Constructor.DeclaringType;
+ if (dt.Name == "ExtensionAttribute" && dt.Namespace == "System.Runtime.CompilerServices") {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
/// <summary>
private ParametersCompiled ()
{
parameters = new Parameter [0];
- types = Type.EmptyTypes;
+ types = TypeSpec.EmptyTypes;
}
- private ParametersCompiled (Parameter [] parameters, Type [] types)
+ private ParametersCompiled (IParameterData [] parameters, TypeSpec [] types)
{
this.parameters = parameters;
this.types = types;
}
- public ParametersCompiled (params Parameter[] parameters)
+ public ParametersCompiled (CompilerContext ctx, params Parameter[] parameters)
{
if (parameters == null)
throw new ArgumentException ("Use EmptyReadOnlyParameters");
if (base_name != parameters [j].Name)
continue;
- ErrorDuplicateName (parameters [i]);
+ ErrorDuplicateName (parameters[i], ctx.Report);
i = j;
}
}
}
- public ParametersCompiled (Parameter [] parameters, bool has_arglist) :
- this (parameters)
+ public ParametersCompiled (CompilerContext ctx, Parameter [] parameters, bool has_arglist) :
+ this (ctx, parameters)
{
this.has_arglist = has_arglist;
}
- public static ParametersCompiled CreateFullyResolved (Parameter p, Type type)
+ public static ParametersCompiled CreateFullyResolved (Parameter p, TypeSpec type)
{
- return new ParametersCompiled (new Parameter [] { p }, new Type [] { type });
+ return new ParametersCompiled (new Parameter [] { p }, new TypeSpec [] { type });
}
- public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, Type[] types)
+ public static ParametersCompiled CreateFullyResolved (IParameterData[] parameters, TypeSpec[] types)
{
return new ParametersCompiled (parameters, types);
}
- public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, Type compilerTypes)
+ public static AParametersCollection CreateFullyResolved (TypeSpec[] types)
+ {
+ var pd = new ParameterData [types.Length];
+ for (int i = 0; i < pd.Length; ++i)
+ pd[i] = new ParameterData (null, Parameter.Modifier.NONE, null);
+
+ return new ParametersCompiled (pd, types);
+ }
+
+ public static ParametersCompiled CreateImplicitParameter (FullNamedExpression texpr, Location loc)
+ {
+ return new ParametersCompiled (
+ new[] { new Parameter (texpr, "value", Parameter.Modifier.NONE, null, loc) },
+ null);
+ }
+
+ //
+ // Returns non-zero value for equal CLS parameter signatures
+ //
+ public static int IsSameClsSignature (AParametersCollection a, AParametersCollection b)
+ {
+ int res = 0;
+
+ for (int i = 0; i < a.Count; ++i) {
+ 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))
+ res |= 1;
+
+ continue;
+ }
+
+ var ac_a = a_type as ArrayContainer;
+ if (ac_a == null)
+ return 0;
+
+ var ac_b = b_type as ArrayContainer;
+ if (ac_b == null)
+ return 0;
+
+ if (ac_a.Element is ArrayContainer || ac_b.Element is ArrayContainer) {
+ res |= 2;
+ continue;
+ }
+
+ if (ac_a.Rank != ac_b.Rank && TypeSpecComparer.Override.IsEqual (ac_a.Element, ac_b.Element)) {
+ res |= 1;
+ continue;
+ }
+
+ return 0;
+ }
+
+ return res;
+ }
+
+ public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, TypeSpec compilerTypes)
{
- return MergeGenerated (userParams, checkConflicts,
+ return MergeGenerated (ctx, userParams, checkConflicts,
new Parameter [] { compilerParams },
- new Type [] { compilerTypes });
+ new TypeSpec [] { compilerTypes });
}
//
// Use this method when you merge compiler generated parameters with user parameters
//
- public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, Type[] compilerTypes)
+ public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, TypeSpec[] compilerTypes)
{
Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
userParams.FixedParameters.CopyTo(all_params, 0);
- Type [] all_types;
+ TypeSpec [] all_types;
if (userParams.types != null) {
- all_types = new Type [all_params.Length];
+ all_types = new TypeSpec [all_params.Length];
userParams.Types.CopyTo (all_types, 0);
} else {
all_types = null;
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,
+ ctx.Report.Error (316, userParams[i].Location,
"The parameter name `{0}' conflicts with a compiler generated name", p.Name);
}
p.Name = '_' + p.Name;
return parameters;
}
- protected virtual void ErrorDuplicateName (Parameter p)
+ protected virtual void ErrorDuplicateName (Parameter p, Report Report)
{
Report.Error (100, p.Location, "The parameter name `{0}' is a duplicate", p.Name);
}
- /// <summary>
- /// Returns the parameter information based on the name
- /// </summary>
- public int GetParameterIndexByName (string name)
- {
- for (int idx = 0; idx < Count; ++idx) {
- if (parameters [idx].Name == name)
- return idx;
- }
-
- return -1;
- }
-
- public bool Resolve (IResolveContext ec)
+ public bool Resolve (IMemberContext ec)
{
if (types != null)
return true;
- types = new Type [Count];
+ types = new TypeSpec [Count];
bool ok = true;
Parameter p;
for (int i = 0; i < FixedParameters.Length; ++i) {
p = this [i];
- Type t = p.Resolve (ec);
+ TypeSpec t = p.Resolve (ec, i);
if (t == null) {
ok = false;
continue;
return ok;
}
- public void ResolveVariable ()
+ public void ResolveDefaultValues (ResolveContext rc)
{
for (int i = 0; i < FixedParameters.Length; ++i) {
- this [i].ResolveVariable (i);
- }
- }
-
- public CallingConventions CallingConvention
- {
- get {
- if (HasArglist)
- return CallingConventions.VarArgs;
- else
- return CallingConventions.Standard;
+ this [i].ResolveDefaultValue (rc);
}
}
}
}
- public void VerifyClsCompliance ()
+ public void VerifyClsCompliance (IMemberContext ctx)
{
foreach (Parameter p in FixedParameters)
- p.IsClsCompliant ();
+ p.IsClsCompliant (ctx);
}
public Parameter this [int pos] {
get { return (Parameter) parameters [pos]; }
}
- public Expression CreateExpressionTree (EmitContext ec, Location loc)
+ public Expression CreateExpressionTree (BlockContext ec, Location loc)
{
- ArrayList initializers = new ArrayList (Count);
+ var initializers = new ArrayInitializer (Count, loc);
foreach (Parameter p in FixedParameters) {
//
// Each parameter expression is stored to local variable
return new ArrayCreation (
Parameter.ResolveParameterExpressionType (ec, loc),
- "[]", initializers, loc);
+ initializers, loc);
}
public ParametersCompiled Clone ()