Example #1
0
        private static object Invoke([NotNull] object target, [NotNull] string methodName, bool staticContext, bool wantReturnValue, params object[] parameters)
        {
            if (target == null)
            {
                throw new ArgumentNullException("target");
            }
            if (methodName == null)
            {
                throw new ArgumentNullException("methodName");
            }

            if (parameters == null)
            {
                parameters = new object[] { null };
            }

            // This is the magic sauce that lets the DLR bind static method invocations
            // dynamically. The current C# 5 compiler (I don't know about Rosyln) does not
            // support this:
            //
            //     dynamic t = typeof(Console)
            //     t.Beep()
            //
            // This will fail at runtime complaining that TypeInfo does not contain a method
            // named Beep. By specifying the flags below, this will succeed. I presume this was
            // cut due to shipping pressure.
            var binderArgs = new List <CSharpArgumentInfo>
            {
                (staticContext) ?
                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.IsStaticType |
                                          CSharpArgumentInfoFlags.UseCompileTimeType, null) :
                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
            };

            // This is mostly just lip service for the C# binder as we really don't care about the
            // distinction between null references, numeric/string/null literals and const types
            // as everything is coming in - at runtime - boxed/byref in the parameters array to
            // this method. Binding of the target method should succeed regardless. There are a
            // few scenarios where these details matter - out/ref parameters for example. A null
            // literal being passed would be invalid for a ref/out; this would need a null ref.
            for (int i = 0; i < parameters.Length; i++)
            {
                object parameter = parameters[i];
                CSharpArgumentInfoFlags flags = (parameter == null)
                    ? CSharpArgumentInfoFlags.Constant
                    : CSharpArgumentInfoFlags.UseCompileTimeType;

                binderArgs.Add(CSharpArgumentInfo.Create(flags, null));
            }

            var callSite = BuildCallSite(methodName, wantReturnValue, parameters, binderArgs);

            // TODO: build this with expression tree and cache compiled output?
            Func <object> fn =
                () =>
                ((Delegate)callSite.Target).DynamicInvoke(
                    (new object[] { callSite, target }).Concat(parameters).ToArray());

            return(fn());
        }
Example #2
0
        private void ReduceAssignment(Expression value, CSharpBinderFlags flags, CSharpArgumentInfoFlags leftFlags, CSharpArgumentInfoFlags rightFlags, out CallSiteBinder binder, out IEnumerable <Expression> arguments, out Type[] argumentTypes)
        {
            var n = Arguments.Count;

            var argumentInfos = new CSharpArgumentInfo[n + 2];
            var expressions   = new Expression[n + 2];

            // NB: This is the only place where by-ref passing for the receiver is done in Roslyn; for more
            //     info about the apparent inconsistency see https://github.com/dotnet/roslyn/issues/6818.
            //     We're choosing to be consistent with that behavior until further notice.
            if (IsReceiverByRef(Object))
            {
                leftFlags |= CSharpArgumentInfoFlags.IsRef;
            }

            expressions[0]   = Object;
            argumentInfos[0] = CSharpArgumentInfo.Create(leftFlags, null);

            argumentTypes = null;
            CopyArguments(Arguments, argumentInfos, expressions, ref argumentTypes);

            argumentInfos[n + 1] = CSharpArgumentInfo.Create(rightFlags, null); // TODO: check
            expressions[n + 1]   = value;

            flags |= Flags;

            binder    = Binder.SetIndex(flags, Context, argumentInfos);
            arguments = expressions;
        }
        public __CSharpArgumentInfo(CSharpArgumentInfoFlags flags, string name)
        {





        }
Example #4
0
 /// <summary>
 /// Emits creating the <see cref="CSharpArgumentInfo"></see>
 /// </summary>
 /// <param name="generator">The generator.</param>
 /// <param name="flag">The flag.</param>
 /// <param name="name">The name.</param>
 public static void EmitCreateCSharpArgumentInfo(this ILGenerator generator, CSharpArgumentInfoFlags flag, string name = null)
 {
     generator.Emit(OpCodes.Ldc_I4, (int)flag);
     if (String.IsNullOrEmpty(name))
     {
         generator.Emit(OpCodes.Ldnull);
     }
     else
     {
         generator.Emit(OpCodes.Ldstr, name);
     }
     generator.Emit(OpCodes.Call, typeof(CSharpArgumentInfo).GetMethod("Create", new[] { typeof(CSharpArgumentInfoFlags), typeof(string) }));
 }
Example #5
0
        private bool Try(CallSiteBinder binder, string member, object[] args, out object result)
        {
            ObjectTypeHandle[]            argHandles    = AdapterTools.Marshal(args);
            BindingInfo                   binding       = new BindingInfo(binder);
            const CSharpArgumentInfoFlags flagsRefOrOut = CSharpArgumentInfoFlags.IsRef | CSharpArgumentInfoFlags.IsOut;
            ObjectTypeHandle              resHandle;

            try{
                resHandle = Adapter.InvokeMember(member, ref argHandles, binding.ArgumentFlags.Skip(1).Select(f => (f & flagsRefOrOut) != 0).ToArray());
            }catch (MissingMethodException)
            {
                result = null;
                return(false);
            }
            AdapterTools.Unmarshal(argHandles).CopyTo(args, 0);
            result = AdapterTools.Unmarshal(resHandle);
            return(true);
        }
Example #6
0
        public ObjectHandle InvokeMember(BindingInfo binding, ref ObjectHandle[] args)
        {
            object[] oArgs = AdapterTools.Unmarshal(args);

            var binder = binding.CreateBinder();

            object[] argsObj = new object[args.Length + 1];
            argsObj[0] = Value;
            oArgs.CopyTo(argsObj, 1);

            Expression dynExpr;
            object     ret;
            const CSharpArgumentInfoFlags flagsRefOrOut = CSharpArgumentInfoFlags.IsRef | CSharpArgumentInfoFlags.IsOut;
            var argsConst = Expression.Constant(argsObj);
            var argsExp   = argsObj.Select((o, i) => (binding.ArgumentFlags[i] & flagsRefOrOut) != 0?(Expression)Expression.ArrayAccess(argsConst, Expression.Constant(i)):Expression.Constant(o));

            try{
                if ((binding.Flags & CSharpBinderFlags.ResultDiscarded) != 0)
                {
                    dynExpr = Expression.Dynamic(binder, typeof(void), argsExp);
                    Expression.Lambda <Action>(dynExpr).Compile().Invoke();
                    ret = null;
                }
                else
                {
                    dynExpr = Expression.Dynamic(binder, typeof(object), argsExp);
                    ret     = Expression.Lambda <Func <object> >(dynExpr).Compile().Invoke();
                }
            }catch (TargetInvocationException e)
            {
                throw e.InnerException;
            }
            for (int i = 0; i < binding.ArgumentFlags.Length; i++)
            {
                if ((binding.ArgumentFlags[i] & flagsRefOrOut) == 0)
                {
                    argsObj[i] = null;
                }
            }

            Array.Copy(argsObj, 1, oArgs, 0, oArgs.Length);
            args = AdapterTools.Marshal(oArgs);
            return(AdapterTools.Marshal(ret));
        }
        /// <summary>
        /// DynamicOperatorRewriter in EE generates call to this method to dynamically invoke a property setter
        /// with no arguments.
        /// </summary>
        /// <typeparam name="TObject">Type of object on which property is defined.</typeparam>
        /// <typeparam name="TValue">Type of value property needs to be set to.</typeparam>
        /// <param name="obj">Object on which property is defined.</param>
        /// <param name="propName">Name of a property to invoke.</param>
        /// <param name="value">Value property needs to be set to.</param>
        /// <param name="valueFlags"></param>
        /// <param name="accessibilityContext">Type that determines context in which method should be called.</param>
        /// <returns>Result of property invocation.</returns>
        public static object TrySetMemberValue <TObject, TValue>(
            TObject obj,
            string propName,
            TValue value,
            CSharpArgumentInfoFlags valueFlags,
            Type accessibilityContext)
        {
            CSharpArgumentInfo targetArgInfo = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null);
            CSharpArgumentInfo valueArgInfo  = CSharpArgumentInfo.Create(valueFlags, null);

            CSharpSetMemberBinder binder = new CSharpSetMemberBinder(
                propName,
                false, // isCompoundAssignment
                false, // isChecked
                accessibilityContext,
                new CSharpArgumentInfo[] { targetArgInfo, valueArgInfo });

            var site = CallSite <Func <CallSite, TObject, TValue, object> > .Create(binder);

            return(site.Target(site, obj, value));
        }
        public static object TryEvalBinaryOperators <T1, T2>(
            T1 arg1,
            T2 arg2,
            CSharpArgumentInfoFlags arg1Flags,
            CSharpArgumentInfoFlags arg2Flags,
            ExpressionType opKind,
            Type accessibilityContext)
        {
            CSharpArgumentInfo arg1Info = CSharpArgumentInfo.Create(arg1Flags, null);
            CSharpArgumentInfo arg2Info = CSharpArgumentInfo.Create(arg2Flags, null);

            CSharpBinaryOperationBinder binder = new CSharpBinaryOperationBinder(
                opKind,
                false, // isChecked
                CSharpBinaryOperationFlags.None,
                accessibilityContext,
                new CSharpArgumentInfo[] { arg1Info, arg2Info });

            var site = CallSite <Func <CallSite, T1, T2, object> > .Create(binder);

            return(site.Target(site, arg1, arg2));
        }
        private void ReduceAssignment(Expression value, CSharpBinderFlags flags, CSharpArgumentInfoFlags leftFlags, CSharpArgumentInfoFlags rightFlags, out CallSiteBinder binder, out IEnumerable <Expression> arguments, out Type[] argumentTypes)
        {
            var n = Arguments.Count;

            var argumentInfos = new CSharpArgumentInfo[n + 2];
            var expressions   = new Expression[n + 2];

            // NB: By-ref passing for the receiver seems to be omitted in Roslyn here; see https://github.com/dotnet/roslyn/issues/6818.
            //     We're choosing to be consistent with that behavior until further notice.
            expressions[0]   = Object;
            argumentInfos[0] = CSharpArgumentInfo.Create(leftFlags, null);

            argumentTypes = null;
            CopyArguments(Arguments, argumentInfos, expressions, ref argumentTypes);

            argumentInfos[n + 1] = CSharpArgumentInfo.Create(rightFlags, null); // TODO: check
            expressions[n + 1]   = value;

            flags |= Flags;

            binder    = Binder.SetMember(flags, Name, Context, argumentInfos);
            arguments = expressions;
        }
		CSharpArgumentInfo (CSharpArgumentInfoFlags flags, string name)
		{
			this.flags = flags;
			this.name = name;
		}
Example #11
0
 private CSharpArgumentInfo(CSharpArgumentInfoFlags flags, string name)
 {
     Flags = flags;
     Name  = name;
 }
Example #12
0
 public static extern CSharpArgumentInfo Create(CSharpArgumentInfoFlags flags, string name);
 static CSharpArgumentInfo \u202E‬‌‌‪‬‏‫‬‬‍‬‏‫‪‫‏‪​‏‫‏​‪‮‪‬‌‮([In] CSharpArgumentInfoFlags obj0, [In] string obj1)
 {
     // ISSUE: unable to decompile the method.
 }
        internal Expression ReduceAssignment(Expression value, CSharpBinderFlags flags, CSharpArgumentInfoFlags leftFlags = CSharpArgumentInfoFlags.None, CSharpArgumentInfoFlags rightFlags = CSharpArgumentInfoFlags.None)
        {
            var binder = default(CallSiteBinder);
            var arguments = default(IEnumerable<Expression>);
            var argumentTypes = default(Type[]);
            ReduceAssignment(value, flags, leftFlags, rightFlags, out binder, out arguments, out argumentTypes);

            return DynamicHelpers.MakeDynamic(Type, binder, arguments, argumentTypes);
        }
Example #15
0
 static CSharpArgumentInfo \u200D‏‭‪‪‪‮‮‮​‫‌‭‫‍‮‭‍‎‎‎‎‍‍‭‮([In] CSharpArgumentInfoFlags obj0, [In] string obj1)
 {
     // ISSUE: unable to decompile the method.
 }
 /// <summary>
 /// Emits creating the <see cref="CSharpArgumentInfo"></see>
 /// </summary>
 /// <param name="generator">The generator.</param>
 /// <param name="flag">The flag.</param>
 /// <param name="name">The name.</param>
 public static void EmitCreateCSharpArgumentInfo(this ILGenerator generator, CSharpArgumentInfoFlags flag, string name = null)
 {
     generator.Emit(OpCodes.Ldc_I4, (int)flag);
     if (String.IsNullOrEmpty(name))
         generator.Emit(OpCodes.Ldnull);
     else
         generator.Emit(OpCodes.Ldstr, name);
     generator.Emit(OpCodes.Call, typeof(CSharpArgumentInfo).GetMethod("Create", new[] { typeof(CSharpArgumentInfoFlags), typeof(string) }));
 }
 static CSharpArgumentInfo \u202A‌‪‪‌‮‍‌‮‎‮‌‏‫​‬‎‎‪‫‪‏‌‌‪‭‮([In] CSharpArgumentInfoFlags obj0, [In] string obj1)
 {
     // ISSUE: unable to decompile the method.
 }
 public __CSharpArgumentInfo(CSharpArgumentInfoFlags flags, string name)
 {
 }
Example #19
0
        /// <summary>
        /// Creates an object representing a dynamically bound argument with the specified name and the specified argument flags.
        /// </summary>
        /// <param name="expression">The expression representing the value of the argument.</param>
        /// <param name="name">The name of the argument to bind.</param>
        /// <param name="argumentFlags">The argument flags denoting various properties about the dynamically bound argument.</param>
        /// <returns>An object representing a dynamically bound argument.</returns>
        public static DynamicCSharpArgument DynamicArgument(Expression expression, string name, CSharpArgumentInfoFlags argumentFlags)
        {
            RequiresCanRead(expression, nameof(expression));

            return(new DynamicCSharpArgument(argumentFlags, name, expression));
        }
Example #20
0
 internal DynamicCSharpArgument(CSharpArgumentInfoFlags flags, string name, Expression expression)
 {
     Flags      = flags;
     Name       = name;
     Expression = expression;
 }
 static CSharpArgumentInfo \u202B‏‎‬‌‮‌‬‌‪‫‍‏‌‌‬‮‫‬‎‪‏‭​‬‪‮([In] CSharpArgumentInfoFlags obj0, [In] string obj1)
 {
     // ISSUE: unable to decompile the method.
 }
 public void Create_ResultNotNull(CSharpArgumentInfoFlags flag, string name)
 {
     Assert.NotNull(CSharpArgumentInfo.Create(flag, name));
 }
Example #23
0
 <ImportInputs>o__SiteContainer14.<>p__Site16 = CallSite<Func<CallSite, object, object>>.Create(Microsoft.CSharp.RuntimeBinder.Binder.GetMember(CSharpBinderFlags.None, "Value2", typeof(xe8f63ddfa545c93b), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));
 internal DynamicCSharpArgument(CSharpArgumentInfoFlags flags, string name, Expression expression)
 {
     Flags = flags;
     Name = name;
     Expression = expression;
 }
 static CSharpArgumentInfo \u202E‌‎‍‎‫‏‬‭‭‭‍​‮‏‫‮‭‫​‪‬‌‬‮([In] CSharpArgumentInfoFlags obj0, [In] string obj1)
 {
     // ISSUE: unable to decompile the method.
 }
Example #26
0
 private CSharpArgumentInfo(CSharpArgumentInfoFlags flags, string name)
 {
     _flags = flags;
     _name = name;
 }
Example #27
0
 static CSharpArgumentInfo \u200B‬‎‬‍‌‬‎‫‎​‏‌‌‌‍‏‏‍‏‮([In] CSharpArgumentInfoFlags obj0, [In] string obj1)
 {
     // ISSUE: unable to decompile the method.
 }
 CSharpArgumentInfo(CSharpArgumentInfoFlags flags, string name)
 {
     this.flags = flags;
     this.name  = name;
 }
Example #29
0
        internal Expression ReduceAssignment(Expression value, CSharpBinderFlags flags, CSharpArgumentInfoFlags leftFlags = CSharpArgumentInfoFlags.None, CSharpArgumentInfoFlags rightFlags = CSharpArgumentInfoFlags.None)
        {
            var binder        = default(CallSiteBinder);
            var arguments     = default(IEnumerable <Expression>);
            var argumentTypes = default(Type[]);

            ReduceAssignment(value, flags, leftFlags, rightFlags, out binder, out arguments, out argumentTypes);

            return(DynamicHelpers.MakeDynamic(Type, binder, arguments, argumentTypes));
        }
        private void ReduceAssignment(Expression value, CSharpBinderFlags flags, CSharpArgumentInfoFlags leftFlags, CSharpArgumentInfoFlags rightFlags, out CallSiteBinder binder, out IEnumerable<Expression> arguments, out Type[] argumentTypes)
        {
            var n = Arguments.Count;

            var argumentInfos = new CSharpArgumentInfo[n + 2];
            var expressions = new Expression[n + 2];

            // NB: This is the only place where by-ref passing for the receiver is done in Roslyn; for more
            //     info about the apparent inconsistency see https://github.com/dotnet/roslyn/issues/6818.
            //     We're choosing to be consistent with that behavior until further notice.
            if (IsReceiverByRef(Object))
            {
                leftFlags |= CSharpArgumentInfoFlags.IsRef;
            }

            expressions[0] = Object;
            argumentInfos[0] = CSharpArgumentInfo.Create(leftFlags, null);

            argumentTypes = null;
            CopyArguments(Arguments, argumentInfos, expressions, ref argumentTypes);

            argumentInfos[n + 1] = CSharpArgumentInfo.Create(rightFlags, null); // TODO: check
            expressions[n + 1] = value;

            flags |= Flags;

            binder = Binder.SetIndex(flags, Context, argumentInfos);
            arguments = expressions;
        }
Example #31
0
 public void Create_ResultNotNull(CSharpArgumentInfoFlags flag, string name)
 {
     Assert.NotNull(CSharpArgumentInfo.Create(flag, name));
 }
Example #32
0
        public BindingInfo(CallSiteBinder binder)
        {
            Context = binder.GetCallingContext();
            var argInfo = binder.GetArgumentInfo();

            if (argInfo != null)
            {
                ArgumentFlags = argInfo.Select(a => a.GetFlags()).ToArray();
                ArgumentNames = argInfo.Select(a => a.GetName()).ToArray();
            }
            else
            {
                ArgumentFlags = new CSharpArgumentInfoFlags[0];
                ArgumentNames = new string[0];
            }
            Flags = binder.GetBinderFlags();

            var bo = binder as BinaryOperationBinder;

            if (bo != null)
            {
                BinderType = BinderTypeEnum.BinaryOperation;
                ReturnType = bo.ReturnType;
                Operation  = bo.Operation;
                return;
            }
            var c = binder as ConvertBinder;

            if (c != null)
            {
                BinderType = BinderTypeEnum.Convert;
                ReturnType = c.ReturnType;
                Type       = c.Type;
                Explicit   = c.Explicit;
                return;
            }
            var gi = binder as GetIndexBinder;

            if (gi != null)
            {
                BinderType = BinderTypeEnum.GetIndex;
                //CallInfo = gi.CallInfo;
                ReturnType = gi.ReturnType;
                return;
            }
            var gm = binder as GetMemberBinder;

            if (gm != null)
            {
                BinderType = BinderTypeEnum.GetMember;
                IgnoreCase = gm.IgnoreCase;
                Name       = gm.Name;
                ReturnType = gm.ReturnType;
                return;
            }
            var i = binder as InvokeBinder;

            if (i != null)
            {
                BinderType = BinderTypeEnum.Invoke;
                //CallInfo = i.CallInfo;
                return;
            }
            var im = binder as InvokeMemberBinder;

            if (im != null)
            {
                BinderType = BinderTypeEnum.InvokeMember;
                //CallInfo = im.CallInfo;
                IgnoreCase    = im.IgnoreCase;
                Name          = im.Name;
                ReturnType    = im.ReturnType;
                TypeArguments = im.GetTypeArguments().ToArray();
                return;
            }
            var si = binder as SetIndexBinder;

            if (si != null)
            {
                BinderType = BinderTypeEnum.SetIndex;
                //CallInfo = si.CallInfo;
                ReturnType = si.ReturnType;
                return;
            }
            var sm = binder as SetMemberBinder;

            if (sm != null)
            {
                BinderType = BinderTypeEnum.SetMember;
                IgnoreCase = sm.IgnoreCase;
                Name       = sm.Name;
                ReturnType = sm.ReturnType;
                return;
            }
        }
 public static __CSharpArgumentInfo Create(CSharpArgumentInfoFlags flags, string name)
 {
     return new __CSharpArgumentInfo { flags = flags, name = name };
 }
        private void ReduceAssignment(Expression value, CSharpBinderFlags flags, CSharpArgumentInfoFlags leftFlags, CSharpArgumentInfoFlags rightFlags, out CallSiteBinder binder, out IEnumerable<Expression> arguments, out Type[] argumentTypes)
        {
            var n = Arguments.Count;

            var argumentInfos = new CSharpArgumentInfo[n + 2];
            var expressions = new Expression[n + 2];

            // NB: By-ref passing for the receiver seems to be omitted in Roslyn here; see https://github.com/dotnet/roslyn/issues/6818.
            //     We're choosing to be consistent with that behavior until further notice.
            expressions[0] = Object;
            argumentInfos[0] = CSharpArgumentInfo.Create(leftFlags, null);

            argumentTypes = null;
            CopyArguments(Arguments, argumentInfos, expressions, ref argumentTypes);

            argumentInfos[n + 1] = CSharpArgumentInfo.Create(rightFlags, null); // TODO: check
            expressions[n + 1] = value;

            flags |= Flags;

            binder = Binder.SetMember(flags, Name, Context, argumentInfos);
            arguments = expressions;
        }
Example #35
0
 public static __CSharpArgumentInfo Create(CSharpArgumentInfoFlags flags, string name)
 {
     return(new __CSharpArgumentInfo {
         flags = flags, name = name
     });
 }
Example #36
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CSharpArgumentInfo"/> class.
 /// </summary>
 /// <param name="flags">The flags for the argument.</param>
 /// <param name="name">The name of the argument, if named; otherwise null.</param>
 public static CSharpArgumentInfo Create(CSharpArgumentInfoFlags flags, string name)
 {
     return(new CSharpArgumentInfo(flags, name));
 }
 internal Expression ReduceAssignment(Expression value, CSharpBinderFlags flags, CSharpArgumentInfoFlags leftFlags = CSharpArgumentInfoFlags.None, CSharpArgumentInfoFlags rightFlags = CSharpArgumentInfoFlags.None)
 {
     ReduceAssignment(value, flags, leftFlags, rightFlags, out CallSiteBinder binder, out IEnumerable <Expression> arguments, out Type[] argumentTypes);
		public static CSharpArgumentInfo Create (CSharpArgumentInfoFlags flags, string name)
		{
			return new CSharpArgumentInfo (flags, name);
		}
Example #39
0
 public bool HasFlag(CSharpArgumentInfoFlags flag) => (Flags & flag) != 0;
 static CSharpArgumentInfo \u202C​‭‬‪‮‫‍‍‫‎‏‭‏‎‬‌‏‮‪‍‫‭‭‫‭‬‮([In] CSharpArgumentInfoFlags obj0, [In] string obj1)
 {
     // ISSUE: unable to decompile the method.
 }
        /// <summary>
        /// Creates an object representing a dynamically bound argument with the specified name and the specified argument flags.
        /// </summary>
        /// <param name="expression">The expression representing the value of the argument.</param>
        /// <param name="name">The name of the argument to bind.</param>
        /// <param name="argumentFlags">The argument flags denoting various properties about the dynamically bound argument.</param>
        /// <returns>An object representing a dynamically bound argument.</returns>
        public static DynamicCSharpArgument DynamicArgument(Expression expression, string name, CSharpArgumentInfoFlags argumentFlags)
        {
            RequiresCanRead(expression, nameof(expression));

            return new DynamicCSharpArgument(argumentFlags, name, expression);
        }
Example #42
0
        internal BoundExpression GetArgumentInfo(
            MethodSymbol argumentInfoFactory,
            BoundExpression boundArgument,
            string name,
            RefKind refKind,
            bool isStaticType)
        {
            CSharpArgumentInfoFlags flags = 0;

            if (isStaticType)
            {
                flags |= CSharpArgumentInfoFlags.IsStaticType;
            }

            if (name != null)
            {
                flags |= CSharpArgumentInfoFlags.NamedArgument;
            }

            Debug.Assert(refKind == RefKind.None || refKind == RefKind.Ref || refKind == RefKind.Out, "unexpected refKind in dynamic");

            // by-ref type doesn't trigger dynamic dispatch and it can't be a null literal => set UseCompileTimeType
            if (refKind == RefKind.Out)
            {
                flags |= CSharpArgumentInfoFlags.IsOut | CSharpArgumentInfoFlags.UseCompileTimeType;
            }
            else if (refKind == RefKind.Ref)
            {
                flags |= CSharpArgumentInfoFlags.IsRef | CSharpArgumentInfoFlags.UseCompileTimeType;
            }

            var argType = boundArgument.Type;

            // Check "literal" constant.

            // What the runtime binder does with this LiteralConstant flag is just to create a constant,
            // which is a compelling enough reason to make sure that on the production end of the binder
            // data, we do the inverse (i.e., use the LiteralConstant flag whenever we encounter a constant
            // argument.

            // And in fact, the bug being fixed with this change is that the compiler will consider constants
            // for numeric and enum conversions even if they are not literals (such as, (1-1) --> enum), but
            // the runtime binder didn't. So we do need to set this flag whenever we see a constant.

            // But the complication is that null values lose their type when they get to the runtime binder,
            // and so we need a way to distinguish a null constant of any given type from the null literal.
            // The design is simple! We use UseCompileTimeType to determine whether we care about the type of
            // a null constant argument, so that the null literal gets "LiteralConstant" whereas every other
            // constant gets "LiteralConstant | UseCompileTimeType". Because obviously UseCompileTimeType is
            // wrong for the null literal.

            // We care, because we want to prevent this from working:
            //
            //    const C x = null;
            //    class C { public void M(SomeUnrelatedReferenceType x) { } }
            //    ...
            //    dynamic d = new C(); d.M(x); // This will pass a null constant and the type is gone!
            //
            // as well as the alternative where x is a const null of type object.

            if (boundArgument.ConstantValue != null)
            {
                flags |= CSharpArgumentInfoFlags.Constant;
            }

            // Check compile time type.
            // See also DynamicRewriter::GenerateCallingObjectFlags.
            if ((object)argType != null && !argType.IsDynamic())
            {
                flags |= CSharpArgumentInfoFlags.UseCompileTimeType;
            }

            return(_factory.Call(null, argumentInfoFactory, _factory.Literal((int)flags), _factory.Literal(name)));
        }
Example #43
0
 private CSharpArgumentInfo(CSharpArgumentInfoFlags flags, string name)
 {
     this.Flags = flags;
     this.Name  = name;
 }