Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mcs/mcs/ChangeLog19
-rw-r--r--mcs/mcs/expression.cs161
-rw-r--r--mcs/mcs/parameter.cs6
-rw-r--r--mcs/mcs/support.cs83
4 files changed, 161 insertions, 108 deletions
diff --git a/mcs/mcs/ChangeLog b/mcs/mcs/ChangeLog
index 818849b6043..fd7f1aa244f 100644
--- a/mcs/mcs/ChangeLog
+++ b/mcs/mcs/ChangeLog
@@ -1,3 +1,22 @@
+2006-12-16 Marek Safar <marek.safar@gmail.com>
+
+ A fix for bug #77014
+ * expression.cs (Invocation.BetterFunction): Fixed to cope with dynamic
+ paramters correctly and not rely on hacks in Parameters class.
+ (Invocation.IsParamsMethodApplicable): Changed to accept params parameter
+ at any possition.
+ (Invocation.VerifyArgumentsCompat): Ditto.
+ (Invocation.EmitArguments): Changed to correctly emit params arguments at
+ any possition.
+
+ * parameter.cs (HasParams): Don't assume that params is the last one.
+
+ * support.cs (ReflectionParameters.ctor): Look for params attribute
+ correctly.
+ (ReflectionParameters.ParameterType): Removed hack when we returned last
+ parameter for out of range parameters.
+ (ParameterName, ParameterModifier): Ditto.
+
2006-12-14 Marek Safar <marek.safar@gmail.com>
A fix for bug #79987
diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs
index 5db4b296f8b..d7cdd548ffa 100644
--- a/mcs/mcs/expression.cs
+++ b/mcs/mcs/expression.cs
@@ -4075,19 +4075,21 @@ namespace Mono.CSharp {
bool better_at_least_one = false;
bool same = true;
- for (int j = 0; j < argument_count; ++j) {
+ for (int j = 0, c_idx = 0, b_idx = 0; j < argument_count; ++j, ++c_idx, ++b_idx) {
Argument a = (Argument) args [j];
- Type ct = TypeManager.TypeToCoreType (candidate_pd.ParameterType (j));
- Type bt = TypeManager.TypeToCoreType (best_pd.ParameterType (j));
+ Type ct = TypeManager.TypeToCoreType (candidate_pd.ParameterType (c_idx));
+ Type bt = TypeManager.TypeToCoreType (best_pd.ParameterType (b_idx));
- if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
- if (candidate_params)
- ct = TypeManager.GetElementType (ct);
+ if (candidate_params && candidate_pd.ParameterModifier (c_idx) == Parameter.Modifier.PARAMS) {
+ ct = TypeManager.GetElementType (ct);
+ --c_idx;
+ }
- if (best_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
- if (best_params)
- bt = TypeManager.GetElementType (bt);
+ if (best_params && best_pd.ParameterModifier (b_idx) == Parameter.Modifier.PARAMS) {
+ bt = TypeManager.GetElementType (bt);
+ --b_idx;
+ }
if (ct.Equals (bt))
continue;
@@ -4317,6 +4319,10 @@ namespace Mono.CSharp {
return false;
if (pd_count != arg_count)
return false;
+
+ if (!(((Argument) arguments [count]).Expr is Arglist))
+ return false;
+ --pd_count;
} else {
if (!pd.HasParams)
return false;
@@ -4333,9 +4339,26 @@ namespace Mono.CSharp {
// remains is when the number of parameters is
// less than or equal to the argument count.
//
- for (int i = 0; i < count; ++i) {
+ int argument_index = 0;
+ Argument a;
+ for (int i = 0; i < pd_count; ++i) {
- Argument a = (Argument) arguments [i];
+ if ((pd.ParameterModifier (i) & Parameter.Modifier.PARAMS) != 0) {
+ Type element_type = TypeManager.GetElementType (pd.ParameterType (i));
+ int params_args_count = arg_count - pd_count;
+ if (params_args_count < 0)
+ continue;
+
+ do {
+ a = (Argument) arguments [argument_index++];
+
+ if (!Convert.ImplicitConversionExists (ec, a.Expr, element_type))
+ return false;
+ } while (params_args_count-- > 0);
+ continue;
+ }
+
+ a = (Argument) arguments [argument_index++];
Parameter.Modifier a_mod = a.Modifier &
(unchecked (~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK)));
@@ -4346,9 +4369,9 @@ namespace Mono.CSharp {
if (a_mod == Parameter.Modifier.NONE)
if (!Convert.ImplicitConversionExists (ec,
- a.Expr,
- pd.ParameterType (i)))
- return false;
+ a.Expr,
+ pd.ParameterType (i)))
+ return false;
if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
Type pt = pd.ParameterType (i);
@@ -4364,23 +4387,6 @@ namespace Mono.CSharp {
}
- if (do_varargs) {
- Argument a = (Argument) arguments [count];
- if (!(a.Expr is Arglist))
- return false;
-
- return true;
- }
-
- Type element_type = TypeManager.GetElementType (pd.ParameterType (pd_count - 1));
-
- for (int i = pd_count - 1; i < arg_count; i++) {
- Argument a = (Argument) arguments [i];
-
- if (!Convert.ImplicitConversionExists (ec, a.Expr, element_type))
- return false;
- }
-
return true;
}
@@ -4852,12 +4858,13 @@ namespace Mono.CSharp {
{
ParameterData pd = TypeManager.GetParameterData (method);
int j;
- for (j = 0; j < arg_count; j++) {
- Argument a = (Argument) Arguments [j];
- Expression a_expr = a.Expr;
+ int a_idx = 0;
+ int params_arg_count = 0;
+ Argument a = null;
+ for (j = 0; j < pd.Count & a_idx < arg_count; j++, a_idx++) {
+ a = (Argument) Arguments [a_idx];
Type parameter_type = pd.ParameterType (j);
Parameter.Modifier pm = pd.ParameterModifier (j);
- Parameter.Modifier am = a.Modifier;
if (pm == Parameter.Modifier.ARGLIST) {
if (!(a.Expr is Arglist))
@@ -4867,37 +4874,45 @@ namespace Mono.CSharp {
if (pm == Parameter.Modifier.PARAMS) {
pm = Parameter.Modifier.NONE;
+ params_arg_count = arg_count - pd.Count;
if (chose_params_expanded)
parameter_type = TypeManager.GetElementType (parameter_type);
}
- if (pm != am)
+ conversion:
+ if (pm != a.Modifier)
break;
if (!TypeManager.IsEqual (a.Type, parameter_type)) {
if (pm == Parameter.Modifier.OUT || pm == Parameter.Modifier.REF)
break;
- Expression conv = Convert.ImplicitConversion (ec, a_expr, parameter_type, loc);
+ Expression conv = Convert.ImplicitConversion (ec, a.Expr, parameter_type, loc);
if (conv == null)
break;
// Update the argument with the implicit conversion
- if (a_expr != conv)
+ if (a.Expr != conv)
a.Expr = conv;
}
+ if (params_arg_count > 0) {
+ --params_arg_count;
+ a = (Argument) Arguments [++a_idx];
+ goto conversion;
+ }
+
if (parameter_type.IsPointer && !ec.InUnsafe) {
UnsafeError (loc);
return false;
}
}
- if (j == arg_count)
+ if (a_idx == arg_count)
return true;
if (!may_fail)
- Error_InvalidArguments (loc, j, method, delegate_type, (Argument) Arguments [j], pd);
+ Error_InvalidArguments (loc, a_idx, method, delegate_type, a, pd);
return false;
}
@@ -5037,22 +5052,20 @@ namespace Mono.CSharp {
// <summary>
// Emits the list of arguments as an array
// </summary>
- static void EmitParams (EmitContext ec, int idx, ArrayList arguments)
+ static void EmitParams (EmitContext ec, ArrayList arguments, int idx, int count)
{
ILGenerator ig = ec.ig;
- int count = arguments.Count - idx;
- Argument a = (Argument) arguments [idx];
- Type t = a.Expr.Type;
-
- IntConstant.EmitInt (ig, count);
- ig.Emit (OpCodes.Newarr, TypeManager.TypeToCoreType (t));
-
- int top = arguments.Count;
- for (int j = idx; j < top; j++){
- a = (Argument) arguments [j];
+ Type t = null;
+ for (int j = 0; j < count; j++){
+ Argument a = (Argument) arguments [j + idx];
+ if (j == 0) {
+ t = a.Expr.Type;
+ IntConstant.EmitInt (ig, count);
+ ig.Emit (OpCodes.Newarr, TypeManager.TypeToCoreType (t));
+ }
ig.Emit (OpCodes.Dup);
- IntConstant.EmitInt (ig, j - idx);
+ IntConstant.EmitInt (ig, j);
bool is_stobj, has_type_arg;
OpCode op = ArrayAccess.GetStoreOpcode (t, out is_stobj, out has_type_arg);
@@ -5085,29 +5098,47 @@ namespace Mono.CSharp {
public static void EmitArguments (EmitContext ec, MethodBase mb, ArrayList arguments, bool dup_args, LocalTemporary this_arg)
{
ParameterData pd = mb == null ? null : TypeManager.GetParameterData (mb);
- int top = arguments == null ? 0 : arguments.Count;
+ int top = pd.Count;
LocalTemporary [] temps = null;
if (dup_args && top != 0)
temps = new LocalTemporary [top];
+ int argument_index = 0;
+ Argument a;
for (int i = 0; i < top; i++){
- Argument a = (Argument) arguments [i];
-
if (pd != null){
if (pd.ParameterModifier (i) == Parameter.Modifier.PARAMS){
+ //Type element_type = TypeManager.GetElementType (pd.ParameterType (i));
+ int params_args_count = arguments == null ?
+ 0 : arguments.Count - top + 1;
+
+ // Fill not provided argument
+ if (params_args_count <= 0) {
+ ILGenerator ig = ec.ig;
+ IntConstant.EmitInt (ig, 0);
+ ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (pd.ParameterType (i)));
+ continue;
+ }
+
//
// Special case if we are passing the same data as the
- // params argument, do not put it in an array.
+ // params argument, we do not need to recreate an array.
//
- if (pd.ParameterType (i) == a.Type)
+ a = (Argument) arguments [argument_index];
+ if (params_args_count == 1 && pd.ParameterType (i) == a.Type) {
+ ++argument_index;
a.Emit (ec);
- else
- EmitParams (ec, i, arguments);
- return;
+ continue;
+ }
+
+ EmitParams (ec, arguments, i, params_args_count);
+ argument_index += params_args_count;
+ continue;
}
}
-
+
+ a = (Argument) arguments [argument_index++];
a.Emit (ec);
if (dup_args) {
ec.ig.Emit (OpCodes.Dup);
@@ -5124,14 +5155,6 @@ namespace Mono.CSharp {
temps [i].Release (ec);
}
}
-
- if (pd != null && pd.Count > top &&
- pd.ParameterModifier (top) == Parameter.Modifier.PARAMS){
- ILGenerator ig = ec.ig;
-
- IntConstant.EmitInt (ig, 0);
- ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (pd.ParameterType (top)));
- }
}
static Type[] GetVarargsTypes (MethodBase mb, ArrayList arguments)
diff --git a/mcs/mcs/parameter.cs b/mcs/mcs/parameter.cs
index 614bade23ce..80fc9753ca4 100644
--- a/mcs/mcs/parameter.cs
+++ b/mcs/mcs/parameter.cs
@@ -794,7 +794,11 @@ namespace Mono.CSharp {
if (count == 0)
return false;
- return FixedParameters [count - 1] is ParamsParameter;
+ for (int i = count; i != 0; --i) {
+ if ((FixedParameters [i - 1].ModFlags & Parameter.Modifier.PARAMS) != 0)
+ return true;
+ }
+ return false;
}
}
diff --git a/mcs/mcs/support.cs b/mcs/mcs/support.cs
index 74b81a5f8db..2060f95e0f6 100644
--- a/mcs/mcs/support.cs
+++ b/mcs/mcs/support.cs
@@ -32,46 +32,60 @@ namespace Mono.CSharp {
public class ReflectionParameters : ParameterData {
ParameterInfo [] pi;
Type [] types;
- bool last_arg_is_params = false;
- bool is_varargs = false;
+ int params_idx = -1;
+ bool is_varargs;
ParameterData gpd;
public ReflectionParameters (MethodBase mb)
{
- object [] attrs;
-
ParameterInfo [] pi = mb.GetParameters ();
is_varargs = (mb.CallingConvention & CallingConventions.VarArgs) != 0;
this.pi = pi;
- int count = pi.Length-1;
+ int count = pi.Length;
- if (pi.Length == 0) {
+ if (count == 0) {
types = Type.EmptyTypes;
- } else {
- types = new Type [pi.Length];
- for (int i = 0; i < pi.Length; i++)
- types [i] = pi [i].ParameterType;
+ return;
}
- if (count < 0)
- return;
+ types = new Type [count];
+ for (int i = 0; i < count; i++)
+ types [i] = pi [i].ParameterType;
+ // TODO: This (if) should be done one level higher to correctly use
+ // out caching facilities.
MethodBase generic = TypeManager.DropGenericMethodArguments (mb);
if (generic != mb) {
- gpd = TypeManager.GetParameterData (generic);
- last_arg_is_params = gpd.HasParams;
- return;
+ gpd = TypeManager.GetParameterData (generic);
+ if (gpd.HasParams) {
+ for (int i = gpd.Count; i != 0; --i) {
+ if ((gpd.ParameterModifier (i)& Parameter.Modifier.PARAMS) != 0) {
+ this.params_idx = i;
+ break;
+ }
+ }
+ }
+ return;
}
- attrs = pi [count].GetCustomAttributes (TypeManager.param_array_type, true);
- if (attrs == null)
- return;
-
- if (attrs.Length == 0)
- return;
-
- last_arg_is_params = true;
+ //
+ // So far, the params attribute can be used in C# for the last
+ // and next to last method parameters.
+ // If some other language can place it anywhere we will
+ // have to analyze all parameters and not just last 2.
+ //
+ --count;
+ for (int i = count; i >= 0 && i > count - 2; --i) {
+ if (!pi [i].ParameterType.IsArray)
+ continue;
+
+ object [] attrs = pi [i].GetCustomAttributes (TypeManager.param_array_type, true);
+ if (attrs.Length == 1) {
+ params_idx = i;
+ return;
+ }
+ }
}
public string GetSignatureForError ()
@@ -93,15 +107,10 @@ namespace Mono.CSharp {
public Type ParameterType (int pos)
{
- if (last_arg_is_params && pos >= pi.Length - 1)
- return pi [pi.Length - 1].ParameterType;
- else if (is_varargs && pos >= pi.Length)
+ if (is_varargs && pos >= pi.Length)
return TypeManager.runtime_argument_handle_type;
- else {
- Type t = pi [pos].ParameterType;
- return t;
- }
+ return pi [pos].ParameterType;
}
public string ParameterName (int pos)
@@ -109,12 +118,10 @@ namespace Mono.CSharp {
if (gpd != null)
return gpd.ParameterName (pos);
- if (last_arg_is_params && pos >= pi.Length - 1)
- return pi [pi.Length - 1].Name;
- else if (is_varargs && pos >= pi.Length)
+ if (is_varargs && pos >= pi.Length)
return "__arglist";
- else
- return pi [pos].Name;
+
+ return pi [pos].Name;
}
public string ParameterDesc (int pos)
@@ -136,7 +143,7 @@ namespace Mono.CSharp {
sb.Append ("ref ");
}
- if (pos >= pi.Length - 1 && last_arg_is_params)
+ if (params_idx == pos)
sb.Append ("params ");
sb.Append (TypeManager.CSharpName (partype).Replace ("&", ""));
@@ -146,7 +153,7 @@ namespace Mono.CSharp {
public Parameter.Modifier ParameterModifier (int pos)
{
- if (last_arg_is_params && pos >= pi.Length - 1)
+ if (pos == params_idx)
return Parameter.Modifier.PARAMS;
else if (is_varargs && pos >= pi.Length)
return Parameter.Modifier.ARGLIST;
@@ -170,7 +177,7 @@ namespace Mono.CSharp {
}
public bool HasParams {
- get { return last_arg_is_params; }
+ get { return params_idx != -1; }
}
public Type[] Types {