//\r
// delegate.cs: Delegate Handler\r
//\r
-// Author: Ravi Pratap (ravi@ximian.com)\r
+// Authors:\r
+// Ravi Pratap (ravi@ximian.com)\r
+// Miguel de Icaza (miguel@ximian.com)\r
//\r
// Licensed under the terms of the GNU GPL\r
//\r
return TypeBuilder;\r
\r
if (IsTopLevel) {\r
+ if (TypeManager.NamespaceClash (Name))\r
+ return null;\r
+ \r
ModuleBuilder builder = CodeGen.ModuleBuilder;\r
attr = TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed;\r
\r
//\r
\r
// Check accessibility\r
- foreach (Type partype in param_types)\r
+ foreach (Type partype in param_types){\r
if (!container.AsAccessible (partype, ModFlags)) {\r
Report.Error (59, Location,\r
"Inconsistent accessibility: parameter type `" +\r
"accessible than delegate `" + Name + "'");\r
return false;\r
}\r
+ if (partype.IsPointer && !UnsafeOK (container))\r
+ return false;\r
+ }\r
\r
ReturnType = ResolveTypeExpr (ReturnType, false, Location);\r
ret_type = ReturnType.Type;\r
return false;\r
}\r
\r
+ if (ret_type.IsPointer && !UnsafeOK (container))\r
+ return false;\r
+\r
//\r
// We don't have to check any others because they are all\r
// guaranteed to be accessible - they are standard types.\r
ret_type, \r
param_types);\r
\r
+ //\r
+ // Define parameters, and count out/ref parameters\r
+ //\r
+ int out_params = 0;\r
i = 0;\r
if (Parameters.FixedParameters != null){\r
int top = Parameters.FixedParameters.Length;\r
\r
for (; i < top; i++) {\r
p = Parameters.FixedParameters [i];\r
+ InvokeBuilder.DefineParameter (i+1, p.Attributes, p.Name);\r
\r
- InvokeBuilder.DefineParameter (\r
- i+1, p.Attributes, p.Name);\r
+ if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0)\r
+ out_params++;\r
}\r
}\r
if (Parameters.ArrayParameter != null){\r
for (i = 0 ; i < top; i++) {\r
p = Parameters.FixedParameters [i];\r
\r
- BeginInvokeBuilder.DefineParameter (\r
- i+1, p.Attributes, p.Name);\r
+ BeginInvokeBuilder.DefineParameter (i+1, p.Attributes, p.Name);\r
}\r
}\r
if (Parameters.ArrayParameter != null){\r
Parameter p = Parameters.ArrayParameter;\r
\r
- BeginInvokeBuilder.DefineParameter (\r
- i+1, p.Attributes, p.Name);\r
+ BeginInvokeBuilder.DefineParameter (i+1, p.Attributes, p.Name);\r
i++;\r
}\r
\r
Parameter.Modifier.NONE, null);\r
\r
Parameters async_parameters = new Parameters (async_params, null, Location);\r
+ async_parameters.ComputeAndDefineParameterTypes (this);\r
\r
async_parameters.ComputeAndDefineParameterTypes (this);\r
TypeManager.RegisterMethod (BeginInvokeBuilder,\r
async_param_types);\r
\r
//\r
- // EndInvoke\r
+ // EndInvoke is a bit more interesting, all the parameters labeled as\r
+ // out or ref have to be duplicated here.\r
//\r
- Type [] end_param_types = new Type [1];\r
- end_param_types [0] = TypeManager.iasyncresult_type;\r
- \r
- EndInvokeBuilder = TypeBuilder.DefineMethod ("EndInvoke",\r
- mattr,\r
- cc,\r
- ret_type,\r
- end_param_types);\r
- EndInvokeBuilder.DefineParameter (1, ParameterAttributes.None, "result");\r
\r
+ Type [] end_param_types = new Type [out_params + 1];\r
+ Parameter [] end_params = new Parameter [out_params + 1];\r
+ int param = 0; \r
+ if (out_params > 0){\r
+ int top = Parameters.FixedParameters.Length;\r
+ for (i = 0; i < top; i++){\r
+ Parameter p = Parameters.FixedParameters [i];\r
+ if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0)\r
+ continue;\r
+\r
+ end_param_types [param] = param_types [i];\r
+ end_params [param] = p;\r
+ param++;\r
+ }\r
+ }\r
+ end_param_types [out_params] = TypeManager.iasyncresult_type;\r
+ end_params [out_params] = new Parameter (TypeManager.system_iasyncresult_expr, "result", Parameter.Modifier.NONE, null);\r
+\r
+ //\r
+ // Create method, define parameters, register parameters with type system\r
+ //\r
+ EndInvokeBuilder = TypeBuilder.DefineMethod ("EndInvoke", mattr, cc, ret_type, end_param_types);\r
EndInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);\r
\r
- Parameter [] end_params = new Parameter [1];\r
- end_params [0] = new Parameter (\r
- TypeManager.system_iasyncresult_expr, "result",\r
- Parameter.Modifier.NONE, null);\r
+ //\r
+ // EndInvoke: Label the parameters\r
+ //\r
+ EndInvokeBuilder.DefineParameter (out_params + 1, ParameterAttributes.None, "result");\r
+ for (i = 0; i < end_params.Length-1; i++){\r
+ EndInvokeBuilder.DefineParameter (i + 1, end_params [i].Attributes, end_params [i].Name);\r
+ }\r
+\r
+ Parameters end_parameters = new Parameters (end_params, null, Location);\r
+ end_parameters.ComputeAndDefineParameterTypes (this);\r
\r
TypeManager.RegisterMethod (\r
- EndInvokeBuilder, new InternalParameters (\r
- container,\r
- new Parameters (\r
- end_params, null, Location)),\r
- end_param_types);\r
+ EndInvokeBuilder,\r
+ new InternalParameters (container, end_parameters),\r
+ end_param_types);\r
\r
return true;\r
}\r
ec, delegate_type, "Invoke", loc);\r
\r
if (!(ml is MethodGroupExpr)) {\r
- Report.Error (-100, loc, "Internal error : could not find Invoke method!");\r
+ Report.Error (-100, loc, "Internal error: could not find Invoke method!");\r
return null;\r
}\r
\r
for (int i = pd_count; i > 0; ) {\r
i--;\r
\r
- if (invoke_pd.ParameterType (i) == pd.ParameterType (i))\r
+ if (invoke_pd.ParameterType (i) == pd.ParameterType (i) &&\r
+ invoke_pd.ParameterModifier (i) == pd.ParameterModifier (i))\r
continue;\r
- else\r
+ else {\r
return null;\r
+ }\r
}\r
\r
if (((MethodInfo) invoke_mb).ReturnType == ((MethodInfo) mb).ReturnType)\r
\r
Expression ml = Expression.MemberLookup (\r
ec, delegate_type, "Invoke", loc);\r
- \r
+\r
if (!(ml is MethodGroupExpr)) {\r
- Report.Error (-100, loc, "Internal error : could not find Invoke method!");\r
+ Report.Error (-100, loc, "Internal error: could not find Invoke method!" + delegate_type);\r
return false;\r
}\r
\r
\r
int pd_count = pd.Count;\r
\r
- bool not_params_method = (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS);\r
+ bool not_params_method = (pd_count == 0) ||\r
+ (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS);\r
\r
if (not_params_method && pd_count != arg_count) {\r
Report.Error (1593, loc,\r
ec, delegate_type, "Invoke", loc);\r
\r
if (!(ml is MethodGroupExpr)) {\r
- Report.Error (-100, loc, "Internal error : could not find Invoke method!");\r
+ Report.Error (-100, loc, "Internal error: could not find Invoke method!");\r
return false;\r
}\r
\r
ec, delegate_type, "Invoke", loc);\r
\r
if (!(probe_ml is MethodGroupExpr)) {\r
- Report.Error (-100, loc, "Internal error : could not find Invoke method!");\r
+ Report.Error (-100, loc, "Internal error: could not find Invoke method!");\r
return false;\r
}\r
\r
\r
for (int i = length; i > 0; ) {\r
i--;\r
- \r
- sb.Append (TypeManager.CSharpName (pd.ParameterType (length - i - 1)));\r
+\r
+ sb.Append (pd.ParameterDesc (length - i - 1));\r
if (i != 0)\r
sb.Append (", ");\r
}\r
}\r
}\r
\r
- public void CloseDelegate ()\r
- {\r
- TypeBuilder.CreateType ();\r
- }\r
- \r
public Expression InstanceExpression {\r
get {\r
return instance_expr;\r
\r
public override Expression DoResolve (EmitContext ec)\r
{\r
- if (Arguments == null) {\r
- Report.Error (-11, loc,\r
- "Delegate creation expression takes only one argument");\r
- return null;\r
- }\r
-\r
- if (Arguments.Count != 1) {\r
- Report.Error (-11, loc,\r
- "Delegate creation expression takes only one argument");\r
+ if (Arguments == null || Arguments.Count != 1) {\r
+ Report.Error (149, loc,\r
+ "Method name expected");\r
return null;\r
}\r
\r
ec, type, ".ctor", loc);\r
\r
if (!(ml is MethodGroupExpr)) {\r
- Report.Error (-100, loc, "Internal error : Could not find delegate constructor!");\r
+ Report.Error (-100, loc, "Internal error: Could not find delegate constructor!");\r
return null;\r
}\r
\r
Expression.AllBindingFlags, loc);\r
\r
if (invoke_method == null) {\r
- Report.Error (-200, loc, "Internal error ! COuld not find Invoke method!");\r
+ Report.Error (-200, loc, "Internal error ! Could not find Invoke method!");\r
return null;\r
}\r
\r
\r
return null;\r
}\r
+\r
+ //\r
+ // Check safe/unsafe of the delegate\r
+ //\r
+ if (!ec.InUnsafe){\r
+ ParameterData param = Invocation.GetParameterData (delegate_method);\r
+ int count = param.Count;\r
+ \r
+ for (int i = 0; i < count; i++){\r
+ if (param.ParameterType (i).IsPointer){\r
+ Expression.UnsafeError (loc);\r
+ return null;\r
+ }\r
+ }\r
+ }\r
\r
if (mg.InstanceExpression != null)\r
delegate_instance_expr = mg.InstanceExpression.Resolve (ec);\r
else {\r
- if (!ec.IsStatic)\r
- delegate_instance_expr = ec.This;\r
- else\r
+ if (ec.IsStatic){\r
+ if (!delegate_method.IsStatic){\r
+ Report.Error (120, loc,\r
+ "An object reference is required for the non-static method " +\r
+ delegate_method.Name);\r
+ return null;\r
+ }\r
delegate_instance_expr = null;\r
+ } else\r
+ delegate_instance_expr = ec.This;\r
}\r
\r
if (delegate_instance_expr != null)\r
Type e_type = e.Type;\r
\r
if (!TypeManager.IsDelegateType (e_type)) {\r
- Report.Error (-12, loc, "Cannot create a delegate from something " +\r
- "not a delegate or a method.");\r
+ e.Error_UnexpectedKind ("method");\r
return null;\r
}\r
\r
}\r
\r
delegate_instance_expr = e;\r
- delegate_method = ((MethodGroupExpr) invoke_method).Methods [0];\r
+ delegate_method = ((MethodGroupExpr) invoke_method).Methods [0];\r
\r
eclass = ExprClass.Value;\r
return this;\r
else\r
delegate_instance_expr.Emit (ec);\r
\r
- ec.ig.Emit (OpCodes.Ldftn, (MethodInfo) delegate_method);\r
+ if (delegate_method.IsVirtual) {\r
+ ec.ig.Emit (OpCodes.Dup);\r
+ ec.ig.Emit (OpCodes.Ldvirtftn, (MethodInfo) delegate_method);\r
+ } else\r
+ ec.ig.Emit (OpCodes.Ldftn, (MethodInfo) delegate_method);\r
ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) constructor_method);\r
}\r
}\r
\r
Expression lookup = Expression.MemberLookup (ec, del_type, "Invoke", loc);\r
if (!(lookup is MethodGroupExpr)) {\r
- Report.Error (-100, loc, "Internal error : could not find Invoke method!");\r
+ Report.Error (-100, loc, "Internal error: could not find Invoke method!");\r
return null;\r
}\r
\r