2
// parameter.cs: Parameter definition.
4
// Author: Miguel de Icaza (miguel@gnu.org)
5
// Marek Safar (marek.safar@seznam.cz)
7
// Dual licensed under the terms of the MIT X11 or GNU GPL
9
// Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10
// Copyright 2003-2008 Novell, Inc.
11
// Copyright 2011 Xamarin Inc
18
using MetaType = IKVM.Reflection.Type;
19
using IKVM.Reflection;
20
using IKVM.Reflection.Emit;
22
using MetaType = System.Type;
23
using System.Reflection;
24
using System.Reflection.Emit;
27
namespace Mono.CSharp {
30
/// Abstract Base class for parameters of a method.
32
public abstract class ParameterBase : Attributable
34
protected ParameterBuilder builder;
36
public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
39
if (a.Type == pa.MarshalAs) {
40
UnmanagedMarshal marshal = a.GetMarshal (this);
41
if (marshal != null) {
42
builder.SetMarshal (marshal);
47
if (a.HasSecurityAttribute) {
48
a.Error_InvalidSecurityParent ();
52
if (a.Type == pa.Dynamic) {
53
a.Error_MisusedDynamicAttribute ();
57
builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
60
public ParameterBuilder Builder {
66
public override bool IsClsComplianceRequired()
73
/// Class for applying custom attributes on the return type
75
public class ReturnParameter : ParameterBase
79
// TODO: merge method and mb
80
public ReturnParameter (MemberCore method, MethodBuilder mb, Location location)
84
builder = mb.DefineParameter (0, ParameterAttributes.None, "");
86
catch (ArgumentOutOfRangeException) {
87
method.Compiler.Report.RuntimeMissingSupport (location, "custom attributes on the return type");
91
public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
93
if (a.Type == pa.CLSCompliant) {
94
method.Compiler.Report.Warning (3023, 1, a.Location,
95
"CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
98
// This occurs after Warning -28
102
base.ApplyAttributeBuilder (a, ctor, cdata, pa);
105
public override AttributeTargets AttributeTargets {
107
return AttributeTargets.ReturnValue;
114
public override string[] ValidAttributeTargets {
121
public class ImplicitLambdaParameter : Parameter
123
public ImplicitLambdaParameter (string name, Location loc)
124
: base (null, name, Modifier.NONE, null, loc)
128
public override TypeSpec Resolve (IMemberContext ec, int index)
130
if (parameter_type == null)
131
throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set",
135
return parameter_type;
138
public void SetParameterType (TypeSpec type)
140
parameter_type = type;
144
public class ParamsParameter : Parameter {
145
public ParamsParameter (FullNamedExpression type, string name, Attributes attrs, Location loc):
146
base (type, name, Parameter.Modifier.PARAMS, attrs, loc)
150
public override TypeSpec Resolve (IMemberContext ec, int index)
152
if (base.Resolve (ec, index) == null)
155
var ac = parameter_type as ArrayContainer;
156
if (ac == null || ac.Rank != 1) {
157
ec.Module.Compiler.Report.Error (225, Location, "The params parameter must be a single dimensional array");
161
return parameter_type;
164
public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
166
base.ApplyAttributes (mb, cb, index, pa);
167
pa.ParamArray.EmitAttribute (builder);
171
public class ArglistParameter : Parameter {
172
// Doesn't have proper type because it's never chosen for better conversion
173
public ArglistParameter (Location loc) :
174
base (null, String.Empty, Parameter.Modifier.NONE, null, loc)
176
parameter_type = InternalType.Arglist;
179
public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
184
public override bool CheckAccessibility (InterfaceMemberBase member)
189
public override TypeSpec Resolve (IMemberContext ec, int index)
191
return parameter_type;
195
public interface IParameterData
197
Expression DefaultValue { get; }
198
bool HasExtensionMethodModifier { get; }
199
bool HasDefaultValue { get; }
200
Parameter.Modifier ModFlags { get; }
205
// Parameter information created by parser
207
public class Parameter : ParameterBase, IParameterData, ILocalVariable // TODO: INamedBlockVariable
210
public enum Modifier : byte {
216
CallerMemberName = 1 << 4,
217
CallerLineNumber = 1 << 5,
218
CallerFilePath = 1 << 6,
220
RefOutMask = REF | OUT,
221
ModifierMask = PARAMS | REF | OUT | This,
222
CallerMask = CallerMemberName | CallerLineNumber | CallerFilePath
225
static readonly string[] attribute_targets = new string[] { "param" };
227
FullNamedExpression texpr;
230
Expression default_expr;
231
protected TypeSpec parameter_type;
232
readonly Location loc;
234
public bool HasAddressTaken;
236
TemporaryVariableReference expr_tree_variable;
238
HoistedParameter hoisted_variant;
240
public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
247
// Only assign, attributes will be attached during resolve
248
base.attributes = attrs;
253
public Expression DefaultExpression {
259
public DefaultParameterValueExpression DefaultValue {
261
return default_expr as DefaultParameterValueExpression;
264
default_expr = value;
268
Expression IParameterData.DefaultValue {
270
var expr = default_expr as DefaultParameterValueExpression;
271
return expr == null ? default_expr : expr.Child;
275
bool HasOptionalExpression {
277
return default_expr is DefaultParameterValueExpression;
281
public Location Location {
287
public Modifier ParameterModifier {
293
public TypeSpec Type {
295
return parameter_type;
298
parameter_type = value;
302
public FullNamedExpression TypeExpression {
308
public override string[] ValidAttributeTargets {
310
return attribute_targets;
316
public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
318
if (a.Type == pa.In && ModFlags == Modifier.OUT) {
319
a.Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
323
if (a.Type == pa.ParamArray) {
324
a.Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
328
if (a.Type == pa.Out && (ModFlags & Modifier.REF) != 0 &&
329
!OptAttributes.Contains (pa.In)) {
330
a.Report.Error (662, a.Location,
331
"Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
335
if (a.Type == pa.CLSCompliant) {
336
a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
337
} else if (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter) {
338
if (HasOptionalExpression) {
339
a.Report.Error (1745, a.Location,
340
"Cannot specify `{0}' attribute on optional parameter `{1}'",
341
TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
344
if (a.Type == pa.DefaultParameterValue)
346
} else if (a.Type == pa.CallerMemberNameAttribute) {
347
if ((modFlags & Modifier.CallerMemberName) == 0) {
348
a.Report.Error (4022, a.Location,
349
"The CallerMemberName attribute can only be applied to parameters with default value");
351
} else if (a.Type == pa.CallerLineNumberAttribute) {
352
if ((modFlags & Modifier.CallerLineNumber) == 0) {
353
a.Report.Error (4020, a.Location,
354
"The CallerLineNumber attribute can only be applied to parameters with default value");
356
} else if (a.Type == pa.CallerFilePathAttribute) {
357
if ((modFlags & Modifier.CallerFilePath) == 0) {
358
a.Report.Error (4021, a.Location,
359
"The CallerFilePath attribute can only be applied to parameters with default value");
363
base.ApplyAttributeBuilder (a, ctor, cdata, pa);
366
public virtual bool CheckAccessibility (InterfaceMemberBase member)
368
if (parameter_type == null)
371
return member.IsAccessibleAs (parameter_type);
375
// Resolve is used in method definitions
377
public virtual TypeSpec Resolve (IMemberContext rc, int index)
379
if (parameter_type != null)
380
return parameter_type;
382
if (attributes != null)
383
attributes.AttachTo (this, rc);
385
parameter_type = texpr.ResolveAsType (rc);
386
if (parameter_type == null)
391
if ((modFlags & Parameter.Modifier.RefOutMask) != 0 && parameter_type.IsSpecialRuntimeType) {
392
rc.Module.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
393
GetSignatureForError ());
397
TypeManager.CheckTypeVariance (parameter_type,
398
(modFlags & Parameter.Modifier.RefOutMask) != 0 ? Variance.None : Variance.Contravariant,
401
if (parameter_type.IsStatic) {
402
rc.Module.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
403
texpr.GetSignatureForError ());
404
return parameter_type;
407
if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)) {
408
rc.Module.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
409
TypeManager.CSharpName (parameter_type));
412
return parameter_type;
415
void ResolveCallerAttributes (ResolveContext rc)
417
var pa = rc.Module.PredefinedAttributes;
418
TypeSpec caller_type;
420
foreach (var attr in attributes.Attrs) {
421
var atype = attr.ResolveType ();
425
if (atype == pa.CallerMemberNameAttribute) {
426
caller_type = rc.BuiltinTypes.String;
427
if (caller_type != parameter_type && !Convert.ImplicitReferenceConversionExists (caller_type, parameter_type)) {
428
rc.Report.Error (4019, attr.Location,
429
"The CallerMemberName attribute cannot be applied because there is no standard conversion from `{0}' to `{1}'",
430
caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ());
433
modFlags |= Modifier.CallerMemberName;
437
if (atype == pa.CallerLineNumberAttribute) {
438
caller_type = rc.BuiltinTypes.Int;
439
if (caller_type != parameter_type && !Convert.ImplicitNumericConversionExists (caller_type, parameter_type)) {
440
rc.Report.Error (4017, attr.Location,
441
"The CallerMemberName attribute cannot be applied because there is no standard conversion from `{0}' to `{1}'",
442
caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ());
445
modFlags |= Modifier.CallerLineNumber;
449
if (atype == pa.CallerFilePathAttribute) {
450
caller_type = rc.BuiltinTypes.String;
451
if (caller_type != parameter_type && !Convert.ImplicitReferenceConversionExists (caller_type, parameter_type)) {
452
rc.Report.Error (4018, attr.Location,
453
"The CallerFilePath attribute cannot be applied because there is no standard conversion from `{0}' to `{1}'",
454
caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ());
457
modFlags |= Modifier.CallerFilePath;
463
public void ResolveDefaultValue (ResolveContext rc)
466
// Default value was specified using an expression
468
if (default_expr != null) {
469
((DefaultParameterValueExpression)default_expr).Resolve (rc, this);
470
if (attributes != null)
471
ResolveCallerAttributes (rc);
476
if (attributes == null)
479
var pa = rc.Module.PredefinedAttributes;
480
var def_attr = attributes.Search (pa.DefaultParameterValue);
481
if (def_attr != null) {
482
if (def_attr.Resolve () == null)
485
var default_expr_attr = def_attr.GetParameterDefaultValue ();
486
if (default_expr_attr == null)
489
var dpa_rc = def_attr.CreateResolveContext ();
490
default_expr = default_expr_attr.Resolve (dpa_rc);
492
if (default_expr is BoxedCast)
493
default_expr = ((BoxedCast) default_expr).Child;
495
Constant c = default_expr as Constant;
497
if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
498
rc.Report.Error (1910, default_expr.Location,
499
"Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
500
default_expr.Type.GetSignatureForError ());
502
rc.Report.Error (1909, default_expr.Location,
503
"The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
504
default_expr.Type.GetSignatureForError ()); ;
511
if (TypeSpecComparer.IsEqual (default_expr.Type, parameter_type) ||
512
(default_expr is NullConstant && TypeSpec.IsReferenceType (parameter_type) && !parameter_type.IsGenericParameter) ||
513
parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
518
// LAMESPEC: Some really weird csc behaviour which we have to mimic
519
// User operators returning same type as parameter type are considered
520
// valid for this attribute only
522
// struct S { public static implicit operator S (int i) {} }
524
// void M ([DefaultParameterValue (3)]S s)
526
var expr = Convert.ImplicitUserConversion (dpa_rc, default_expr, parameter_type, loc);
527
if (expr != null && TypeSpecComparer.IsEqual (expr.Type, parameter_type)) {
531
rc.Report.Error (1908, default_expr.Location, "The type of the default value should match the type of the parameter");
535
var opt_attr = attributes.Search (pa.OptionalParameter);
536
if (opt_attr != null) {
537
default_expr = EmptyExpression.MissingValue;
541
public bool HasDefaultValue {
542
get { return default_expr != null; }
545
public bool HasExtensionMethodModifier {
546
get { return (modFlags & Modifier.This) != 0; }
550
// Hoisted parameter variant
552
public HoistedParameter HoistedVariant {
554
return hoisted_variant;
557
hoisted_variant = value;
561
public Modifier ModFlags {
562
get { return modFlags & ~Modifier.This; }
567
set { name = value; }
570
public override AttributeTargets AttributeTargets {
572
return AttributeTargets.Parameter;
576
public void Error_DuplicateName (Report r)
578
r.Error (100, Location, "The parameter name `{0}' is a duplicate", Name);
581
public virtual string GetSignatureForError ()
584
if (parameter_type != null)
585
type_name = TypeManager.CSharpName (parameter_type);
587
type_name = texpr.GetSignatureForError ();
589
string mod = GetModifierSignature (modFlags);
591
return String.Concat (mod, " ", type_name);
596
public static string GetModifierSignature (Modifier mod)
601
case Modifier.PARAMS:
612
public void IsClsCompliant (IMemberContext ctx)
614
if (parameter_type.IsCLSCompliant ())
617
ctx.Module.Compiler.Report.Warning (3001, 1, Location,
618
"Argument type `{0}' is not CLS-compliant", parameter_type.GetSignatureForError ());
621
public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
624
throw new InternalErrorException ("builder already exists");
626
var pattrs = ParametersCompiled.GetParameterAttribute (modFlags);
627
if (HasOptionalExpression)
628
pattrs |= ParameterAttributes.Optional;
631
builder = cb.DefineParameter (index, pattrs, Name);
633
builder = mb.DefineParameter (index, pattrs, Name);
635
if (OptAttributes != null)
636
OptAttributes.Emit ();
638
if (HasDefaultValue) {
640
// Emit constant values for true constants only, the other
641
// constant-like expressions will rely on default value expression
643
var def_value = DefaultValue;
644
Constant c = def_value != null ? def_value.Child as Constant : default_expr as Constant;
646
if (c.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
647
pa.DecimalConstant.EmitAttribute (builder, (decimal) c.GetValue (), c.Location);
649
builder.SetConstant (c.GetValue ());
651
} else if (default_expr.Type.IsStruct) {
653
// Handles special case where default expression is used with value-type
655
// void Foo (S s = default (S)) {}
657
builder.SetConstant (null);
661
if (parameter_type != null) {
662
if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
663
pa.Dynamic.EmitAttribute (builder);
664
} else if (parameter_type.HasDynamicElement) {
665
pa.Dynamic.EmitAttribute (builder, parameter_type, Location);
670
public Parameter Clone ()
672
Parameter p = (Parameter) MemberwiseClone ();
673
if (attributes != null)
674
p.attributes = attributes.Clone ();
679
public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec)
681
if ((modFlags & Modifier.RefOutMask) != 0)
682
ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
684
expr_tree_variable = TemporaryVariableReference.Create (ResolveParameterExpressionType (ec, Location).Type, ec.CurrentBlock.ParametersBlock, Location);
685
expr_tree_variable = (TemporaryVariableReference) expr_tree_variable.Resolve (ec);
687
Arguments arguments = new Arguments (2);
688
arguments.Add (new Argument (new TypeOf (parameter_type, Location)));
689
arguments.Add (new Argument (new StringConstant (ec.BuiltinTypes, Name, Location)));
690
return new SimpleAssign (ExpressionTreeVariableReference (),
691
Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location));
694
public void Emit (EmitContext ec)
696
ec.EmitArgumentLoad (idx);
699
public void EmitAssign (EmitContext ec)
701
ec.EmitArgumentStore (idx);
704
public void EmitAddressOf (EmitContext ec)
706
if ((ModFlags & Modifier.RefOutMask) != 0) {
707
ec.EmitArgumentLoad (idx);
709
ec.EmitArgumentAddress (idx);
713
public TemporaryVariableReference ExpressionTreeVariableReference ()
715
return expr_tree_variable;
719
// System.Linq.Expressions.ParameterExpression type
721
public static TypeExpr ResolveParameterExpressionType (IMemberContext ec, Location location)
723
TypeSpec p_type = ec.Module.PredefinedTypes.ParameterExpression.Resolve ();
724
return new TypeExpression (p_type, location);
727
public void Warning_UselessOptionalParameter (Report Report)
729
Report.Warning (1066, 1, Location,
730
"The default value specified for optional parameter `{0}' will never be used",
736
// Imported or resolved parameter information
738
public class ParameterData : IParameterData
740
readonly string name;
741
readonly Parameter.Modifier modifiers;
742
readonly Expression default_value;
744
public ParameterData (string name, Parameter.Modifier modifiers)
747
this.modifiers = modifiers;
750
public ParameterData (string name, Parameter.Modifier modifiers, Expression defaultValue)
751
: this (name, modifiers)
753
this.default_value = defaultValue;
756
#region IParameterData Members
758
public Expression DefaultValue {
759
get { return default_value; }
762
public bool HasExtensionMethodModifier {
763
get { return (modifiers & Parameter.Modifier.This) != 0; }
766
public bool HasDefaultValue {
767
get { return default_value != null; }
770
public Parameter.Modifier ModFlags {
771
get { return modifiers; }
781
public abstract class AParametersCollection
783
protected bool has_arglist;
784
protected bool has_params;
786
// Null object pattern
787
protected IParameterData [] parameters;
788
protected TypeSpec [] types;
790
public CallingConventions CallingConvention {
793
CallingConventions.VarArgs :
794
CallingConventions.Standard;
799
get { return parameters.Length; }
802
public TypeSpec ExtensionMethodType {
807
return FixedParameters [0].HasExtensionMethodModifier ?
812
public IParameterData [] FixedParameters {
818
public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
820
return (modFlags & Parameter.Modifier.OUT) != 0 ?
821
ParameterAttributes.Out : ParameterAttributes.None;
824
// Very expensive operation
825
public MetaType[] GetMetaInfo ()
830
return MetaType.EmptyTypes;
832
types = new MetaType[Count - 1];
835
return MetaType.EmptyTypes;
837
types = new MetaType[Count];
840
for (int i = 0; i < types.Length; ++i) {
841
types[i] = Types[i].GetMetaInfo ();
843
if ((FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) == 0)
846
// TODO MemberCache: Should go to MetaInfo getter
847
types [i] = types [i].MakeByRefType ();
854
// Returns the parameter information based on the name
856
public int GetParameterIndexByName (string name)
858
for (int idx = 0; idx < Count; ++idx) {
859
if (parameters [idx].Name == name)
866
public string GetSignatureForDocumentation ()
871
StringBuilder sb = new StringBuilder ("(");
872
for (int i = 0; i < Count; ++i) {
876
sb.Append (types [i].GetSignatureForDocumentation ());
878
if ((parameters[i].ModFlags & Parameter.Modifier.RefOutMask) != 0)
883
return sb.ToString ();
886
public string GetSignatureForError ()
888
return GetSignatureForError ("(", ")", Count);
891
public string GetSignatureForError (string start, string end, int count)
893
StringBuilder sb = new StringBuilder (start);
894
for (int i = 0; i < count; ++i) {
897
sb.Append (ParameterDesc (i));
900
return sb.ToString ();
903
public bool HasArglist {
904
get { return has_arglist; }
907
public bool HasExtensionMethodType {
912
return FixedParameters [0].HasExtensionMethodModifier;
916
public bool HasParams {
917
get { return has_params; }
920
public bool IsEmpty {
921
get { return parameters.Length == 0; }
924
public AParametersCollection Inflate (TypeParameterInflator inflator)
926
TypeSpec[] inflated_types = null;
927
bool default_value = false;
929
for (int i = 0; i < Count; ++i) {
930
var inflated_param = inflator.Inflate (types[i]);
931
if (inflated_types == null) {
932
if (inflated_param == types[i])
935
default_value |= FixedParameters[i] is DefaultValueExpression;
936
inflated_types = new TypeSpec[types.Length];
937
Array.Copy (types, inflated_types, types.Length);
940
inflated_types[i] = inflated_param;
943
if (inflated_types == null)
946
var clone = (AParametersCollection) MemberwiseClone ();
947
clone.types = inflated_types;
949
for (int i = 0; i < Count; ++i) {
950
var dve = clone.FixedParameters[i] as DefaultValueExpression;
952
throw new NotImplementedException ("net");
953
// clone.FixedParameters [i].DefaultValue = new DefaultValueExpression ();
961
public string ParameterDesc (int pos)
963
if (types == null || types [pos] == null)
964
return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
966
string type = TypeManager.CSharpName (types [pos]);
967
if (FixedParameters [pos].HasExtensionMethodModifier)
968
return "this " + type;
970
Parameter.Modifier mod = FixedParameters [pos].ModFlags;
974
return Parameter.GetModifierSignature (mod) + " " + type;
977
public TypeSpec[] Types {
978
get { return types; }
979
set { types = value; }
984
// A collection of imported or resolved parameters
986
public class ParametersImported : AParametersCollection
988
public ParametersImported (IParameterData [] parameters, TypeSpec [] types, bool hasArglist, bool hasParams)
990
this.parameters = parameters;
992
this.has_arglist = hasArglist;
993
this.has_params = hasParams;
996
public ParametersImported (IParameterData[] param, TypeSpec[] types, bool hasParams)
998
this.parameters = param;
1000
this.has_params = hasParams;
1005
/// Represents the methods parameters
1007
public class ParametersCompiled : AParametersCollection
1009
public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled ();
1011
// Used by C# 2.0 delegates
1012
public static readonly ParametersCompiled Undefined = new ParametersCompiled ();
1014
private ParametersCompiled ()
1016
parameters = new Parameter [0];
1017
types = TypeSpec.EmptyTypes;
1020
private ParametersCompiled (IParameterData[] parameters, TypeSpec[] types)
1022
this.parameters = parameters;
1026
public ParametersCompiled (params Parameter[] parameters)
1028
if (parameters == null || parameters.Length == 0)
1029
throw new ArgumentException ("Use EmptyReadOnlyParameters");
1031
this.parameters = parameters;
1032
int count = parameters.Length;
1034
for (int i = 0; i < count; i++){
1035
has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
1039
public ParametersCompiled (Parameter [] parameters, bool has_arglist) :
1042
this.has_arglist = has_arglist;
1045
public static ParametersCompiled CreateFullyResolved (Parameter p, TypeSpec type)
1047
return new ParametersCompiled (new Parameter [] { p }, new TypeSpec [] { type });
1050
public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, TypeSpec[] types)
1052
return new ParametersCompiled (parameters, types);
1056
// TODO: This does not fit here, it should go to different version of AParametersCollection
1057
// as the underlying type is not Parameter and some methods will fail to cast
1059
public static AParametersCollection CreateFullyResolved (params TypeSpec[] types)
1061
var pd = new ParameterData [types.Length];
1062
for (int i = 0; i < pd.Length; ++i)
1063
pd[i] = new ParameterData (null, Parameter.Modifier.NONE, null);
1065
return new ParametersCompiled (pd, types);
1068
public static ParametersCompiled CreateImplicitParameter (FullNamedExpression texpr, Location loc)
1070
return new ParametersCompiled (
1071
new[] { new Parameter (texpr, "value", Parameter.Modifier.NONE, null, loc) },
1075
public void CheckConstraints (IMemberContext mc)
1077
foreach (Parameter p in parameters) {
1079
// It's null for compiler generated types or special types like __arglist
1081
if (p.TypeExpression != null)
1082
ConstraintChecker.Check (mc, p.Type, p.TypeExpression.Location);
1087
// Returns non-zero value for equal CLS parameter signatures
1089
public static int IsSameClsSignature (AParametersCollection a, AParametersCollection b)
1093
for (int i = 0; i < a.Count; ++i) {
1094
var a_type = a.Types[i];
1095
var b_type = b.Types[i];
1096
if (TypeSpecComparer.Override.IsEqual (a_type, b_type)) {
1097
if ((a.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (b.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask))
1103
var ac_a = a_type as ArrayContainer;
1107
var ac_b = b_type as ArrayContainer;
1111
if (ac_a.Element is ArrayContainer || ac_b.Element is ArrayContainer) {
1116
if (ac_a.Rank != ac_b.Rank && TypeSpecComparer.Override.IsEqual (ac_a.Element, ac_b.Element)) {
1127
public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, TypeSpec compilerTypes)
1129
return MergeGenerated (ctx, userParams, checkConflicts,
1130
new Parameter [] { compilerParams },
1131
new TypeSpec [] { compilerTypes });
1135
// Use this method when you merge compiler generated parameters with user parameters
1137
public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, TypeSpec[] compilerTypes)
1139
Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
1140
userParams.FixedParameters.CopyTo(all_params, 0);
1142
TypeSpec [] all_types;
1143
if (userParams.types != null) {
1144
all_types = new TypeSpec [all_params.Length];
1145
userParams.Types.CopyTo (all_types, 0);
1150
int last_filled = userParams.Count;
1152
foreach (Parameter p in compilerParams) {
1153
for (int i = 0; i < last_filled; ++i) {
1154
while (p.Name == all_params [i].Name) {
1155
if (checkConflicts && i < userParams.Count) {
1156
ctx.Report.Error (316, userParams[i].Location,
1157
"The parameter name `{0}' conflicts with a compiler generated name", p.Name);
1159
p.Name = '_' + p.Name;
1162
all_params [last_filled] = p;
1163
if (all_types != null)
1164
all_types [last_filled] = compilerTypes [index++];
1168
ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
1169
parameters.has_params = userParams.has_params;
1174
// Parameters checks for members which don't have a block
1176
public void CheckParameters (MemberCore member)
1178
for (int i = 0; i < parameters.Length; ++i) {
1179
var name = parameters[i].Name;
1180
for (int ii = i + 1; ii < parameters.Length; ++ii) {
1181
if (parameters[ii].Name == name)
1182
this[ii].Error_DuplicateName (member.Compiler.Report);
1187
public bool Resolve (IMemberContext ec)
1192
types = new TypeSpec [Count];
1196
for (int i = 0; i < FixedParameters.Length; ++i) {
1198
TypeSpec t = p.Resolve (ec, i);
1210
public void ResolveDefaultValues (MemberCore m)
1212
ResolveContext rc = null;
1213
for (int i = 0; i < parameters.Length; ++i) {
1214
Parameter p = (Parameter) parameters [i];
1217
// Try not to enter default values resolution if there are is not any default value possible
1219
if (p.HasDefaultValue || p.OptAttributes != null) {
1221
rc = new ResolveContext (m);
1223
p.ResolveDefaultValue (rc);
1228
// Define each type attribute (in/out/ref) and
1229
// the argument names.
1230
public void ApplyAttributes (IMemberContext mc, MethodBase builder)
1235
MethodBuilder mb = builder as MethodBuilder;
1236
ConstructorBuilder cb = builder as ConstructorBuilder;
1237
var pa = mc.Module.PredefinedAttributes;
1239
for (int i = 0; i < Count; i++) {
1240
this [i].ApplyAttributes (mb, cb, i + 1, pa);
1244
public void VerifyClsCompliance (IMemberContext ctx)
1246
foreach (Parameter p in FixedParameters)
1247
p.IsClsCompliant (ctx);
1250
public Parameter this [int pos] {
1251
get { return (Parameter) parameters [pos]; }
1254
public Expression CreateExpressionTree (BlockContext ec, Location loc)
1256
var initializers = new ArrayInitializer (Count, loc);
1257
foreach (Parameter p in FixedParameters) {
1259
// Each parameter expression is stored to local variable
1260
// to save some memory when referenced later.
1262
StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec), Location.Null);
1263
if (se.Resolve (ec)) {
1264
ec.CurrentBlock.AddScopeStatement (new TemporaryVariableReference.Declarator (p.ExpressionTreeVariableReference ()));
1265
ec.CurrentBlock.AddScopeStatement (se);
1268
initializers.Add (p.ExpressionTreeVariableReference ());
1271
return new ArrayCreation (
1272
Parameter.ResolveParameterExpressionType (ec, loc),
1276
public ParametersCompiled Clone ()
1278
ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
1280
p.parameters = new IParameterData [parameters.Length];
1281
for (int i = 0; i < Count; ++i)
1282
p.parameters [i] = this [i].Clone ();
1289
// Default parameter value expression. We need this wrapper to handle
1290
// default parameter values of folded constants (e.g. indexer parameters).
1291
// The expression is resolved only once but applied to two methods which
1292
// both share reference to this expression and we ensure that resolving
1293
// this expression always returns same instance
1295
public class DefaultParameterValueExpression : CompositeExpression
1297
public DefaultParameterValueExpression (Expression expr)
1302
protected override Expression DoResolve (ResolveContext rc)
1304
return base.DoResolve (rc);
1307
public void Resolve (ResolveContext rc, Parameter p)
1309
var expr = Resolve (rc);
1315
if (!(expr is Constant || expr is DefaultValueExpression || (expr is New && ((New) expr).IsDefaultStruct))) {
1316
rc.Report.Error (1736, Location,
1317
"The expression being assigned to optional parameter `{0}' must be a constant or default value",
1323
var parameter_type = p.Type;
1324
if (type == parameter_type)
1327
var res = Convert.ImplicitConversionStandard (rc, expr, parameter_type, Location);
1329
if (parameter_type.IsNullableType && res is Nullable.Wrap) {
1330
Nullable.Wrap wrap = (Nullable.Wrap) res;
1332
if (!(res is Constant)) {
1333
rc.Report.Error (1770, Location,
1334
"The expression being assigned to nullable optional parameter `{0}' must be default value",
1340
if (!expr.IsNull && TypeSpec.IsReferenceType (parameter_type) && parameter_type.BuiltinType != BuiltinTypeSpec.Type.String) {
1341
rc.Report.Error (1763, Location,
1342
"Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
1343
p.Name, parameter_type.GetSignatureForError ());
1352
rc.Report.Error (1750, Location,
1353
"Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
1354
type.GetSignatureForError (), parameter_type.GetSignatureForError ());
1357
public override object Accept (StructuralVisitor visitor)
1359
return visitor.Visit (this);