// // Creates mcs arguments from dynamic argument info // public Compiler.Arguments CreateCompilerArguments(IEnumerable <CSharpArgumentInfo> info, DynamicMetaObject[] args) { var res = new Compiler.Arguments(args.Length); int pos = 0; // enumerates over args foreach (var item in info) { var expr = CreateCompilerExpression(item, args[pos++]); if (item.IsNamed) { res.Add(new Compiler.NamedArgument(item.Name, Compiler.Location.Null, expr, item.ArgumentModifier)); } else { res.Add(new Compiler.Argument(expr, item.ArgumentModifier)); } if (pos == args.Length) { break; } } return(res); }
protected override Expression CreateExpressionTree (ResolveContext ec, TypeSpec delegate_type) { if (ec.IsInProbingMode) return this; BlockContext bc = new BlockContext (ec.MemberContext, ec.ConstructorBlock, ec.BuiltinTypes.Void) { CurrentAnonymousMethod = ec.CurrentAnonymousMethod }; Expression args = Parameters.CreateExpressionTree (bc, loc); Expression expr = Block.CreateExpressionTree (ec); if (expr == null) return null; Arguments arguments = new Arguments (2); arguments.Add (new Argument (expr)); arguments.Add (new Argument (args)); return CreateExpressionFactoryCall (ec, "Lambda", new TypeArguments (new TypeExpression (delegate_type, loc)), arguments); }
public Expression CreateCallSiteBinder(ResolveContext ec, Arguments args) { Arguments binder_args = new Arguments(member != null ? 5 : 3); MemberAccess binder = GetBinderNamespace(loc); bool is_member_access = member is MemberAccess; string call_flags; if (!is_member_access && member is SimpleName) { call_flags = "SimpleNameCall"; is_member_access = true; } else { call_flags = "None"; } binder_args.Add(new Argument(new MemberAccess(new MemberAccess(binder, "CSharpCallFlags", loc), call_flags, loc))); if (is_member_access) { binder_args.Add(new Argument(new StringLiteral(member.Name, member.Location))); } binder_args.Add(new Argument(new TypeOf(new TypeExpression(ec.CurrentType, loc), loc))); if (member != null && member.HasTypeArguments) { TypeArguments ta = member.TypeArguments; if (ta.Resolve(ec)) { ArrayList targs = new ArrayList(ta.Count); foreach (Type t in ta.Arguments) { targs.Add(new TypeOf(new TypeExpression(t, loc), loc)); } binder_args.Add(new Argument(new ImplicitlyTypedArrayCreation("[]", targs, loc))); } } else if (is_member_access) { binder_args.Add(new Argument(new NullLiteral(loc))); } Expression real_args; if (args == null) { // Cannot be null because .NET trips over real_args = new ArrayCreation(new MemberAccess(binder, "CSharpArgumentInfo", loc), "[]", new ArrayList(0), loc); } else { real_args = new ImplicitlyTypedArrayCreation("[]", args.CreateDynamicBinderArguments(), loc); } binder_args.Add(new Argument(real_args)); return(new New(new MemberAccess(binder, is_member_access ? "CSharpInvokeMemberBinder" : "CSharpInvokeBinder", loc), binder_args, loc)); }
public Invocation(Compiler.Expression expr, Compiler.Arguments arguments, CSharpInvokeMemberBinder invokeBinder) : base(expr, arguments) { this.invokeBinder = invokeBinder; }
public DynamicInvocation(ATypeNameExpression member, Arguments args, Location loc) : base(null, args, loc) { base.binder = this; this.member = member; }
public DynamicInvocation(ATypeNameExpression member, Arguments args, Type type, Location loc) : this(member, args, loc) { // When a return type is known not to be dynamic this.type = type; }
public DynamicExpressionStatement(IDynamicBinder binder, Arguments args, Location loc) { this.binder = binder; this.arguments = args; this.loc = loc; }
public DynamicIndexBinder(bool isSet, Arguments args, Location loc) : base(null, args, loc) { base.binder = this; this.isSet = isSet; }
public override Expression CreateExpressionTree (ResolveContext ec) { BlockContext bc = new BlockContext (ec.MemberContext, Block, ReturnType); Expression args = parameters.CreateExpressionTree (bc, loc); Expression expr = Block.CreateExpressionTree (ec); if (expr == null) return null; Arguments arguments = new Arguments (2); arguments.Add (new Argument (expr)); arguments.Add (new Argument (args)); return CreateExpressionFactoryCall (ec, "Lambda", new TypeArguments (new TypeExpression (type, loc)), arguments); }
public ArrayInitializer CreateDynamicBinderArguments(ResolveContext rc) { Location loc = Location.Null; var all = new ArrayInitializer(args.Count, loc); MemberAccess binder = DynamicExpressionStatement.GetBinderNamespace(loc); foreach (Argument a in args) { Arguments dargs = new Arguments(2); // CSharpArgumentInfoFlags.None = 0 const string info_flags_enum = "CSharpArgumentInfoFlags"; Expression info_flags = new IntLiteral(rc.BuiltinTypes, 0, loc); if (a.Expr is Constant) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "Constant", loc)); } else if (a.ArgType == Argument.AType.Ref) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "IsRef", loc)); info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "UseCompileTimeType", loc)); } else if (a.ArgType == Argument.AType.Out) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "IsOut", loc)); info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "UseCompileTimeType", loc)); } else if (a.ArgType == Argument.AType.DynamicTypeName) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "IsStaticType", loc)); } var arg_type = a.Expr.Type; if (arg_type.BuiltinType != BuiltinTypeSpec.Type.Dynamic && arg_type != InternalType.NullLiteral) { MethodGroupExpr mg = a.Expr as MethodGroupExpr; if (mg != null) { rc.Report.Error(1976, a.Expr.Location, "The method group `{0}' cannot be used as an argument of dynamic operation. Consider using parentheses to invoke the method", mg.Name); } else if (arg_type == InternalType.AnonymousMethod) { rc.Report.Error(1977, a.Expr.Location, "An anonymous method or lambda expression cannot be used as an argument of dynamic operation. Consider using a cast"); } else if (arg_type.Kind == MemberKind.Void || arg_type == InternalType.Arglist || arg_type.IsPointer) { rc.Report.Error(1978, a.Expr.Location, "An expression of type `{0}' cannot be used as an argument of dynamic operation", arg_type.GetSignatureForError()); } info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "UseCompileTimeType", loc)); } string named_value; NamedArgument na = a as NamedArgument; if (na != null) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "NamedArgument", loc)); named_value = na.Name; } else { named_value = null; } dargs.Add(new Argument(info_flags)); dargs.Add(new Argument(new StringLiteral(rc.BuiltinTypes, named_value, loc))); all.Add(new Invocation(new MemberAccess(new MemberAccess(binder, "CSharpArgumentInfo", loc), "Create", loc), dargs)); } return(all); }
protected override Expression DoResolve(ResolveContext ec) { right = right.Resolve(ec); if (right == null) { return(null); } MemberAccess ma = target as MemberAccess; using (ec.Set(ResolveContext.Options.CompoundAssignmentScope)) { target = target.Resolve(ec); } if (target == null) { return(null); } if (target is MethodGroupExpr) { ec.Report.Error(1656, loc, "Cannot assign to `{0}' because it is a `{1}'", ((MethodGroupExpr)target).Name, target.ExprClassName); return(null); } var event_expr = target as EventExpr; if (event_expr != null) { source = Convert.ImplicitConversionRequired(ec, right, target.Type, loc); if (source == null) { return(null); } Expression rside; if (op == Binary.Operator.Addition) { rside = EmptyExpression.EventAddition; } else if (op == Binary.Operator.Subtraction) { rside = EmptyExpression.EventSubtraction; } else { rside = null; } target = target.ResolveLValue(ec, rside); if (target == null) { return(null); } eclass = ExprClass.Value; type = event_expr.Operator.ReturnType; return(this); } // // Only now we can decouple the original source/target // into a tree, to guarantee that we do not have side // effects. // if (left == null) { left = new TargetExpression(target); } source = new Binary(op, left, right, true); if (target is DynamicMemberAssignable) { Arguments targs = ((DynamicMemberAssignable)target).Arguments; source = source.Resolve(ec); Arguments args = new Arguments(targs.Count + 1); args.AddRange(targs); args.Add(new Argument(source)); var binder_flags = CSharpBinderFlags.ValueFromCompoundAssignment; // // Compound assignment does target conversion using additional method // call, set checked context as the binary operation can overflow // if (ec.HasSet(ResolveContext.Options.CheckedScope)) { binder_flags |= CSharpBinderFlags.CheckedContext; } if (target is DynamicMemberBinder) { source = new DynamicMemberBinder(ma.Name, binder_flags, args, loc).Resolve(ec); // Handles possible event addition/subtraction if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction) { args = new Arguments(targs.Count + 1); args.AddRange(targs); args.Add(new Argument(right)); string method_prefix = op == Binary.Operator.Addition ? Event.AEventAccessor.AddPrefix : Event.AEventAccessor.RemovePrefix; var invoke = DynamicInvocation.CreateSpecialNameInvoke( new MemberAccess(right, method_prefix + ma.Name, loc), args, loc).Resolve(ec); args = new Arguments(targs.Count); args.AddRange(targs); source = new DynamicEventCompoundAssign(ma.Name, args, (ExpressionStatement)source, (ExpressionStatement)invoke, loc).Resolve(ec); } } else { source = new DynamicIndexBinder(binder_flags, args, loc).Resolve(ec); } return(source); } return(base.DoResolve(ec)); }
protected override Expression ResolveConversions(ResolveContext ec) { // // LAMESPEC: Under dynamic context no target conversion is happening // This allows more natual dynamic behaviour but breaks compatibility // with static binding // if (target is RuntimeValueExpression) { return(this); } TypeSpec target_type = target.Type; // // 1. the return type is implicitly convertible to the type of target // if (Convert.ImplicitConversionExists(ec, source, target_type)) { source = Convert.ImplicitConversion(ec, source, target_type, loc); return(this); } // // Otherwise, if the selected operator is a predefined operator // Binary b = source as Binary; if (b == null) { if (source is ReducedExpression) { b = ((ReducedExpression)source).OriginalExpression as Binary; } else if (source is Nullable.LiftedBinaryOperator) { var po = ((Nullable.LiftedBinaryOperator)source); if (po.UserOperator == null) { b = po.Binary; } } else if (source is TypeCast) { b = ((TypeCast)source).Child as Binary; } } if (b != null) { // // 2a. the operator is a shift operator // // 2b. the return type is explicitly convertible to the type of x, and // y is implicitly convertible to the type of x // if ((b.Oper & Binary.Operator.ShiftMask) != 0 || Convert.ImplicitConversionExists(ec, right, target_type)) { source = Convert.ExplicitConversion(ec, source, target_type, loc); return(this); } } if (source.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { Arguments arg = new Arguments(1); arg.Add(new Argument(source)); return(new SimpleAssign(target, new DynamicConversion(target_type, CSharpBinderFlags.ConvertExplicit, arg, loc), loc).Resolve(ec)); } right.Error_ValueCannotBeConverted(ec, target_type, false); return(null); }
public ArrayInitializer CreateDynamicBinderArguments(ResolveContext rc) { Location loc = Location.Null; var all = new ArrayInitializer(args.Count, loc); MemberAccess binder = DynamicExpressionStatement.GetBinderNamespace(rc, loc); foreach (Argument a in args) { Arguments dargs = new Arguments(2); // CSharpArgumentInfoFlags.None = 0 const string info_flags_enum = "CSharpArgumentInfoFlags"; Expression info_flags = new IntLiteral(rc.BuiltinTypes, 0, loc); if (a.Expr is Constant) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "Constant", loc)); } else if (a.ArgType == Argument.AType.Ref) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "IsRef", loc)); info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "UseCompileTimeType", loc)); } else if (a.ArgType == Argument.AType.Out) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "IsOut", loc)); info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "UseCompileTimeType", loc)); } else if (a.ArgType == Argument.AType.DynamicTypeName) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "IsStaticType", loc)); } TypeSpec arg_type; if (rc.FileType == SourceFileType.PlayScript && a.Expr is ArrayInitializer || a.Expr is AsObjectInitializer) { if (a.Expr is ArrayInitializer) { arg_type = rc.Module.PredefinedTypes.AsArray.Resolve(); } else { arg_type = rc.Module.PredefinedTypes.AsExpandoObject.Resolve(); } } else { arg_type = a.Expr.Type; } if (arg_type.BuiltinType != BuiltinTypeSpec.Type.Dynamic && arg_type != InternalType.NullLiteral) { MethodGroupExpr mg = a.Expr as MethodGroupExpr; bool wasConverted = false; // In PlayScript, we try to implicity convert to dynamic, which handles conversions of method groups to delegates, and // anon methods to delegates. if (rc.FileType == SourceFileType.PlayScript && (mg != null || arg_type == InternalType.AnonymousMethod)) { var expr = Convert.ImplicitConversion(rc, a.Expr, rc.BuiltinTypes.Dynamic, loc); if (expr != null) { a.Expr = expr; arg_type = rc.BuiltinTypes.Dynamic; wasConverted = true; } } // Failed.. check the C# error if (!wasConverted) { if (mg != null) { rc.Report.Error(1976, a.Expr.Location, "The method group `{0}' cannot be used as an argument of dynamic operation. Consider using parentheses to invoke the method", mg.Name); } else if (arg_type == InternalType.AnonymousMethod) { rc.Report.Error(1977, a.Expr.Location, "An anonymous method or lambda expression cannot be used as an argument of dynamic operation. Consider using a cast"); } else if (arg_type.Kind == MemberKind.Void || arg_type == InternalType.Arglist || arg_type.IsPointer) { rc.Report.Error(1978, a.Expr.Location, "An expression of type `{0}' cannot be used as an argument of dynamic operation", arg_type.GetSignatureForError()); } } info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "UseCompileTimeType", loc)); } string named_value; NamedArgument na = a as NamedArgument; if (na != null) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "NamedArgument", loc)); named_value = na.Name; } else { named_value = null; } dargs.Add(new Argument(info_flags)); dargs.Add(new Argument(new StringLiteral(rc.BuiltinTypes, named_value, loc))); all.Add(new Invocation(new MemberAccess(new MemberAccess(binder, "CSharpArgumentInfo", loc), "Create", loc), dargs)); } return(all); }
public void AddRange(Arguments args) { this.args.AddRange(args.args); }
public ArgumentsOrdered(Arguments args) : base(args.Count) { AddRange(args); ordered = new List <MovableArgument> (); }
// // Creates mcs arguments from dynamic argument info // public Compiler.Arguments CreateCompilerArguments (IEnumerable<CSharpArgumentInfo> info, DynamicMetaObject[] args) { var res = new Compiler.Arguments (args.Length); int pos = 0; // enumerates over args foreach (var item in info) { var expr = CreateCompilerExpression (item, args[pos++]); if (item.IsNamed) { res.Add (new Compiler.NamedArgument (item.Name, Compiler.Location.Null, expr, item.ArgumentModifier)); } else { res.Add (new Compiler.Argument (expr, item.ArgumentModifier)); } if (pos == args.Length) break; } return res; }
protected override Expression DoResolve(ResolveContext ec) { constructor_method = Delegate.GetConstructor(type); var invoke_method = Delegate.GetInvokeMethod(type); if (!ec.HasSet(ResolveContext.Options.ConditionalAccessReceiver)) { if (method_group.HasConditionalAccess()) { conditional_access_receiver = true; ec.Set(ResolveContext.Options.ConditionalAccessReceiver); } } Arguments arguments = CreateDelegateMethodArguments(ec, invoke_method.Parameters, invoke_method.Parameters.Types, loc); method_group = method_group.OverloadResolve(ec, ref arguments, this, OverloadResolver.Restrictions.CovariantDelegate); if (conditional_access_receiver) { ec.With(ResolveContext.Options.ConditionalAccessReceiver, false); } if (method_group == null) { return(null); } var delegate_method = method_group.BestCandidate; if (delegate_method.DeclaringType.IsNullableType) { ec.Report.Error(1728, loc, "Cannot create delegate from method `{0}' because it is a member of System.Nullable<T> type", delegate_method.GetSignatureForError()); return(null); } if (!AllowSpecialMethodsInvocation) { Invocation.IsSpecialMethodInvocation(ec, delegate_method, loc); } ExtensionMethodGroupExpr emg = method_group as ExtensionMethodGroupExpr; if (emg != null) { method_group.InstanceExpression = emg.ExtensionExpression; TypeSpec e_type = emg.ExtensionExpression.Type; if (TypeSpec.IsValueType(e_type)) { ec.Report.Error(1113, loc, "Extension method `{0}' of value type `{1}' cannot be used to create delegates", delegate_method.GetSignatureForError(), e_type.GetSignatureForError()); } } TypeSpec rt = method_group.BestCandidateReturnType; if (rt.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { rt = ec.BuiltinTypes.Object; } if (!Delegate.IsTypeCovariant(ec, rt, invoke_method.ReturnType)) { Expression ret_expr = new TypeExpression(delegate_method.ReturnType, loc); Error_ConversionFailed(ec, delegate_method, ret_expr); } if (method_group.IsConditionallyExcluded) { ec.Report.SymbolRelatedToPreviousError(delegate_method); MethodOrOperator m = delegate_method.MemberDefinition as MethodOrOperator; if (m != null && m.IsPartialDefinition) { ec.Report.Error(762, loc, "Cannot create delegate from partial method declaration `{0}'", delegate_method.GetSignatureForError()); } else { ec.Report.Error(1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute", TypeManager.CSharpSignature(delegate_method)); } } var expr = method_group.InstanceExpression; if (expr != null && (expr.Type.IsGenericParameter || !TypeSpec.IsReferenceType(expr.Type))) { method_group.InstanceExpression = new BoxedCast(expr, ec.BuiltinTypes.Object); } eclass = ExprClass.Value; return(this); }
// // This constructor is invoked from the `New' expression // public NewDelegate (TypeSpec type, Arguments Arguments, Location loc) { this.type = type; this.Arguments = Arguments; this.loc = loc; }
public void Resolve() { if (RootContext.Unsafe && module.PredefinedTypes.SecurityAction.Define()) { // // Emits [assembly: SecurityPermissionAttribute (SecurityAction.RequestMinimum, SkipVerification = true)] // when -unsafe option was specified // Location loc = Location.Null; MemberAccess system_security_permissions = new MemberAccess(new MemberAccess( new QualifiedAliasMember(QualifiedAliasMember.GlobalAlias, "System", loc), "Security", loc), "Permissions", loc); var req_min = (ConstSpec)module.PredefinedTypes.SecurityAction.GetField("RequestMinimum", module.PredefinedTypes.SecurityAction.TypeSpec, loc); Arguments pos = new Arguments(1); pos.Add(new Argument(req_min.GetConstant(null))); Arguments named = new Arguments(1); named.Add(new NamedArgument("SkipVerification", loc, new BoolLiteral(true, loc))); GlobalAttribute g = new GlobalAttribute(new NamespaceEntry(module, null, null, null), "assembly", new MemberAccess(system_security_permissions, "SecurityPermissionAttribute"), new Arguments[] { pos, named }, loc, false); g.AttachTo(module, module); var ctor = g.Resolve(); if (ctor != null) { g.ExtractSecurityPermissionSet(ctor, ref declarative_security); } } if (module.OptAttributes == null) { return; } // Ensure that we only have GlobalAttributes, since the Search isn't safe with other types. if (!module.OptAttributes.CheckTargets()) { return; } cls_attribute = module.ResolveAssemblyAttribute(module.PredefinedAttributes.CLSCompliant); if (cls_attribute != null) { is_cls_compliant = cls_attribute.GetClsCompliantAttributeValue(); } if (added_modules != null && RootContext.VerifyClsCompliance && is_cls_compliant) { foreach (var m in added_modules) { if (!m.IsCLSCompliant) { Report.Error(3013, "Added modules must be marked with the CLSCompliant attribute to match the assembly", m.Name); } } } Attribute a = module.ResolveAssemblyAttribute(module.PredefinedAttributes.RuntimeCompatibility); if (a != null) { var val = a.GetNamedValue("WrapNonExceptionThrows") as BoolConstant; if (val != null) { wrap_non_exception_throws = val.Value; } } }
public DelegateInvocation (Expression instance_expr, Arguments args, Location loc) { this.InstanceExpr = instance_expr; this.arguments = args; this.loc = loc; }
public void EmitPredefined(EmitContext ec, MethodSpec method, Arguments Arguments) { Expression instance_copy = null; if (!HasAwaitArguments && ec.HasSet(BuilderContext.Options.AsyncBody)) { HasAwaitArguments = Arguments != null && Arguments.ContainsEmitWithAwait(); if (HasAwaitArguments && InstanceExpressionOnStack) { throw new NotSupportedException(); } } OpCode call_op; LocalTemporary lt = null; if (method.IsStatic) { call_op = OpCodes.Call; } else { if (IsVirtualCallRequired(InstanceExpression, method)) { call_op = OpCodes.Callvirt; } else { call_op = OpCodes.Call; } if (HasAwaitArguments) { instance_copy = InstanceExpression.EmitToField(ec); if (Arguments == null) { EmitCallInstance(ec, instance_copy, method.DeclaringType, call_op); } } else if (!InstanceExpressionOnStack) { var instance_on_stack_type = EmitCallInstance(ec, InstanceExpression, method.DeclaringType, call_op); if (DuplicateArguments) { ec.Emit(OpCodes.Dup); if (Arguments != null && Arguments.Count != 0) { lt = new LocalTemporary(instance_on_stack_type); lt.Store(ec); instance_copy = lt; } } } } if (Arguments != null && !InstanceExpressionOnStack) { EmittedArguments = Arguments.Emit(ec, DuplicateArguments, HasAwaitArguments); if (EmittedArguments != null) { if (instance_copy != null) { EmitCallInstance(ec, instance_copy, method.DeclaringType, call_op); if (lt != null) { lt.Release(ec); } } EmittedArguments.Emit(ec); } } if (call_op == OpCodes.Callvirt && (InstanceExpression.Type.IsGenericParameter || InstanceExpression.Type.IsStruct)) { ec.Emit(OpCodes.Constrained, InstanceExpression.Type); } // // Set instance expression to actual result expression. When it contains await it can be // picked up by caller // InstanceExpression = instance_copy; if (method.Parameters.HasArglist) { var varargs_types = GetVarargsTypes(method, Arguments); ec.Emit(call_op, method, varargs_types); return; } // // If you have: // this.DoFoo (); // and DoFoo is not virtual, you can omit the callvirt, // because you don't need the null checking behavior. // ec.Emit(call_op, method); }