//
//
using System;
+using System.Text;
+
+#if STATIC
+using MetaType = IKVM.Reflection.Type;
+using IKVM.Reflection;
+using IKVM.Reflection.Emit;
+#else
+using MetaType = System.Type;
using System.Reflection;
using System.Reflection.Emit;
-using System.Text;
-using System.Linq;
+#endif
namespace Mono.CSharp {
}
}
- /// <summary>
- /// Class for applying custom attributes on the implicit parameter type
- /// of the 'set' method in properties, and the 'add' and 'remove' methods in events.
- /// </summary>
- ///
- // TODO: should use more code from Parameter.ApplyAttributeBuilder
- public class ImplicitParameter : ParameterBase {
- public ImplicitParameter (MethodBuilder mb)
- {
- builder = mb.DefineParameter (1, ParameterAttributes.None, "value");
- }
-
- public override AttributeTargets AttributeTargets {
- get {
- return AttributeTargets.Parameter;
- }
- }
-
- /// <summary>
- /// Is never called
- /// </summary>
- public override string[] ValidAttributeTargets {
- get {
- return null;
- }
- }
- }
-
public class ImplicitLambdaParameter : Parameter
{
public ImplicitLambdaParameter (string name, Location loc)
return parameter_type;
}
- public TypeSpec Type {
- set { parameter_type = value; }
+ public void SetParameterType (TypeSpec type)
+ {
+ parameter_type = type;
}
}
var ac = parameter_type as ArrayContainer;
if (ac == null || ac.Rank != 1) {
- ec.Compiler.Report.Error (225, Location, "The params parameter must be a single dimensional array");
+ ec.Module.Compiler.Report.Error (225, Location, "The params parameter must be a single dimensional array");
return null;
}
return parameter_type;
}
- public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
+ public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
{
- base.ApplyAttributes (mb, cb, index);
- PredefinedAttributes.Get.ParamArray.EmitAttribute (builder);
+ base.ApplyAttributes (mb, cb, index, pa);
+ pa.ParamArray.EmitAttribute (builder);
}
}
parameter_type = InternalType.Arglist;
}
- public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
+ public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
{
// Nothing to do
}
//
// Parameter information created by parser
//
- public class Parameter : ParameterBase, IParameterData, ILocalVariable {
+ public class Parameter : ParameterBase, IParameterData, ILocalVariable // TODO: INamedBlockVariable
+ {
[Flags]
public enum Modifier : byte {
NONE = 0,
ISBYREF = 8,
REFMASK = 32,
OUTMASK = 64,
+ SignatureMask = REFMASK | OUTMASK,
This = 128
}
- static string[] attribute_targets = new string [] { "param" };
+ static readonly string[] attribute_targets = new string[] { "param" };
FullNamedExpression texpr;
readonly Modifier modFlags;
string name;
Expression default_expr;
protected TypeSpec parameter_type;
- public readonly Location Location;
+ readonly Location loc;
protected int idx;
public bool HasAddressTaken;
- Expression expr_tree_variable;
- static TypeExpr parameter_expr_tree_type;
+ TemporaryVariableReference expr_tree_variable;
HoistedVariable hoisted_variant;
{
this.name = name;
modFlags = mod;
- Location = loc;
+ this.loc = loc;
texpr = type;
// Only assign, attributes will be attached during resolve
base.attributes = attrs;
}
-#region Properties
- public Expression DefaultValue {
+ #region Properties
+
+ public DefaultParameterValueExpression DefaultValue {
get {
- return default_expr;
+ return default_expr as DefaultParameterValueExpression;
}
set {
default_expr = value;
}
}
+ Expression IParameterData.DefaultValue {
+ get {
+ var expr = default_expr as DefaultParameterValueExpression;
+ return expr == null ? default_expr : expr.Child;
+ }
+ }
+
+ bool HasOptionalExpression {
+ get {
+ return default_expr is DefaultParameterValueExpression;
+ }
+ }
+
+ public Location Location {
+ get {
+ return loc;
+ }
+ }
+
+ public TypeSpec Type {
+ get {
+ return parameter_type;
+ }
+ set {
+ parameter_type = value;
+ }
+ }
+
public FullNamedExpression TypeExpression {
get {
return texpr;
}
}
-#endregion
+
+ public override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
+
+ #endregion
public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
{
return;
}
- if (a.Type == PredefinedAttributes.Get.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
+ if (a.Type == pa.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
!OptAttributes.Contains (pa.In)) {
a.Report.Error (662, a.Location,
"Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
}
- if (HasDefaultValue && (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter)) {
- a.Report.Error (1745, a.Location,
- "Cannot specify `{0}' attribute on optional parameter `{1}'",
- TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
- return;
- }
-
- if (a.Type == pa.DefaultParameterValue) {
- TypeSpec arg_type;
- var c = a.GetParameterDefaultValue (out arg_type);
- if (c == null) {
- if (parameter_type == TypeManager.object_type) {
- a.Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
- arg_type.GetSignatureForError ());
- } else {
- a.Report.Error (1909, a.Location, "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
- parameter_type.GetSignatureForError ()); ;
- }
-
- return;
+ if (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter) {
+ if (HasOptionalExpression) {
+ a.Report.Error (1745, a.Location,
+ "Cannot specify `{0}' attribute on optional parameter `{1}'",
+ TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
}
- if (arg_type == parameter_type || parameter_type == TypeManager.object_type ||
- (c.IsNull && TypeManager.IsReferenceType (parameter_type) && !TypeManager.IsGenericParameter (parameter_type)))
- builder.SetConstant (c.GetValue ());
- else
- a.Report.Error (1908, a.Location, "The type of the default value should match the type of the parameter");
-
- return;
+ if (a.Type == pa.DefaultParameterValue)
+ return;
}
base.ApplyAttributeBuilder (a, ctor, cdata, pa);
public virtual bool CheckAccessibility (InterfaceMemberBase member)
{
- if (parameter_type == null || TypeManager.IsGenericParameter (parameter_type))
+ if (parameter_type == null)
return true;
return member.IsAccessibleAs (parameter_type);
}
- public static void Reset ()
- {
- parameter_expr_tree_type = null;
- }
-
// <summary>
// Resolve is used in method definitions
// </summary>
if (attributes != null)
attributes.AttachTo (this, rc);
- var expr = texpr.ResolveAsTypeTerminal (rc, false);
- if (expr == null)
+ parameter_type = texpr.ResolveAsType (rc);
+ if (parameter_type == null)
return null;
this.idx = index;
- texpr = expr;
- parameter_type = texpr.Type;
- if ((modFlags & Parameter.Modifier.ISBYREF) != 0 &&
- TypeManager.IsSpecialType (parameter_type)) {
- rc.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
+ if ((modFlags & Parameter.Modifier.ISBYREF) != 0 && parameter_type.IsSpecialRuntimeType) {
+ rc.Module.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
GetSignatureForError ());
return null;
}
rc);
if (parameter_type.IsStatic) {
- rc.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
+ rc.Module.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
texpr.GetSignatureForError ());
return parameter_type;
}
- if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || parameter_type == InternalType.Dynamic)) {
- rc.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
+ if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)) {
+ rc.Module.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
TypeManager.CSharpName (parameter_type));
}
// Default value was specified using an expression
//
if (default_expr != null) {
- default_expr = ResolveDefaultExpression (rc);
+ ((DefaultParameterValueExpression)default_expr).Resolve (rc, this);
return;
}
if (attributes == null)
return;
- var pa = attributes.Search (PredefinedAttributes.Get.OptionalParameter);
- if (pa == null)
- return;
-
- //
- // Default value was specified using an attribute
- //
- attributes.Attrs.Remove (pa);
+ var opt_attr = attributes.Search (rc.Module.PredefinedAttributes.OptionalParameter);
+ var def_attr = attributes.Search (rc.Module.PredefinedAttributes.DefaultParameterValue);
+ if (def_attr != null) {
+ if (def_attr.Resolve () == null)
+ return;
- TypeSpec expr_type = null;
- pa = attributes.Search (PredefinedAttributes.Get.DefaultParameterValue);
- if (pa != null) {
- attributes.Attrs.Remove (pa);
- default_expr = pa.GetParameterDefaultValue (out expr_type);
- } else {
- default_expr = EmptyExpression.MissingValue;
- }
+ var default_expr_attr = def_attr.GetParameterDefaultValue ();
+ if (default_expr_attr == null)
+ return;
- if (default_expr == null) {
- if (expr_type == null)
- expr_type = parameter_type;
+ var dpa_rc = def_attr.CreateResolveContext ();
+ default_expr = default_expr_attr.Resolve (dpa_rc);
- default_expr = new DefaultValueExpression (new TypeExpression (expr_type, Location), Location);
- }
+ if (default_expr is BoxedCast)
+ default_expr = ((BoxedCast) default_expr).Child;
- default_expr = default_expr.Resolve (rc);
- }
-
- Expression ResolveDefaultExpression (ResolveContext rc)
- {
- default_expr = default_expr.Resolve (rc);
- if (default_expr == null)
- return null;
+ Constant c = default_expr as Constant;
+ if (c == null) {
+ if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
+ rc.Report.Error (1910, default_expr.Location,
+ "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
+ default_expr.Type.GetSignatureForError ());
+ } else {
+ rc.Report.Error (1909, default_expr.Location,
+ "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
+ default_expr.Type.GetSignatureForError ()); ;
+ }
- if (!(default_expr 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);
+ default_expr = null;
+ return;
}
- return null;
- }
-
- if (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;
- }
+ if (TypeSpecComparer.IsEqual (default_expr.Type, parameter_type) ||
+ (default_expr is NullConstant && TypeSpec.IsReferenceType (parameter_type) && !parameter_type.IsGenericParameter) ||
+ parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
+ return;
+ }
- return res;
+ //
+ // LAMESPEC: Some really weird csc behaviour which we have to mimic
+ // User operators returning same type as parameter type are considered
+ // valid for this attribute only
+ //
+ // struct S { public static implicit operator S (int i) {} }
+ //
+ // void M ([DefaultParameterValue (3)]S s)
+ //
+ var expr = Convert.ImplicitUserConversion (dpa_rc, default_expr, parameter_type, loc);
+ if (expr != null && TypeSpecComparer.IsEqual (expr.Type, parameter_type)) {
+ return;
}
+
+ rc.Report.Error (1908, default_expr.Location, "The type of the default value should match the type of the parameter");
+ return;
}
- rc.Compiler.Report.Error (1750, Location,
- "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
- TypeManager.CSharpName (default_expr.Type), GetSignatureForError ());
-
- return null;
+ if (opt_attr != null) {
+ default_expr = EmptyExpression.MissingValue;
+ }
}
public bool HasDefaultValue {
set { name = value; }
}
- ParameterAttributes Attributes {
- get { return ParametersCompiled.GetParameterAttribute (modFlags) |
- (HasDefaultValue ? ParameterAttributes.Optional : ParameterAttributes.None); }
- }
-
public override AttributeTargets AttributeTargets {
get {
return AttributeTargets.Parameter;
}
}
+ public void Error_DuplicateName (Report r)
+ {
+ r.Error (100, Location, "The parameter name `{0}' is a duplicate", Name);
+ }
+
public virtual string GetSignatureForError ()
{
string type_name;
if (parameter_type.IsCLSCompliant ())
return;
- ctx.Compiler.Report.Warning (3001, 1, Location,
- "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
+ ctx.Module.Compiler.Report.Warning (3001, 1, Location,
+ "Argument type `{0}' is not CLS-compliant", parameter_type.GetSignatureForError ());
}
- public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
+ public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
{
+ if (builder != null)
+ throw new InternalErrorException ("builder already exists");
+
+ var pattrs = ParametersCompiled.GetParameterAttribute (modFlags);
+ if (HasOptionalExpression)
+ pattrs |= ParameterAttributes.Optional;
+
if (mb == null)
- builder = cb.DefineParameter (index, Attributes, Name);
+ builder = cb.DefineParameter (index, pattrs, Name);
else
- builder = mb.DefineParameter (index, Attributes, Name);
+ builder = mb.DefineParameter (index, pattrs, Name);
if (OptAttributes != null)
OptAttributes.Emit ();
// Emit constant values for true constants only, the other
// constant-like expressions will rely on default value expression
//
- Constant c = default_expr as Constant;
+ var def_value = DefaultValue;
+ Constant c = def_value != null ? def_value.Child as Constant : default_expr as Constant;
if (c != null) {
- if (default_expr.Type == TypeManager.decimal_type) {
- builder.SetCustomAttribute (Const.CreateDecimalConstantAttribute (c));
+ if (c.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
+ pa.DecimalConstant.EmitAttribute (builder, (decimal) c.GetValue (), c.Location);
} else {
- builder.SetConstant (c.GetTypedValue ());
+ builder.SetConstant (c.GetValue ());
}
+ } else if (default_expr.Type.IsStruct) {
+ //
+ // Handles special case where default expression is used with value-type
+ //
+ // void Foo (S s = default (S)) {}
+ //
+ builder.SetConstant (null);
}
}
- if (parameter_type == 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 }));
- }
+ if (parameter_type != null) {
+ if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
+ pa.Dynamic.EmitAttribute (builder);
+ } else if (parameter_type.HasDynamicElement) {
+ pa.Dynamic.EmitAttribute (builder, parameter_type, Location);
}
}
}
- public override string[] ValidAttributeTargets {
- get {
- return attribute_targets;
- }
- }
-
public Parameter Clone ()
{
Parameter p = (Parameter) MemberwiseClone ();
if ((modFlags & Modifier.ISBYREF) != 0)
ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
- expr_tree_variable = new TemporaryVariable (ResolveParameterExpressionType (ec, Location).Type, Location);
- expr_tree_variable = expr_tree_variable.Resolve (ec);
+ expr_tree_variable = TemporaryVariableReference.Create (ResolveParameterExpressionType (ec, Location).Type, ec.CurrentBlock.ParametersBlock, Location);
+ expr_tree_variable = (TemporaryVariableReference) expr_tree_variable.Resolve (ec);
Arguments arguments = new Arguments (2);
- arguments.Add (new Argument (new TypeOf (
- new TypeExpression (parameter_type, Location), Location)));
- arguments.Add (new Argument (new StringConstant (Name, Location)));
+ arguments.Add (new Argument (new TypeOf (parameter_type, Location)));
+ arguments.Add (new Argument (new StringConstant (ec.BuiltinTypes, Name, Location)));
return new SimpleAssign (ExpressionTreeVariableReference (),
Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location));
}
public void Emit (EmitContext ec)
{
- int arg_idx = idx;
- if (!ec.IsStatic)
- arg_idx++;
-
- ParameterReference.EmitLdArg (ec, arg_idx);
+ ec.EmitArgumentLoad (idx);
}
public void EmitAssign (EmitContext ec)
{
- int arg_idx = idx;
- if (!ec.IsStatic)
- arg_idx++;
-
- if (arg_idx <= 255)
- ec.Emit (OpCodes.Starg_S, (byte) arg_idx);
- else
- ec.Emit (OpCodes.Starg, arg_idx);
+ ec.EmitArgumentStore (idx);
}
public void EmitAddressOf (EmitContext ec)
{
- int arg_idx = idx;
-
- if (!ec.IsStatic)
- arg_idx++;
-
- bool is_ref = (ModFlags & Modifier.ISBYREF) != 0;
- if (is_ref) {
- ParameterReference.EmitLdArg (ec, arg_idx);
+ if ((ModFlags & Modifier.ISBYREF) != 0) {
+ ec.EmitArgumentLoad (idx);
} else {
- if (arg_idx <= 255)
- ec.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
- else
- ec.Emit (OpCodes.Ldarga, arg_idx);
+ ec.EmitArgumentAddress (idx);
}
}
- public Expression ExpressionTreeVariableReference ()
+ public TemporaryVariableReference ExpressionTreeVariableReference ()
{
return expr_tree_variable;
}
//
public static TypeExpr ResolveParameterExpressionType (IMemberContext ec, Location location)
{
- if (parameter_expr_tree_type != null)
- return parameter_expr_tree_type;
-
- TypeSpec p_type = TypeManager.parameter_expression_type;
- if (p_type == null) {
- p_type = TypeManager.CoreLookupType (ec.Compiler, "System.Linq.Expressions", "ParameterExpression", MemberKind.Class, true);
- TypeManager.parameter_expression_type = p_type;
- }
-
- parameter_expr_tree_type = new TypeExpression (p_type, location).
- ResolveAsTypeTerminal (ec, false);
-
- return parameter_expr_tree_type;
+ TypeSpec p_type = ec.Module.PredefinedTypes.ParameterExpression.Resolve ();
+ return new TypeExpression (p_type, location);
}
public void Warning_UselessOptionalParameter (Report Report)
}
// Very expensive operation
- public Type[] GetMetaInfo ()
+ public MetaType[] GetMetaInfo ()
{
- Type[] types;
+ MetaType[] types;
if (has_arglist) {
if (Count == 1)
- return Type.EmptyTypes;
+ return MetaType.EmptyTypes;
- types = new Type [Count - 1];
+ types = new MetaType[Count - 1];
} else {
if (Count == 0)
- return Type.EmptyTypes;
+ return MetaType.EmptyTypes;
- types = new Type [Count];
+ types = new MetaType[Count];
}
for (int i = 0; i < types.Length; ++i) {
return -1;
}
+ public string GetSignatureForDocumentation ()
+ {
+ if (IsEmpty)
+ return string.Empty;
+
+ StringBuilder sb = new StringBuilder ("(");
+ for (int i = 0; i < Count; ++i) {
+ if (i != 0)
+ sb.Append (",");
+
+ sb.Append (types [i].GetSignatureForDocumentation ());
+
+ if ((parameters[i].ModFlags & Parameter.Modifier.ISBYREF) != 0)
+ sb.Append ("@");
+ }
+ sb.Append (")");
+
+ return sb.ToString ();
+ }
+
public string GetSignatureForError ()
{
return GetSignatureForError ("(", ")", Count);
//
public class ParametersImported : AParametersCollection
{
- ParametersImported (AParametersCollection param, TypeSpec[] types)
- {
- this.parameters = param.FixedParameters;
- this.types = types;
- has_arglist = param.HasArglist;
- has_params = param.HasParams;
- }
-
- ParametersImported (IParameterData [] parameters, TypeSpec [] types, bool hasArglist, bool hasParams)
+ public ParametersImported (IParameterData [] parameters, TypeSpec [] types, bool hasArglist, bool hasParams)
{
this.parameters = parameters;
this.types = types;
this.types = types;
this.has_params = hasParams;
}
-
- public static AParametersCollection Create (TypeSpec parent, MethodBase method)
- {
- return Create (parent, method.GetParameters (), method);
- }
-
- //
- // Imports System.Reflection parameters
- //
- public static AParametersCollection Create (TypeSpec parent, ParameterInfo [] pi, MethodBase method)
- {
- int varargs = method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0 ? 1 : 0;
-
- if (pi.Length == 0 && varargs == 0)
- return ParametersCompiled.EmptyReadOnlyParameters;
-
- TypeSpec [] types = new TypeSpec [pi.Length + varargs];
- IParameterData [] par = new IParameterData [pi.Length + varargs];
- bool is_params = false;
- for (int i = 0; i < pi.Length; i++) {
- ParameterInfo p = pi [i];
- Parameter.Modifier mod = 0;
- Expression default_value = null;
- if (p.ParameterType.IsByRef) {
- if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out)
- mod = Parameter.Modifier.OUT;
- else
- mod = Parameter.Modifier.REF;
-
- //
- // Strip reference wrapping
- //
- 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;
- 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;
- }
- }
-
- 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, 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, varargs != 0, is_params) :
- new ParametersImported (par, types, is_params);
- }
-
- 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>
this.types = types;
}
- public ParametersCompiled (CompilerContext ctx, params Parameter[] parameters)
+ public ParametersCompiled (params Parameter[] parameters)
{
- if (parameters == null)
+ if (parameters == null || parameters.Length == 0)
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++){
has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
- if (ctx != null) {
- string base_name = parameters[i].Name;
-
- for (int j = i + 1; j < count; j++) {
- if (base_name != parameters[j].Name)
- continue;
-
- ErrorDuplicateName (parameters[i], ctx.Report);
- i = j;
- }
- }
}
}
- public ParametersCompiled (CompilerContext ctx, Parameter [] parameters, bool has_arglist) :
- this (ctx, parameters)
+ public ParametersCompiled (Parameter [] parameters, bool has_arglist) :
+ this (parameters)
{
this.has_arglist = has_arglist;
}
// TODO: This does not fit here, it should go to different version of AParametersCollection
// as the underlying type is not Parameter and some methods will fail to cast
//
- public static AParametersCollection CreateFullyResolved (TypeSpec[] types)
+ public static AParametersCollection CreateFullyResolved (params TypeSpec[] types)
{
var pd = new ParameterData [types.Length];
for (int i = 0; i < pd.Length; ++i)
null);
}
+ public void CheckConstraints (IMemberContext mc)
+ {
+ foreach (Parameter p in parameters) {
+ //
+ // It's null for compiler generated types or special types like __arglist
+ //
+ if (p.TypeExpression != null)
+ ConstraintChecker.Check (mc, p.Type, p.TypeExpression.Location);
+ }
+ }
+
//
// Returns non-zero value for equal CLS parameter signatures
//
return parameters;
}
- protected virtual void ErrorDuplicateName (Parameter p, Report Report)
+ //
+ // Parameters checks for members which don't have a block
+ //
+ public void CheckParameters (MemberCore member)
{
- Report.Error (100, p.Location, "The parameter name `{0}' is a duplicate", p.Name);
+ for (int i = 0; i < parameters.Length; ++i) {
+ var name = parameters[i].Name;
+ for (int ii = i + 1; ii < parameters.Length; ++ii) {
+ if (parameters[ii].Name == name)
+ this[ii].Error_DuplicateName (member.Compiler.Report);
+ }
+ }
}
public bool Resolve (IMemberContext ec)
public void ResolveDefaultValues (MemberCore m)
{
- var count = parameters.Length;
+ ResolveContext rc = null;
+ for (int i = 0; i < parameters.Length; ++i) {
+ Parameter p = (Parameter) parameters [i];
- //
- // Try not to enter default values resolution if there are not any
- //
- if (parameters[count - 1].HasDefaultValue || (HasParams && count > 1 && parameters[count - 2].HasDefaultValue) ||
- ((Parameter) parameters[count - 1]).OptAttributes != null) {
- var rc = new ResolveContext (m);
- for (int i = 0; i < count; ++i) {
- this [i].ResolveDefaultValue (rc);
+ //
+ // Try not to enter default values resolution if there are is not any default value possible
+ //
+ if (p.HasDefaultValue || p.OptAttributes != null) {
+ if (rc == null)
+ rc = new ResolveContext (m);
+
+ p.ResolveDefaultValue (rc);
}
}
}
// Define each type attribute (in/out/ref) and
// the argument names.
- public void ApplyAttributes (MethodBase builder)
+ public void ApplyAttributes (IMemberContext mc, MethodBase builder)
{
if (Count == 0)
return;
MethodBuilder mb = builder as MethodBuilder;
ConstructorBuilder cb = builder as ConstructorBuilder;
+ var pa = mc.Module.PredefinedAttributes;
for (int i = 0; i < Count; i++) {
- this [i].ApplyAttributes (mb, cb, i + 1);
+ this [i].ApplyAttributes (mb, cb, i + 1, pa);
}
}
// to save some memory when referenced later.
//
StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
- if (se.Resolve (ec))
+ if (se.Resolve (ec)) {
+ ec.CurrentBlock.AddScopeStatement (new TemporaryVariableReference.Declarator (p.ExpressionTreeVariableReference ()));
ec.CurrentBlock.AddScopeStatement (se);
+ }
initializers.Add (p.ExpressionTreeVariableReference ());
}
return p;
}
}
+
+ //
+ // Default parameter value expression. We need this wrapper to handle
+ // default parameter values of folded constants when for indexer parameters
+ // The expression is resolved only once but applied to two methods which
+ // both share reference to this expression and we ensure that resolving
+ // this expression always returns same instance
+ //
+ public class DefaultParameterValueExpression : CompositeExpression
+ {
+ public DefaultParameterValueExpression (Expression expr)
+ : base (expr)
+ {
+ }
+
+ protected override Expression DoResolve (ResolveContext rc)
+ {
+ return base.DoResolve (rc);
+ }
+
+ public void Resolve (ResolveContext rc, Parameter p)
+ {
+ var expr = Resolve (rc);
+ if (expr == null)
+ return;
+
+ expr = Child;
+
+ if (!(expr is Constant || expr is DefaultValueExpression || (expr is New && ((New) expr).IsDefaultStruct))) {
+ rc.Report.Error (1736, Location,
+ "The expression being assigned to optional parameter `{0}' must be a constant or default value",
+ p.Name);
+
+ return;
+ }
+
+ var parameter_type = p.Type;
+ if (type == parameter_type)
+ return;
+
+ var res = Convert.ImplicitConversionStandard (rc, expr, parameter_type, Location);
+ if (res != null) {
+ if (parameter_type.IsNullableType && res is Nullable.Wrap) {
+ Nullable.Wrap wrap = (Nullable.Wrap) res;
+ res = wrap.Child;
+ if (!(res is Constant)) {
+ rc.Report.Error (1770, Location,
+ "The expression being assigned to nullable optional parameter `{0}' must be default value",
+ p.Name);
+ return;
+ }
+ }
+
+ if (!expr.IsNull && TypeSpec.IsReferenceType (parameter_type) && parameter_type.BuiltinType != BuiltinTypeSpec.Type.String) {
+ rc.Report.Error (1763, Location,
+ "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
+ p.Name, parameter_type.GetSignatureForError ());
+
+ return;
+ }
+
+ this.expr = res;
+ return;
+ }
+
+ rc.Report.Error (1750, Location,
+ "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
+ type.GetSignatureForError (), parameter_type.GetSignatureForError ());
+ }
+ }
}