public override BoundNode VisitCall(BoundCall node)
            {
                if (node.Method.MethodKind == MethodKind.LocalFunction)
                {
                    BoundExpression receiver;
                    MethodSymbol method;
                    var arguments = node.Arguments;
                    _lambdaRewriter.RemapLocalFunction(node.Syntax, node.Method, out receiver, out method, ref arguments);
                    node = node.Update(receiver, method, arguments);
                }

                return base.VisitCall(node);
            }
Exemple #2
0
        private BoundExpression RewriteStringConcatenationFourExprs(SyntaxNode syntax, BoundExpression loweredFirst, BoundExpression loweredSecond, BoundExpression loweredThird, BoundExpression loweredFourth)
        {
            Debug.Assert(loweredFirst.HasAnyErrors || loweredFirst.Type.IsStringType());
            Debug.Assert(loweredSecond.HasAnyErrors || loweredSecond.Type.IsStringType());
            Debug.Assert(loweredThird.HasAnyErrors || loweredThird.Type.IsStringType());
            Debug.Assert(loweredFourth.HasAnyErrors || loweredFourth.Type.IsStringType());

            var method = UnsafeGetSpecialTypeMethod(syntax, SpecialMember.System_String__ConcatStringStringStringString);

            Debug.Assert((object)method != null);

            return(BoundCall.Synthesized(syntax, null, method, ImmutableArray.Create(loweredFirst, loweredSecond, loweredThird, loweredFourth)));
        }
        /// <summary>
        /// Strangely enough there is such a thing as unary concatenation and it must be rewritten.
        /// </summary>
        private BoundExpression RewriteStringConcatenationOneExpr(SyntaxNode syntax, BoundExpression loweredOperand)
        {
            if (loweredOperand.Type.SpecialType == SpecialType.System_String)
            {
                // loweredOperand ?? ""
                return(_factory.Coalesce(loweredOperand, _factory.Literal("")));
            }

            var method = UnsafeGetSpecialTypeMethod(syntax, SpecialMember.System_String__ConcatObject);

            Debug.Assert((object)method != null);
            return((BoundExpression)BoundCall.Synthesized(syntax, null, method, loweredOperand));
        }
Exemple #4
0
        private BoundExpression RewriteStringConcatenationManyExprs(SyntaxNode syntax, ImmutableArray <BoundExpression> loweredArgs)
        {
            Debug.Assert(loweredArgs.Length > 4);
            Debug.Assert(loweredArgs.All(a => a.HasErrors || a.Type.IsStringType()));

            var method = UnsafeGetSpecialTypeMethod(syntax, SpecialMember.System_String__ConcatStringArray);

            Debug.Assert((object)method != null);

            var array = _factory.ArrayOrEmpty(_factory.SpecialType(SpecialType.System_String), loweredArgs);

            return((BoundExpression)BoundCall.Synthesized(syntax, null, method, array));
        }
Exemple #5
0
        private BoundExpression RewriteStringConcatenationThreeExprs(SyntaxNode syntax, BoundExpression loweredFirst, BoundExpression loweredSecond, BoundExpression loweredThird)
        {
            SpecialMember member = (loweredFirst.Type.SpecialType == SpecialType.System_String &&
                                    loweredSecond.Type.SpecialType == SpecialType.System_String &&
                                    loweredThird.Type.SpecialType == SpecialType.System_String) ?
                                   SpecialMember.System_String__ConcatStringStringString :
                                   SpecialMember.System_String__ConcatObjectObjectObject;

            var method = UnsafeGetSpecialTypeMethod(syntax, member);

            Debug.Assert((object)method != null);

            return(BoundCall.Synthesized(syntax, null, method, ImmutableArray.Create(loweredFirst, loweredSecond, loweredThird)));
        }
Exemple #6
0
        /// <summary>
        /// Checks whether the expression represents a boxing conversion of a special value type.
        /// If it does, it tries to return a string-based representation instead in order
        /// to avoid allocations.  If it can't, the original expression is returned.
        /// </summary>
        private BoundExpression ConvertConcatExprToStringIfPossible(SyntaxNode syntax, BoundExpression expr)
        {
            if (expr.Kind == BoundKind.Conversion)
            {
                BoundConversion conv = (BoundConversion)expr;
                if (conv.ConversionKind == ConversionKind.Boxing)
                {
                    BoundExpression operand = conv.Operand;
                    if (operand != null)
                    {
                        // Is the expression a literal char?  If so, we can
                        // simply make it a literal string instead and avoid any
                        // allocations for converting the char to a string at run time.
                        if (operand.Kind == BoundKind.Literal)
                        {
                            ConstantValue cv = ((BoundLiteral)operand).ConstantValue;
                            if (cv != null && cv.SpecialType == SpecialType.System_Char)
                            {
                                return(_factory.StringLiteral(cv.CharValue.ToString()));
                            }
                        }

                        // Can the expression be optimized with a ToString call?
                        // If so, we can synthesize a ToString call to avoid boxing.
                        if (ConcatExprCanBeOptimizedWithToString(operand.Type))
                        {
                            var toString = UnsafeGetSpecialTypeMethod(syntax, SpecialMember.System_Object__ToString);

                            var type            = (NamedTypeSymbol)operand.Type;
                            var toStringMembers = type.GetMembers(toString.Name);
                            foreach (var member in toStringMembers)
                            {
                                var toStringMethod = member as MethodSymbol;
                                if (toStringMethod.GetLeastOverriddenMethod(type) == (object)toString)
                                {
                                    return(BoundCall.Synthesized(syntax, operand, toStringMethod));
                                }
                            }
                        }
                    }
                }
            }

            // Optimization not possible; just return the original expression.
            return(expr);
        }
 private BoundExpression VisitCall(BoundCall node)
 {
     if (node.IsDelegateCall)
     {
         // Generate Expression.Invoke(Receiver, arguments)
         return(ExprFactory(WellKnownMemberNames.DelegateInvokeName, Visit(node.ReceiverOpt), Expressions(node.Arguments)));
     }
     else
     {
         // Generate Expression.Call(Receiver, Method, [typeArguments,] arguments)
         var method = node.Method;
         return(ExprFactory(
                    "Call",
                    method.IsStatic ? _bound.Null(ExpressionType) : Visit(node.ReceiverOpt),
                    _bound.MethodInfo(method),
                    Expressions(node.Arguments)));
     }
 }
Exemple #8
0
        public override BoundNode?VisitCall(BoundCall node)
        {
            BoundExpression?receiverOpt = (BoundExpression)this.Visit(node.ReceiverOpt);
            ImmutableArray <BoundExpression> arguments = this.VisitList(node.Arguments);
            BoundCall updatedNode;

            if (_updatedNullabilities.TryGetValue(node, out (NullabilityInfo Info, TypeSymbol Type)infoAndType) &&
                _updatedMethodSymbols.TryGetValue(node, out MethodSymbol updatedMethodSymbol))
            {
                updatedNode = node.Update(receiverOpt, updatedMethodSymbol, arguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, node.IsDelegateCall, node.Expanded, node.InvokedAsExtensionMethod, node.ArgsToParamsOpt, node.ResultKind, node.BinderOpt, infoAndType.Type);
                updatedNode.TopLevelNullability = infoAndType.Info;
            }
            else
            {
                updatedNode = node.Update(receiverOpt, node.Method, arguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, node.IsDelegateCall, node.Expanded, node.InvokedAsExtensionMethod, node.ArgsToParamsOpt, node.ResultKind, node.BinderOpt, node.Type);
            }
            return(updatedNode);
        }
Exemple #9
0
            public override BoundNode VisitCall(BoundCall node)
            {
                if (node.Method.MethodKind == MethodKind.LocalFunction)
                {
                    BoundExpression receiver;
                    MethodSymbol    method;
                    var             arguments = node.Arguments;
                    _lambdaRewriter.RemapLocalFunction(
                        node.Syntax,
                        node.Method,
                        out receiver,
                        out method,
                        ref arguments);
                    node = node.Update(receiver, method, arguments);
                }

                return(base.VisitCall(node));
            }
        private BoundExpression MakeNewT(SyntaxNode syntax, TypeParameterSymbol typeParameter)
        {
            // "new T()" is rewritten as: "Activator.CreateInstance<T>()".

            // NOTE: DIFFERENCE FROM DEV12
            // Dev12 tried to statically optimize this and would emit default(T) if T happens to be struct
            // However semantics of "new" in C# requires that parameterless constructor be called
            // if struct defines one.
            // Since we cannot know if T has a parameterless constructor statically,
            // we must call Activator.CreateInstance unconditionally.
            MethodSymbol method;

            if (
                !this.TryGetWellKnownTypeMember(
                    syntax,
                    WellKnownMember.System_Activator__CreateInstance_T,
                    out method
                    )
                )
            {
                return(new BoundDefaultExpression(syntax, type: typeParameter, hasErrors: true));
            }

            Debug.Assert((object)method != null);
            method = method.Construct(ImmutableArray.Create <TypeSymbol>(typeParameter));

            var createInstanceCall = new BoundCall(
                syntax,
                null,
                method,
                ImmutableArray <BoundExpression> .Empty,
                default(ImmutableArray <string>),
                default(ImmutableArray <RefKind>),
                isDelegateCall: false,
                expanded: false,
                invokedAsExtensionMethod: false,
                argsToParamsOpt: default(ImmutableArray <int>),
                defaultArguments: default(BitVector),
                resultKind: LookupResultKind.Viable,
                type: typeParameter
                );

            return(createInstanceCall);
        }
        /// <summary>
        /// Synthesize a no-argument call to a given method, possibly applying a conversion to the receiver.
        ///
        /// If the receiver is of struct type and the method is an interface method, then skip the conversion
        /// and just call the interface method directly - the code generator will detect this and generate a
        /// constrained virtual call.
        /// </summary>
        /// <param name="syntax">A syntax node to attach to the synthesized bound node.</param>
        /// <param name="receiver">Receiver of method call.</param>
        /// <param name="method">Method to invoke.</param>
        /// <param name="receiverConversion">Conversion to be applied to the receiver if not calling an interface method on a struct.</param>
        /// <param name="convertedReceiverType">Type of the receiver after applying the conversion.</param>
        /// <returns>A BoundExpression representing the call.</returns>
        private BoundExpression SynthesizeCall(CSharpSyntaxNode syntax, BoundExpression receiver, MethodSymbol method, Conversion receiverConversion, TypeSymbol convertedReceiverType)
        {
            if (!receiver.Type.IsReferenceType && method.ContainingType.IsInterface)
            {
                Debug.Assert(receiverConversion.IsImplicit && !receiverConversion.IsUserDefined);

                // NOTE: The spec says that disposing of a struct enumerator won't cause any
                // unnecessary boxing to occur.  However, Dev10 extends this improvement to the
                // GetEnumerator call as well.

                // We're going to let the emitter take care of avoiding the extra boxing.
                // When it sees an interface call to a struct, it will generate a constrained
                // virtual call, which will skip boxing, if possible.

                // CONSIDER: In cases where the struct implicitly implements the interface method
                // (i.e. with a public method), we could save a few bytes of IL by creating a
                // BoundCall to the struct method rather than the interface method (so that the
                // emitter wouldn't need to create a constrained virtual call).  It is not clear
                // what effect this would have on back compat.

                // NOTE: This call does not correspond to anything that can be written in C# source.
                // We're invoking the interface method directly on the struct (which may have a private
                // explicit implementation).  The code generator knows how to handle it though.

                // receiver.InterfaceMethod()
                return(BoundCall.Synthesized(syntax, receiver, method));
            }
            else
            {
                // ((Interface)receiver).InterfaceMethod()
                Debug.Assert(!receiverConversion.IsNumeric);

                return(BoundCall.Synthesized(
                           syntax: syntax,
                           receiverOpt: MakeConversion(
                               syntax: syntax,
                               rewrittenOperand: receiver,
                               conversion: receiverConversion,
                               @checked: false,
                               rewrittenType: convertedReceiverType),
                           method: method));
            }
        }
                public override BoundNode?VisitCall(BoundCall node)
                {
                    bool mightMutate =
                        // might be a call to a local function that assigns something
                        node.Method.MethodKind == MethodKind.LocalFunction ||
                        // or perhaps we are passing a variable by ref and mutating it that way
                        !node.ArgumentRefKindsOpt.IsDefault;

                    if (mightMutate)
                    {
                        _mightAssignSomething = true;
                    }
                    else
                    {
                        base.VisitCall(node);
                    }

                    return(null);
                }
Exemple #13
0
        private BoundExpression RewriteStringConcatenationManyExprs(SyntaxNode syntax, ImmutableArray <BoundExpression> loweredArgs)
        {
            Debug.Assert(loweredArgs.Length > 3);
            Debug.Assert(loweredArgs.All(a => a.HasErrors || a.Type.SpecialType == SpecialType.System_Object || a.Type.SpecialType == SpecialType.System_String));

            bool       isObject    = false;
            TypeSymbol elementType = null;

            foreach (var arg in loweredArgs)
            {
                elementType = arg.Type;
                if (elementType.SpecialType != SpecialType.System_String)
                {
                    isObject = true;
                    break;
                }
            }

            // Count == 4 is handled differently because there is a Concat method with 4 arguments
            // for strings, but there is no such method for objects.
            if (!isObject && loweredArgs.Length == 4)
            {
                SpecialMember member = SpecialMember.System_String__ConcatStringStringStringString;
                var           method = UnsafeGetSpecialTypeMethod(syntax, member);
                Debug.Assert((object)method != null);

                return((BoundExpression)BoundCall.Synthesized(syntax, null, method, loweredArgs));
            }
            else
            {
                SpecialMember member = isObject ?
                                       SpecialMember.System_String__ConcatObjectArray :
                                       SpecialMember.System_String__ConcatStringArray;

                var method = UnsafeGetSpecialTypeMethod(syntax, member);
                Debug.Assert((object)method != null);

                var array = _factory.ArrayOrEmpty(elementType, loweredArgs);

                return((BoundExpression)BoundCall.Synthesized(syntax, null, method, array));
            }
        }
                public override BoundNode VisitCall(BoundCall node)
                {
                    bool mightMutate =
                        // might be a call to a local function that assigns something
                        node.Method.MethodKind == MethodKind.LocalFunction ||
                        // or perhaps we are passing a variable by ref and mutating it that way, e.g. `int.Parse(..., out x)`
                        !node.ArgumentRefKindsOpt.IsDefault ||
                        // or perhaps we are calling a mutating method of a value type
                        MethodMayMutateReceiver(node.ReceiverOpt, node.Method);

                    if (mightMutate)
                    {
                        _mightAssignSomething = true;
                    }
                    else
                    {
                        base.VisitCall(node);
                    }
                    return(null);
                }
Exemple #15
0
        //private MethodSymbol FindUsualObjectCtor()
        //{
        //    var objectType = _compilation.GetSpecialType(SpecialType.System_Object);

        //    var ctor = _compilation.UsualType().GetMembers(".ctor").Where(c => c.GetParameterCount() == 1 && c.GetParameterTypes()[0] == objectType).FirstOrDefault();
        //    return (MethodSymbol) ctor;
        //}
        private BoundExpression MemVarFieldAccess(SyntaxNode syntax, XsVariableSymbol property)
        {
            var getMethod = property.GetMethod;

            Debug.Assert((object)getMethod != null);
            if (property.HasAlias)
            {
                var stringType = _compilation.GetSpecialType(SpecialType.System_String);
                var lit        = new BoundLiteral(syntax, ConstantValue.Create(property.Alias), stringType);

                var arg1 = MakeConversionNode(lit, getMethod.ParameterTypes[0], false);
                var arg2 = new BoundLiteral(syntax, ConstantValue.Create(property.Name), stringType);
                return(BoundCall.Synthesized(syntax, null, getMethod, arg1, arg2));
            }
            else
            {
                var arg1 = new BoundLiteral(syntax, ConstantValue.Create(property.Name), _compilation.GetSpecialType(SpecialType.System_String));
                return(BoundCall.Synthesized(syntax, null, getMethod, arg1));
            }
        }
Exemple #16
0
        private BoundExpression MakePropertyGetAccess(
            SyntaxNode syntax,
            BoundExpression rewrittenReceiver,
            PropertySymbol property,
            ImmutableArray <BoundExpression> rewrittenArguments,
            MethodSymbol getMethodOpt      = null,
            BoundPropertyAccess oldNodeOpt = null)
        {
#if XSHARP
            if (property is XsVariableSymbol xsvar)
            {
                return(MemVarFieldAccess(syntax, xsvar));
            }
#endif
            if (_inExpressionLambda && rewrittenArguments.IsEmpty)
            {
                return(oldNodeOpt != null?
                       oldNodeOpt.Update(rewrittenReceiver, property, LookupResultKind.Viable, property.Type) :
                           new BoundPropertyAccess(syntax, rewrittenReceiver, property, LookupResultKind.Viable, property.Type));
            }
            else
            {
                var getMethod = getMethodOpt ?? property.GetOwnOrInheritedGetMethod();
#if !XSHARP
                Debug.Assert((object)getMethod != null);
                Debug.Assert(getMethod.ParameterCount == rewrittenArguments.Length);
                Debug.Assert(((object)getMethodOpt == null) || ReferenceEquals(getMethod, getMethodOpt));
#else
                if (getMethod == null)
                {
                    _diagnostics.Add(new CSDiagnosticInfo(ErrorCode.ERR_PropertyLacksGet, property.Name), syntax.Location);
                    return(BadExpression(rewrittenReceiver));
                }
#endif
                return(BoundCall.Synthesized(
                           syntax,
                           rewrittenReceiver,
                           getMethod,
                           rewrittenArguments));
            }
        }
Exemple #17
0
        public static BoundCall ErrorCall(
            CSharpSyntaxNode node,
            BoundExpression receiverOpt,
            MethodSymbol method,
            ImmutableArray<BoundExpression> arguments,
            ImmutableArray<string> namedArguments,
            ImmutableArray<RefKind> refKinds,
            bool isDelegateCall,
            bool invokedAsExtensionMethod,
            ImmutableArray<MethodSymbol> originalMethods,
            LookupResultKind resultKind)
        {
            if (!originalMethods.IsEmpty)
                resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure);

            var call = new BoundCall(node, receiverOpt, method, arguments, namedArguments,
                refKinds, isDelegateCall: isDelegateCall, expanded: false, invokedAsExtensionMethod: invokedAsExtensionMethod, argsToParamsOpt: default(ImmutableArray<int>),
                resultKind: resultKind, type: method.ReturnType, hasErrors: true);
            call.OriginalMethodsOpt = originalMethods;
            return call;
        }
Exemple #18
0
        private BoundExpression MemVarFieldAssign(SyntaxNode syntax, XsVariableSymbol property, BoundExpression rewrittenRight)
        {
            var setMethod = property.SetMethod;

            if (property.HasAlias)
            {
                var stringType = _compilation.GetSpecialType(SpecialType.System_String);

                var lit = new BoundLiteral(syntax, ConstantValue.Create(property.Alias), stringType);

                var arg1 = MakeConversionNode(lit, setMethod.ParameterTypes[0], false);
                var arg2 = new BoundLiteral(syntax, ConstantValue.Create(property.Name), stringType);
                var arg3 = MakeConversionNode(rewrittenRight, setMethod.ParameterTypes[2], false);
                return(BoundCall.Synthesized(syntax, null, setMethod, ImmutableArray.Create(arg1, arg2, arg3)));
            }
            else
            {
                var arg1 = new BoundLiteral(syntax, ConstantValue.Create(property.Name), _compilation.GetSpecialType(SpecialType.System_String));
                return(BoundCall.Synthesized(syntax, null, setMethod, arg1, MakeConversionNode(rewrittenRight, _compilation.UsualType(), false)));
            }
        }
Exemple #19
0
        private BoundExpression MakeCall(
            CSharpSyntaxNode syntax,
            BoundExpression rewrittenReceiver,
            MethodSymbol method,
            ImmutableArray <BoundExpression> rewrittenArguments,
            ImmutableArray <RefKind> argumentRefKindsOpt,
            bool expanded,
            bool invokedAsExtensionMethod,
            ImmutableArray <int> argsToParamsOpt,
            LookupResultKind resultKind,
            TypeSymbol type,
            BoundCall nodeOpt = null)
        {
            // We have already lowered each argument, but we may need some additional rewriting for the arguments,
            // such as generating a params array, re-ordering arguments based on argsToParamsOpt map, inserting arguments for optional parameters, etc.
            ImmutableArray <LocalSymbol> temps;

            rewrittenArguments = MakeArguments(syntax, rewrittenArguments, method, method, expanded, argsToParamsOpt, ref argumentRefKindsOpt, out temps, invokedAsExtensionMethod);

            return(MakeCall(nodeOpt, syntax, rewrittenReceiver, method, rewrittenArguments, argumentRefKindsOpt, invokedAsExtensionMethod, resultKind, type, temps));
        }
        public override BoundNode VisitCall(BoundCall node)
        {
            BoundExpression receiverOpt = (BoundExpression)this.Visit(node.ReceiverOpt);
            ReadOnlyArray <BoundExpression> arguments = this.VisitList(node.Arguments);
            TypeSymbol type = this.VisitType(node.Type);

            if (!RequiresSpill(arguments) && !RequiresSpill(receiverOpt))
            {
                return(node.Update(
                           receiverOpt,
                           node.Method,
                           arguments,
                           node.ArgumentNamesOpt,
                           node.ArgumentRefKindsOpt,
                           node.IsDelegateCall,
                           node.Expanded,
                           node.InvokedAsExtensionMethod,
                           node.ArgsToParamsOpt,
                           node.ResultKind, type));
            }

            var spillBuilder = new SpillBuilder();
            var spillResult  = SpillExpressionsWithReceiver(receiverOpt, arguments, spillBuilder, node.Method.ParameterRefKinds);

            var newCall = node.Update(
                spillResult.Item1,
                node.Method,
                spillResult.Item2,
                node.ArgumentNamesOpt,
                node.ArgumentRefKindsOpt,
                node.IsDelegateCall,
                node.Expanded,
                node.InvokedAsExtensionMethod,
                node.ArgsToParamsOpt,
                node.ResultKind,
                type);

            return(spillBuilder.BuildSequenceAndFree(F, newCall));
        }
Exemple #21
0
        public override BoundNode VisitCall(BoundCall node)
        {
            BoundSpillSequence2 ss = null;
            var arguments          = this.VisitExpressionList(ref ss, node.Arguments, node.ArgumentRefKindsOpt);

            BoundExpression receiver = null;

            if (ss == null)
            {
                receiver = VisitExpression(ref ss, node.ReceiverOpt);
            }
            else if (!node.Method.IsStatic)
            {
                // spill the receiver if there were await expressions in the arguments
                var ss2 = new BoundSpillSequence2();
                receiver = Spill(ss2, VisitExpression(ref ss2, node.ReceiverOpt), refKind: node.ReceiverOpt.Type.IsReferenceType ? RefKind.None : RefKind.Ref);
                ss2.IncludeSequence(ss);
                ss = ss2;
            }

            return(UpdateExpression(ss, node.Update(receiver, node.Method, arguments)));
        }
Exemple #22
0
        private BoundExpression MakeLiftedDecimalIncDecOperator(SyntaxNode syntax, BinaryOperatorKind oper, BoundExpression operand)
        {
            Debug.Assert(operand.Type.IsNullableType() && operand.Type.GetNullableUnderlyingType().SpecialType == SpecialType.System_Decimal);

            // This method assumes that operand is already a temporary and so there is no need to copy it again.
            MethodSymbol method            = GetDecimalIncDecOperator(oper);
            MethodSymbol getValueOrDefault = UnsafeGetNullableMethod(syntax, operand.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
            MethodSymbol ctor = UnsafeGetNullableMethod(syntax, operand.Type, SpecialMember.System_Nullable_T__ctor);

            // x.HasValue
            BoundExpression condition = MakeNullableHasValue(syntax, operand);
            // x.GetValueOrDefault()
            BoundExpression getValueCall = BoundCall.Synthesized(syntax, operand, getValueOrDefault);
            // op_Inc(x.GetValueOrDefault())
            BoundExpression methodCall = BoundCall.Synthesized(syntax, null, method, getValueCall);
            // new decimal?(op_Inc(x.GetValueOrDefault()))
            BoundExpression consequence = new BoundObjectCreationExpression(syntax, ctor, methodCall);
            // default(decimal?)
            BoundExpression alternative = new BoundDefaultOperator(syntax, null, operand.Type);

            // x.HasValue ? new decimal?(op_Inc(x.GetValueOrDefault())) : default(decimal?)
            return(RewriteConditionalOperator(syntax, condition, consequence, alternative, ConstantValue.NotAvailable, operand.Type));
        }
Exemple #23
0
        private static BoundCall ReverseLastTwoParameterOrder(BoundCall result)
        {
            // The input call has its arguments in the appropriate order for the invocation, but its last
            // two argument expressions appear in the reverse order from which they appeared in source.
            // Since we want region analysis to see them in source order, we rewrite the call so that these
            // two arguments are evaluated in source order.
            int n         = result.Arguments.Length;
            var arguments = ArrayBuilder <BoundExpression> .GetInstance();

            arguments.AddRange(result.Arguments);
            var lastArgument = arguments[n - 1];

            arguments[n - 1] = arguments[n - 2];
            arguments[n - 2] = lastArgument;
            var argsToParams = ArrayBuilder <int> .GetInstance();

            argsToParams.AddRange(Enumerable.Range(0, n));
            argsToParams[n - 1] = n - 2;
            argsToParams[n - 2] = n - 1;
            return(result.Update(
                       result.ReceiverOpt, result.Method, arguments.ToImmutableAndFree(), default(ImmutableArray <string>),
                       default(ImmutableArray <RefKind>), result.IsDelegateCall, result.Expanded, result.InvokedAsExtensionMethod,
                       argsToParams.ToImmutableAndFree(), result.ResultKind, result.BinderOpt, result.Type));
        }
Exemple #24
0
        public static BoundCall ErrorCall(
            CSharpSyntaxNode node,
            BoundExpression receiverOpt,
            MethodSymbol method,
            ImmutableArray <BoundExpression> arguments,
            ImmutableArray <string> namedArguments,
            ImmutableArray <RefKind> refKinds,
            bool isDelegateCall,
            bool invokedAsExtensionMethod,
            ImmutableArray <MethodSymbol> originalMethods,
            LookupResultKind resultKind)
        {
            if (!originalMethods.IsEmpty)
            {
                resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure);
            }

            var call = new BoundCall(node, receiverOpt, method, arguments, namedArguments,
                                     refKinds, isDelegateCall: isDelegateCall, expanded: false, invokedAsExtensionMethod: invokedAsExtensionMethod, argsToParamsOpt: default(ImmutableArray <int>),
                                     resultKind: resultKind, type: method.ReturnType, hasErrors: true);

            call.OriginalMethodsOpt = originalMethods;
            return(call);
        }
        public override BoundNode VisitCall(BoundCall node)
        {
            BoundSpillSequence2 ss = null;
            var arguments = this.VisitExpressionList(ref ss, node.Arguments, node.ArgumentRefKindsOpt);

            BoundExpression receiver = null;
            if (ss == null)
            {
                receiver = VisitExpression(ref ss, node.ReceiverOpt);
            }
            else if (!node.Method.IsStatic)
            {
                // spill the receiver if there were await expressions in the arguments
                var ss2 = new BoundSpillSequence2();
                receiver = Spill(ss2, VisitExpression(ref ss2, node.ReceiverOpt), refKind: node.ReceiverOpt.Type.IsReferenceType ? RefKind.None : RefKind.Ref);
                ss2.IncludeSequence(ss);
                ss = ss2;
            }

            return UpdateExpression(ss, node.Update(receiver, node.Method, arguments));
        }
Exemple #26
0
 public override BoundNode VisitCall(BoundCall node)
 {
     VisitCall(node.Method, null, node.Arguments, node.ArgumentRefKindsOpt, node.ArgumentNamesOpt, node.Expanded, node);
     CheckReceiverIfField(node.ReceiverOpt);
     return(base.VisitCall(node));
 }
Exemple #27
0
        private BoundExpression MakeCall(
            SyntaxNode syntax,
            BoundExpression rewrittenReceiver,
            MethodSymbol method,
            ImmutableArray<BoundExpression> rewrittenArguments,
            ImmutableArray<RefKind> argumentRefKindsOpt,
            bool expanded,
            bool invokedAsExtensionMethod,
            ImmutableArray<int> argsToParamsOpt,
            LookupResultKind resultKind,
            TypeSymbol type,
            BoundCall nodeOpt = null)
        {
            // We have already lowered each argument, but we may need some additional rewriting for the arguments,
            // such as generating a params array, re-ordering arguments based on argsToParamsOpt map, inserting arguments for optional parameters, etc.
            ImmutableArray<LocalSymbol> temps;
            rewrittenArguments = MakeArguments(syntax, rewrittenArguments, method, method, expanded, argsToParamsOpt, ref argumentRefKindsOpt, out temps, invokedAsExtensionMethod);

            return MakeCall(nodeOpt, syntax, rewrittenReceiver, method, rewrittenArguments, argumentRefKindsOpt, invokedAsExtensionMethod, resultKind, type, temps);
        }
Exemple #28
0
        public override BoundNode VisitCall(BoundCall node)
        {
            Debug.Assert(node != null);

            // Rewrite the receiver
            BoundExpression rewrittenReceiver = VisitExpression(node.ReceiverOpt);

            // Rewrite the arguments.
            // NOTE: We may need additional argument rewriting such as generating a params array, re-ordering arguments based on argsToParamsOpt map, inserting arguments for optional parameters, etc.
            // NOTE: This is done later by MakeArguments, for now we just lower each argument.
            var rewrittenArguments = VisitList(node.Arguments);

            return MakeCall(
                syntax: node.Syntax,
                rewrittenReceiver: rewrittenReceiver,
                method: node.Method,
                rewrittenArguments: rewrittenArguments,
                argumentRefKindsOpt: node.ArgumentRefKindsOpt,
                expanded: node.Expanded,
                invokedAsExtensionMethod: node.InvokedAsExtensionMethod,
                argsToParamsOpt: node.ArgsToParamsOpt,
                resultKind: node.ResultKind,
                type: node.Type,
                nodeOpt: node);
        }
Exemple #29
0
        private BoundExpression MakeUserDefinedIncrementOperator(BoundIncrementOperator node, BoundExpression rewrittenValueToIncrement)
        {
            Debug.Assert((object)node.MethodOpt != null);
            Debug.Assert(node.MethodOpt.ParameterCount == 1);

            bool isLifted = node.OperatorKind.IsLifted();
            bool @checked = node.OperatorKind.IsChecked();

            BoundExpression rewrittenArgument = rewrittenValueToIncrement;
            SyntaxNode      syntax            = node.Syntax;

            TypeSymbol type = node.MethodOpt.ParameterTypes[0];

            if (isLifted)
            {
                type = _compilation.GetSpecialType(SpecialType.System_Nullable_T).Construct(type);
                Debug.Assert(node.MethodOpt.ParameterTypes[0] == node.MethodOpt.ReturnType);
            }

            if (!node.OperandConversion.IsIdentity)
            {
                rewrittenArgument = MakeConversionNode(
                    syntax: syntax,
                    rewrittenOperand: rewrittenValueToIncrement,
                    conversion: node.OperandConversion,
                    rewrittenType: type,
                    @checked: @checked);
            }

            if (!isLifted)
            {
                return(BoundCall.Synthesized(syntax, null, node.MethodOpt, rewrittenArgument));
            }

            // S? temp = operand;
            // S? r = temp.HasValue ?
            //        new S?(op_Increment(temp.GetValueOrDefault())) :
            //        default(S?);

            // Unlike the other unary operators, we do not attempt to optimize nullable user-defined
            // increment or decrement. The operand is a variable (or property), and so we do not know if
            // it is always null/never null.

            BoundAssignmentOperator tempAssignment;
            BoundLocal boundTemp = _factory.StoreToTemp(rewrittenArgument, out tempAssignment);

            MethodSymbol getValueOrDefault = UnsafeGetNullableMethod(syntax, type, SpecialMember.System_Nullable_T_GetValueOrDefault);
            MethodSymbol ctor = UnsafeGetNullableMethod(syntax, type, SpecialMember.System_Nullable_T__ctor);

            // temp.HasValue
            BoundExpression condition = MakeNullableHasValue(node.Syntax, boundTemp);

            // temp.GetValueOrDefault()
            BoundExpression call_GetValueOrDefault = BoundCall.Synthesized(syntax, boundTemp, getValueOrDefault);

            // op_Increment(temp.GetValueOrDefault())
            BoundExpression userDefinedCall = BoundCall.Synthesized(syntax, null, node.MethodOpt, call_GetValueOrDefault);

            // new S?(op_Increment(temp.GetValueOrDefault()))
            BoundExpression consequence = new BoundObjectCreationExpression(syntax, ctor, userDefinedCall);

            // default(S?)
            BoundExpression alternative = new BoundDefaultOperator(syntax, null, type);

            // temp.HasValue ?
            //          new S?(op_Increment(temp.GetValueOrDefault())) :
            //          default(S?);
            BoundExpression conditionalExpression = RewriteConditionalOperator(
                syntax: syntax,
                rewrittenCondition: condition,
                rewrittenConsequence: consequence,
                rewrittenAlternative: alternative,
                constantValueOpt: null,
                rewrittenType: type);

            // temp = operand;
            // temp.HasValue ?
            //          new S?(op_Increment(temp.GetValueOrDefault())) :
            //          default(S?);
            return(new BoundSequence(
                       syntax: syntax,
                       locals: ImmutableArray.Create <LocalSymbol>(boundTemp.LocalSymbol),
                       sideEffects: ImmutableArray.Create <BoundExpression>(tempAssignment),
                       value: conditionalExpression,
                       type: type));
        }
        /// <summary>
        /// Generate a thread-safe accessor for a regular field-like event.
        ///
        /// DelegateType tmp0 = _event; //backing field
        /// DelegateType tmp1;
        /// DelegateType tmp2;
        /// do {
        ///     tmp1 = tmp0;
        ///     tmp2 = (DelegateType)Delegate.Combine(tmp1, value); //Remove for -=
        ///     tmp0 = Interlocked.CompareExchange&lt;DelegateType&gt;(ref _event, tmp2, tmp1);
        /// } while ((object)tmp0 != (object)tmp1);
        ///
        /// Note, if System.Threading.Interlocked.CompareExchange&lt;T&gt; is not available,
        /// we emit the following code and mark the method Synchronized (unless it is a struct).
        ///
        /// _event = (DelegateType)Delegate.Combine(_event, value); //Remove for -=
        ///
        /// </summary>
        internal static BoundBlock ConstructFieldLikeEventAccessorBody_Regular(SourceEventSymbol eventSymbol, bool isAddMethod, CSharpCompilation compilation, DiagnosticBag diagnostics)
        {
            CSharpSyntaxNode syntax = eventSymbol.CSharpSyntaxNode;

            TypeSymbol      delegateType  = eventSymbol.Type;
            MethodSymbol    accessor      = isAddMethod ? eventSymbol.AddMethod : eventSymbol.RemoveMethod;
            ParameterSymbol thisParameter = accessor.ThisParameter;

            TypeSymbol boolType = compilation.GetSpecialType(SpecialType.System_Boolean);

            SpecialMember updateMethodId = isAddMethod ? SpecialMember.System_Delegate__Combine : SpecialMember.System_Delegate__Remove;
            MethodSymbol  updateMethod   = (MethodSymbol)compilation.GetSpecialTypeMember(updateMethodId);

            BoundStatement @return = new BoundReturnStatement(syntax,
                                                              expressionOpt: null)
            {
                WasCompilerGenerated = true
            };

            if (updateMethod == null)
            {
                MemberDescriptor memberDescriptor = SpecialMembers.GetDescriptor(updateMethodId);
                diagnostics.Add(new CSDiagnostic(new CSDiagnosticInfo(ErrorCode.ERR_MissingPredefinedMember,
                                                                      memberDescriptor.DeclaringTypeMetadataName,
                                                                      memberDescriptor.Name),
                                                 syntax.Location));

                return(new BoundBlock(syntax,
                                      locals: ImmutableArray <LocalSymbol> .Empty,
                                      statements: ImmutableArray.Create <BoundStatement>(@return))
                {
                    WasCompilerGenerated = true
                });
            }

            Binder.ReportUseSiteDiagnostics(updateMethod, diagnostics, syntax);

            BoundThisReference fieldReceiver = eventSymbol.IsStatic ?
                                               null :
                                               new BoundThisReference(syntax, thisParameter.Type)
            {
                WasCompilerGenerated = true
            };

            BoundFieldAccess boundBackingField = new BoundFieldAccess(syntax,
                                                                      receiver: fieldReceiver,
                                                                      fieldSymbol: eventSymbol.AssociatedField,
                                                                      constantValueOpt: null)
            {
                WasCompilerGenerated = true
            };

            BoundParameter boundParameter = new BoundParameter(syntax,
                                                               parameterSymbol: accessor.Parameters[0])
            {
                WasCompilerGenerated = true
            };

            BoundExpression delegateUpdate;

            MethodSymbol compareExchangeMethod = (MethodSymbol)compilation.GetWellKnownTypeMember(WellKnownMember.System_Threading_Interlocked__CompareExchange_T);

            if ((object)compareExchangeMethod == null)
            {
                // (DelegateType)Delegate.Combine(_event, value)
                delegateUpdate = BoundConversion.SynthesizedNonUserDefined(syntax,
                                                                           operand: BoundCall.Synthesized(syntax,
                                                                                                          receiverOpt: null,
                                                                                                          method: updateMethod,
                                                                                                          arguments: ImmutableArray.Create <BoundExpression>(boundBackingField, boundParameter)),
                                                                           kind: ConversionKind.ExplicitReference,
                                                                           type: delegateType);

                // _event = (DelegateType)Delegate.Combine(_event, value);
                BoundStatement eventUpdate = new BoundExpressionStatement(syntax,
                                                                          expression: new BoundAssignmentOperator(syntax,
                                                                                                                  left: boundBackingField,
                                                                                                                  right: delegateUpdate,
                                                                                                                  type: delegateType)
                {
                    WasCompilerGenerated = true
                })
                {
                    WasCompilerGenerated = true
                };

                return(new BoundBlock(syntax,
                                      locals: ImmutableArray <LocalSymbol> .Empty,
                                      statements: ImmutableArray.Create <BoundStatement>(
                                          eventUpdate,
                                          @return))
                {
                    WasCompilerGenerated = true
                });
            }

            compareExchangeMethod = compareExchangeMethod.Construct(ImmutableArray.Create <TypeSymbol>(delegateType));

            Binder.ReportUseSiteDiagnostics(compareExchangeMethod, diagnostics, syntax);

            GeneratedLabelSymbol loopLabel = new GeneratedLabelSymbol("loop");

            const int numTemps = 3;

            LocalSymbol[] tmps      = new LocalSymbol[numTemps];
            BoundLocal[]  boundTmps = new BoundLocal[numTemps];

            for (int i = 0; i < numTemps; i++)
            {
                tmps[i]      = new SynthesizedLocal(accessor, delegateType, SynthesizedLocalKind.LoweringTemp);
                boundTmps[i] = new BoundLocal(syntax, tmps[i], null, delegateType);
            }

            // tmp0 = _event;
            BoundStatement tmp0Init = new BoundExpressionStatement(syntax,
                                                                   expression: new BoundAssignmentOperator(syntax,
                                                                                                           left: boundTmps[0],
                                                                                                           right: boundBackingField,
                                                                                                           type: delegateType)
            {
                WasCompilerGenerated = true
            })
            {
                WasCompilerGenerated = true
            };

            // LOOP:
            BoundStatement loopStart = new BoundLabelStatement(syntax,
                                                               label: loopLabel)
            {
                WasCompilerGenerated = true
            };

            // tmp1 = tmp0;
            BoundStatement tmp1Update = new BoundExpressionStatement(syntax,
                                                                     expression: new BoundAssignmentOperator(syntax,
                                                                                                             left: boundTmps[1],
                                                                                                             right: boundTmps[0],
                                                                                                             type: delegateType)
            {
                WasCompilerGenerated = true
            })
            {
                WasCompilerGenerated = true
            };

            // (DelegateType)Delegate.Combine(tmp1, value)
            delegateUpdate = BoundConversion.SynthesizedNonUserDefined(syntax,
                                                                       operand: BoundCall.Synthesized(syntax,
                                                                                                      receiverOpt: null,
                                                                                                      method: updateMethod,
                                                                                                      arguments: ImmutableArray.Create <BoundExpression>(boundTmps[1], boundParameter)),
                                                                       kind: ConversionKind.ExplicitReference,
                                                                       type: delegateType);

            // tmp2 = (DelegateType)Delegate.Combine(tmp1, value);
            BoundStatement tmp2Update = new BoundExpressionStatement(syntax,
                                                                     expression: new BoundAssignmentOperator(syntax,
                                                                                                             left: boundTmps[2],
                                                                                                             right: delegateUpdate,
                                                                                                             type: delegateType)
            {
                WasCompilerGenerated = true
            })
            {
                WasCompilerGenerated = true
            };

            // Interlocked.CompareExchange<DelegateType>(ref _event, tmp2, tmp1)
            BoundExpression compareExchange = BoundCall.Synthesized(syntax,
                                                                    receiverOpt: null,
                                                                    method: compareExchangeMethod,
                                                                    arguments: ImmutableArray.Create <BoundExpression>(boundBackingField, boundTmps[2], boundTmps[1]));

            // tmp0 = Interlocked.CompareExchange<DelegateType>(ref _event, tmp2, tmp1);
            BoundStatement tmp0Update = new BoundExpressionStatement(syntax,
                                                                     expression: new BoundAssignmentOperator(syntax,
                                                                                                             left: boundTmps[0],
                                                                                                             right: compareExchange,
                                                                                                             type: delegateType)
            {
                WasCompilerGenerated = true
            })
            {
                WasCompilerGenerated = true
            };

            // tmp0 == tmp1 // i.e. exit when they are equal, jump to start otherwise
            BoundExpression loopExitCondition = new BoundBinaryOperator(syntax,
                                                                        operatorKind: BinaryOperatorKind.ObjectEqual,
                                                                        left: boundTmps[0],
                                                                        right: boundTmps[1],
                                                                        constantValueOpt: null,
                                                                        methodOpt: null,
                                                                        resultKind: LookupResultKind.Viable,
                                                                        type: boolType)
            {
                WasCompilerGenerated = true
            };

            // branchfalse (tmp0 == tmp1) LOOP
            BoundStatement loopEnd = new BoundConditionalGoto(syntax,
                                                              condition: loopExitCondition,
                                                              jumpIfTrue: false,
                                                              label: loopLabel)
            {
                WasCompilerGenerated = true
            };

            return(new BoundBlock(syntax,
                                  locals: tmps.AsImmutable(),
                                  statements: ImmutableArray.Create <BoundStatement>(
                                      tmp0Init,
                                      loopStart,
                                      tmp1Update,
                                      tmp2Update,
                                      tmp0Update,
                                      loopEnd,
                                      @return))
            {
                WasCompilerGenerated = true
            });
        }
 private BoundExpression VisitCall(BoundCall node)
 {
     if (node.IsDelegateCall)
     {
         // Generate Expression.Invoke(Receiver, arguments)
         return ExprFactory(WellKnownMemberNames.DelegateInvokeName, Visit(node.ReceiverOpt), Expressions(node.Arguments));
     }
     else
     {
         // Generate Expression.Call(Receiver, Method, [typeArguments,] arguments)
         var method = node.Method;
         return ExprFactory(
             "Call",
             method.IsStatic ? _bound.Null(ExpressionType) : Visit(node.ReceiverOpt),
             _bound.MethodInfo(method),
             Expressions(node.Arguments));
     }
 }
Exemple #32
0
        /// <summary>
        /// If the call represents an extension method invocation with an explicit receiver, return the original
        /// methods as ReducedExtensionMethodSymbols. Otherwise, return the original methods unchanged.
        /// </summary>
        private static ImmutableArray<MethodSymbol> CreateReducedExtensionMethodsFromOriginalsIfNecessary(BoundCall call)
        {
            var methods = call.OriginalMethodsOpt;
            TypeSymbol extensionThisType = null;
            Debug.Assert(!methods.IsDefault);

            if (call.InvokedAsExtensionMethod)
            {
                // If the call was invoked as an extension method, the receiver
                // should be non-null and all methods should be extension methods.
                if (call.ReceiverOpt != null)
                {
                    extensionThisType = call.ReceiverOpt.Type;
                }
                else
                {
                    extensionThisType = call.Arguments[0].Type;
                }

                Debug.Assert((object)extensionThisType != null);
            }

            var methodBuilder = ArrayBuilder<MethodSymbol>.GetInstance();
            var filteredMethodBuilder = ArrayBuilder<MethodSymbol>.GetInstance();
            foreach (var method in FilterOverriddenOrHiddenMethods(methods))
            {
                AddReducedAndFilteredMethodGroupSymbol(methodBuilder, filteredMethodBuilder, method, default(ImmutableArray<TypeSymbol>), extensionThisType);
            }
            methodBuilder.Free();
            return filteredMethodBuilder.ToImmutableAndFree();
        }
Exemple #33
0
        private bool CheckIsCallVariable(BoundCall call, CSharpSyntaxNode node, BindValueKind kind, bool checkingReceiver, DiagnosticBag diagnostics)
        {
            // A call can only be a variable if it returns by reference. If this is the case,
            // whether or not it is a valid variable depends on whether or not the call is the
            // RHS of a return or an assign by reference:
            // - If call is used in a context demanding ref-returnable reference all of its ref
            //   inputs must be ref-returnable

            var methodSymbol = call.Method;
            if (methodSymbol.RefKind != RefKind.None)
            {
                if (kind == BindValueKind.RefReturn)
                {
                    var args = call.Arguments;
                    var argRefKinds = call.ArgumentRefKindsOpt;
                    if (!argRefKinds.IsDefault)
                    {
                        for (var i = 0; i < args.Length; i++)
                        {
                            if (argRefKinds[i] != RefKind.None && !CheckIsVariable(args[i].Syntax, args[i], kind, false, diagnostics))
                            {
                                var errorCode = checkingReceiver ? ErrorCode.ERR_RefReturnCall2 : ErrorCode.ERR_RefReturnCall;
                                var parameterIndex = call.ArgsToParamsOpt.IsDefault ? i : call.ArgsToParamsOpt[i];
                                var parameterName = methodSymbol.Parameters[parameterIndex].Name;
                                Error(diagnostics, errorCode, call.Syntax, methodSymbol, parameterName);
                                return false;
                            }
                        }
                    }
                }

                return true;
            }

            if (checkingReceiver)
            {
                // Error is associated with expression, not node which may be distinct.
                Error(diagnostics, ErrorCode.ERR_ReturnNotLValue, call.Syntax, methodSymbol);
            }
            else
            {
                Error(diagnostics, GetStandardLvalueError(kind), node);
            }

            return false;
        }
        private BoundExpression MakeLiftedUserDefinedConversionConsequence(BoundCall call, TypeSymbol resultType)
        {
            if (call.Method.ReturnType.IsNonNullableValueType())
            {
                Debug.Assert(resultType.IsNullableType() && resultType.GetNullableUnderlyingType() == call.Method.ReturnType);
                MethodSymbol ctor = GetNullableMethod(call.Syntax, resultType, SpecialMember.System_Nullable_T__ctor);
                return new BoundObjectCreationExpression(call.Syntax, ctor, call);
            }

            return call;
        }
 public override BoundNode VisitCall(BoundCall node)
 {
     VisitCall(node.Method, null, node.Arguments, node.ArgumentRefKindsOpt, node.ArgumentNamesOpt, node.Expanded, node);
     CheckReceiverIfField(node.ReceiverOpt);
     return base.VisitCall(node);
 }
        public override BoundNode VisitCall(BoundCall node)
        {
            BoundExpression receiverOpt = (BoundExpression)this.Visit(node.ReceiverOpt);
            ReadOnlyArray<BoundExpression> arguments = this.VisitList(node.Arguments);
            TypeSymbol type = this.VisitType(node.Type);

            if (!RequiresSpill(arguments) && !RequiresSpill(receiverOpt))
            {
                return node.Update(
                    receiverOpt, 
                    node.Method, 
                    arguments, 
                    node.ArgumentNamesOpt, 
                    node.ArgumentRefKindsOpt, 
                    node.IsDelegateCall,
                    node.Expanded, 
                    node.InvokedAsExtensionMethod, 
                    node.ArgsToParamsOpt, 
                    node.ResultKind, type);
            }

            var spillBuilder = new SpillBuilder();
            var spillResult = SpillExpressionsWithReceiver(receiverOpt, arguments, spillBuilder, node.Method.ParameterRefKinds);

            var newCall = node.Update(
                spillResult.Item1,
                node.Method,
                spillResult.Item2,
                node.ArgumentNamesOpt,
                node.ArgumentRefKindsOpt,
                node.IsDelegateCall,
                node.Expanded,
                node.InvokedAsExtensionMethod,
                node.ArgsToParamsOpt,
                node.ResultKind,
                type);

            return spillBuilder.BuildSequenceAndFree(F, newCall);
        }
        private BoundExpression MakeNewT(CSharpSyntaxNode syntax, TypeParameterSymbol typeParameter)
        {
            // "new T()" is rewritten as: "Activator.CreateInstance<T>()".

            // NOTE: DIFFERENCE FROM DEV12
            // Dev12 tried to statically optimize this and would emit default(T) if T happens to be struct
            // However semantics of "new" in C# requires that parameterless constructor be called
            // if struct defines one.
            // Since we cannot know if T has a parameterless constructor statically, 
            // we must call Activator.CreateInstance unconditionally.
            MethodSymbol method;

            if (!this.TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Activator__CreateInstance_T, out method))
            {
                return new BoundDefaultOperator(syntax, null, type: typeParameter, hasErrors: true);
            }

            Debug.Assert((object)method != null);
            method = method.Construct(ImmutableArray.Create<TypeSymbol>(typeParameter));

            var createInstanceCall = new BoundCall(
                syntax,
                null,
                method,
                ImmutableArray<BoundExpression>.Empty,
                default(ImmutableArray<string>),
                default(ImmutableArray<RefKind>),
                isDelegateCall: false,
                expanded: false,
                invokedAsExtensionMethod: false,
                argsToParamsOpt: default(ImmutableArray<int>),
                resultKind: LookupResultKind.Viable,
                type: typeParameter);

            return createInstanceCall;
        }
        private BoundExpression MakePropertyAssignment(
            CSharpSyntaxNode syntax,
            BoundExpression rewrittenReceiver,
            PropertySymbol property,
            ImmutableArray <BoundExpression> rewrittenArguments,
            ImmutableArray <RefKind> argumentRefKindsOpt,
            bool expanded,
            ImmutableArray <int> argsToParamsOpt,
            BoundExpression rewrittenRight,
            TypeSymbol type,
            bool used)
        {
            // Rewrite property assignment into call to setter.
            var setMethod = property.GetOwnOrInheritedSetMethod();

            if ((object)setMethod == null)
            {
                Debug.Assert((property as SourcePropertySymbol)?.IsAutoProperty == true,
                             "only autoproperties can be assignable without having setters");

                var backingField = (property as SourcePropertySymbol).BackingField;
                return(factory.AssignmentExpression(
                           factory.Field(rewrittenReceiver, backingField),
                           rewrittenRight));
            }

            // We have already lowered each argument, but we may need some additional rewriting for the arguments,
            // such as generating a params array, re-ordering arguments based on argsToParamsOpt map, inserting arguments for optional parameters, etc.
            ImmutableArray <LocalSymbol> argTemps;

            rewrittenArguments = MakeArguments(syntax, rewrittenArguments, property, setMethod, expanded, argsToParamsOpt, ref argumentRefKindsOpt, out argTemps, enableCallerInfo: ThreeState.True);

            if (used)
            {
                // Save expression value to a temporary before calling the
                // setter, and restore the temporary after the setter, so the
                // assignment can be used as an embedded expression.
                TypeSymbol exprType = rewrittenRight.Type;

                LocalSymbol rhsTemp = factory.SynthesizedLocal(exprType);

                BoundExpression boundRhs = new BoundLocal(syntax, rhsTemp, null, exprType);

                BoundExpression rhsAssignment = new BoundAssignmentOperator(
                    syntax,
                    boundRhs,
                    rewrittenRight,
                    exprType);

                BoundExpression setterCall = BoundCall.Synthesized(
                    syntax,
                    rewrittenReceiver,
                    setMethod,
                    AppendToPossibleNull(rewrittenArguments, rhsAssignment));

                return(new BoundSequence(
                           syntax,
                           AppendToPossibleNull(argTemps, rhsTemp),
                           ImmutableArray.Create(setterCall),
                           boundRhs,
                           type));
            }
            else
            {
                BoundCall setterCall = BoundCall.Synthesized(
                    syntax,
                    rewrittenReceiver,
                    setMethod,
                    AppendToPossibleNull(rewrittenArguments, rewrittenRight));

                if (argTemps.IsDefaultOrEmpty)
                {
                    return(setterCall);
                }
                else
                {
                    return(new BoundSequence(
                               syntax,
                               argTemps,
                               ImmutableArray <BoundExpression> .Empty,
                               setterCall,
                               setMethod.ReturnType));
                }
            }
        }
        private BoundStatement RewriteUsingStatementTryFinally(CSharpSyntaxNode syntax, BoundBlock tryBlock, BoundLocal local)
        {
            // SPEC: When ResourceType is a non-nullable value type, the expansion is:
            // SPEC:
            // SPEC: {
            // SPEC:   ResourceType resource = expr;
            // SPEC:   try { statement; }
            // SPEC:   finally { ((IDisposable)resource).Dispose(); }
            // SPEC: }
            // SPEC:
            // SPEC: Otherwise, when Resource type is a nullable value type or
            // SPEC: a reference type other than dynamic, the expansion is:
            // SPEC:
            // SPEC: {
            // SPEC:   ResourceType resource = expr;
            // SPEC:   try { statement; }
            // SPEC:   finally { if (resource != null) ((IDisposable)resource).Dispose(); }
            // SPEC: }
            // SPEC:
            // SPEC: Otherwise, when ResourceType is dynamic, the expansion is:
            // SPEC: {
            // SPEC:   dynamic resource = expr;
            // SPEC:   IDisposable d = (IDisposable)resource;
            // SPEC:   try { statement; }
            // SPEC:   finally { if (d != null) d.Dispose(); }
            // SPEC: }
            // SPEC:
            // SPEC: An implementation is permitted to implement a given using statement
            // SPEC: differently -- for example, for performance reasons -- as long as the
            // SPEC: behavior is consistent with the above expansion.
            //
            // And we do in fact generate the code slightly differently than precisely how it is
            // described above.
            //
            // First: if the type is a non-nullable value type then we do not do the
            // *boxing conversion* from the resource to IDisposable. Rather, we do
            // a *constrained virtual call* that elides the boxing if possible.
            //
            // Now, you might wonder if that is legal; isn't skipping the boxing producing
            // an observable difference? Because if the value type is mutable and the Dispose
            // mutates it, then skipping the boxing means that we are now mutating the original,
            // not the boxed copy. But this is never observable. Either (1) we have "using(R r = x){}"
            // and r is out of scope after the finally, so it is not possible to observe the mutation,
            // or (2) we have "using(x) {}". But that has the semantics of "using(R temp = x){}",
            // so again, we are not mutating x to begin with; we're always mutating a copy. Therefore
            // it doesn't matter if we skip making *a copy of the copy*.
            //
            // This is what the dev10 compiler does, and we do so as well.
            //
            // Second: if the type is a nullable value type then we can similarly elide the boxing.
            // We can generate
            //
            // {
            //   ResourceType resource = expr;
            //   try { statement; }
            //   finally { if (resource.HasValue) resource.GetValueOrDefault().Dispose(); }
            // }
            //
            // Where again we do a constrained virtual call to Dispose, rather than boxing
            // the value to IDisposable.
            //
            // Note that this optimization is *not* what the native compiler does; in this case
            // the native compiler behavior is to test for HasValue, then *box* and convert
            // the boxed value to IDisposable. There's no need to do that.
            //
            // Third: if we have "using(x)" and x is dynamic then obviously we need not generate
            // "{ dynamic temp1 = x; IDisposable temp2 = (IDisposable) temp1; ... }". Rather, we elide
            // the completely unnecessary first temporary.

            BoundExpression disposedExpression;
            bool            isNullableValueType = local.Type.IsNullableType();

            if (isNullableValueType)
            {
                MethodSymbol getValueOrDefault = GetNullableMethod(syntax, local.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
                // local.GetValueOrDefault()
                disposedExpression = BoundCall.Synthesized(syntax, local, getValueOrDefault);
            }
            else
            {
                // local
                disposedExpression = local;
            }

            // local.Dispose()
            BoundExpression disposeCall;

            MethodSymbol disposeMethodSymbol;

            if (TryGetSpecialTypeMember(syntax, SpecialMember.System_IDisposable__Dispose, out disposeMethodSymbol))
            {
                disposeCall = BoundCall.Synthesized(syntax, disposedExpression, disposeMethodSymbol);
            }
            else
            {
                disposeCall = new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray.Create <BoundNode>(disposedExpression), ErrorTypeSymbol.UnknownResultType);
            }

            // local.Dispose();
            BoundStatement disposeStatement = new BoundExpressionStatement(syntax, disposeCall);

            BoundExpression ifCondition;

            if (isNullableValueType)
            {
                MethodSymbol hasValue = GetNullableMethod(syntax, local.Type, SpecialMember.System_Nullable_T_get_HasValue);
                // local.HasValue
                ifCondition = BoundCall.Synthesized(syntax, local, hasValue);
            }
            else if (local.Type.IsValueType)
            {
                ifCondition = null;
            }
            else
            {
                // local != null
                ifCondition = MakeNullCheck(syntax, local, BinaryOperatorKind.NotEqual);
            }

            BoundStatement finallyStatement;

            if (ifCondition == null)
            {
                // local.Dispose();
                finallyStatement = disposeStatement;
            }
            else
            {
                // if (local != null) local.Dispose();
                // or
                // if (local.HasValue) local.GetValueOrDefault().Dispose();
                finallyStatement = RewriteIfStatement(
                    syntax: syntax,
                    rewrittenCondition: ifCondition,
                    rewrittenConsequence: disposeStatement,
                    rewrittenAlternativeOpt: null,
                    hasErrors: false);
            }

            // try { ... } finally { if (local != null) local.Dispose(); }
            BoundStatement tryFinally = new BoundTryStatement(
                syntax: syntax,
                tryBlock: tryBlock,
                catchBlocks: ImmutableArray <BoundCatchBlock> .Empty,
                finallyBlockOpt: BoundBlock.SynthesizedNoLocals(syntax, finallyStatement));

            return(tryFinally);
        }
Exemple #40
0
        /// <summary>
        /// If the call represents an extension method with an explicit receiver, return a
        /// ReducedExtensionMethodSymbol if it can be constructed. Otherwise, return the 
        /// original call method.
        /// </summary>
        private static ImmutableArray<Symbol> CreateReducedExtensionMethodIfPossible(BoundCall call)
        {
            var method = call.Method;
            Debug.Assert((object)method != null);

            if (call.InvokedAsExtensionMethod && method.IsExtensionMethod && method.MethodKind != MethodKind.ReducedExtension)
            {
                Debug.Assert(call.Arguments.Length > 0);
                BoundExpression receiver = call.Arguments[0];
                MethodSymbol reduced = method.ReduceExtensionMethod(receiver.Type);
                // If the extension method can't be applied to the receiver of the given
                // type, we should also return the original call method.
                method = reduced ?? method;
            }
            return ImmutableArray.Create<Symbol>(method);
        }
        /// <summary>
        /// Generate a thread-safe accessor for a WinRT field-like event.
        ///
        /// Add:
        ///   return EventRegistrationTokenTable&lt;Event&gt;.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddEventHandler(value);
        ///
        /// Remove:
        ///   EventRegistrationTokenTable&lt;Event&gt;.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).RemoveEventHandler(value);
        /// </summary>
        internal static BoundBlock ConstructFieldLikeEventAccessorBody_WinRT(SourceEventSymbol eventSymbol, bool isAddMethod, CSharpCompilation compilation, DiagnosticBag diagnostics)
        {
            CSharpSyntaxNode syntax = eventSymbol.CSharpSyntaxNode;

            MethodSymbol accessor = isAddMethod ? eventSymbol.AddMethod : eventSymbol.RemoveMethod;

            Debug.Assert((object)accessor != null);

            FieldSymbol field = eventSymbol.AssociatedField;

            Debug.Assert((object)field != null);

            NamedTypeSymbol fieldType = (NamedTypeSymbol)field.Type;

            Debug.Assert(fieldType.Name == "EventRegistrationTokenTable");

            MethodSymbol getOrCreateMethod = (MethodSymbol)Binder.GetWellKnownTypeMember(
                compilation,
                WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__GetOrCreateEventRegistrationTokenTable,
                diagnostics,
                syntax: syntax);

            if ((object)getOrCreateMethod == null)
            {
                Debug.Assert(diagnostics.HasAnyErrors());
                return(null);
            }

            getOrCreateMethod = getOrCreateMethod.AsMember(fieldType);

            WellKnownMember processHandlerMember = isAddMethod
                ? WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__AddEventHandler
                : WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__RemoveEventHandler;

            MethodSymbol processHandlerMethod = (MethodSymbol)Binder.GetWellKnownTypeMember(
                compilation,
                processHandlerMember,
                diagnostics,
                syntax: syntax);

            if ((object)processHandlerMethod == null)
            {
                Debug.Assert(diagnostics.HasAnyErrors());
                return(null);
            }

            processHandlerMethod = processHandlerMethod.AsMember(fieldType);

            // _tokenTable
            BoundFieldAccess fieldAccess = new BoundFieldAccess(
                syntax,
                field.IsStatic ? null : new BoundThisReference(syntax, accessor.ThisParameter.Type),
                field,
                constantValueOpt: null)
            {
                WasCompilerGenerated = true
            };

            // EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable)
            BoundCall getOrCreateCall = BoundCall.Synthesized(
                syntax,
                receiverOpt: null,
                method: getOrCreateMethod,
                arg0: fieldAccess);

            // value
            BoundParameter parameterAccess = new BoundParameter(
                syntax,
                accessor.Parameters.Single());

            // EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddHandler(value) // or RemoveHandler
            BoundCall processHandlerCall = BoundCall.Synthesized(
                syntax,
                receiverOpt: getOrCreateCall,
                method: processHandlerMethod,
                arg0: parameterAccess);

            if (isAddMethod)
            {
                // {
                //     return EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddHandler(value);
                // }
                BoundStatement returnStatement = BoundReturnStatement.Synthesized(syntax, processHandlerCall);
                return(BoundBlock.SynthesizedNoLocals(syntax, returnStatement));
            }
            else
            {
                // {
                //     EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).RemoveHandler(value);
                //     return;
                // }
                BoundStatement callStatement   = new BoundExpressionStatement(syntax, processHandlerCall);
                BoundStatement returnStatement = new BoundReturnStatement(syntax, expressionOpt: null);
                return(BoundBlock.SynthesizedNoLocals(syntax, callStatement, returnStatement));
            }
        }
        private BoundExpression MakeNewT(CSharpSyntaxNode syntax, TypeParameterSymbol typeParameter)
        {
            // How "new T()" is rewritten depends on whether T is known to be a value
            // type, a reference type, or neither (see OperatorRewriter::VisitNEWTYVAR).

            if (typeParameter.IsValueType)
            {
                // "new T()" rewritten as: "default(T)".
                return new BoundDefaultOperator(syntax, type: typeParameter);
            }

            // For types not known to be value types, "new T()" requires
            // Activator.CreateInstance<T>().

            MethodSymbol method;

            if (!this.TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Activator__CreateInstance_T, out method))
            {
                return new BoundDefaultOperator(syntax, null, type: typeParameter, hasErrors: true);
            }

            Debug.Assert((object)method != null);
            method = method.Construct(ImmutableArray.Create<TypeSymbol>(typeParameter));

            var createInstanceCall = new BoundCall(
                syntax,
                null,
                method,
                ImmutableArray<BoundExpression>.Empty,
                default(ImmutableArray<string>),
                default(ImmutableArray<RefKind>),
                isDelegateCall: false,
                expanded: false,
                invokedAsExtensionMethod: false,
                argsToParamsOpt: default(ImmutableArray<int>),
                resultKind: LookupResultKind.Viable,
                type: typeParameter);

            if (typeParameter.IsReferenceType)
            {
                // "new T()" is rewritten as: "Activator.CreateInstance<T>()".
                return createInstanceCall;
            }
            else
            {
                // "new T()" is rewritten as: "(null == (object)default(T)) ? Activator.CreateInstance<T>() : default(T)".
                var defaultT = new BoundDefaultOperator(syntax, type: typeParameter);
                return new BoundConditionalOperator(
                    syntax,
                    MakeNullCheck(
                        syntax: syntax,
                        rewrittenExpr: MakeConversion(
                            syntax: syntax,
                            rewrittenOperand: defaultT,
                            conversionKind: ConversionKind.Boxing,
                            rewrittenType: this.compilation.GetSpecialType(SpecialType.System_Object),
                            @checked: false),
                        operatorKind: BinaryOperatorKind.Equal),
                    createInstanceCall,
                    defaultT,
                    constantValueOpt: null,
                    type: typeParameter);
            }
        }
Exemple #43
0
        private BoundExpression LowerLiftedUnaryOperator(
            UnaryOperatorKind kind,
            SyntaxNode syntax,
            MethodSymbol method,
            BoundExpression loweredOperand,
            TypeSymbol type)
        {
            // First, an optimization. If we know that the operand is always null then
            // we can simply lower to the alternative.

            BoundExpression optimized = OptimizeLiftedUnaryOperator(kind, syntax, method, loweredOperand, type);

            if (optimized != null)
            {
                return(optimized);
            }

            // We do not know whether the operand is null or non-null, so we generate:
            //
            // S? temp = operand;
            // R? r = temp.HasValue ?
            //        new R?(OP(temp.GetValueOrDefault())) :
            //        default(R?);

            BoundAssignmentOperator tempAssignment;
            BoundLocal   boundTemp         = _factory.StoreToTemp(loweredOperand, out tempAssignment);
            MethodSymbol getValueOrDefault = UnsafeGetNullableMethod(syntax, boundTemp.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);

            // temp.HasValue
            BoundExpression condition = MakeNullableHasValue(syntax, boundTemp);

            // temp.GetValueOrDefault()
            BoundExpression call_GetValueOrDefault = BoundCall.Synthesized(syntax, boundTemp, getValueOrDefault);

            // new R?(temp.GetValueOrDefault())
            BoundExpression consequence = GetLiftedUnaryOperatorConsequence(kind, syntax, method, type, call_GetValueOrDefault);

            // default(R?)
            BoundExpression alternative = new BoundDefaultOperator(syntax, null, type);

            // temp.HasValue ?
            //          new R?(OP(temp.GetValueOrDefault())) :
            //          default(R?);
            BoundExpression conditionalExpression = RewriteConditionalOperator(
                syntax: syntax,
                rewrittenCondition: condition,
                rewrittenConsequence: consequence,
                rewrittenAlternative: alternative,
                constantValueOpt: null,
                rewrittenType: type);

            // temp = operand;
            // temp.HasValue ?
            //          new R?(OP(temp.GetValueOrDefault())) :
            //          default(R?);
            return(new BoundSequence(
                       syntax: syntax,
                       locals: ImmutableArray.Create <LocalSymbol>(boundTemp.LocalSymbol),
                       sideEffects: ImmutableArray.Create <BoundExpression>(tempAssignment),
                       value: conditionalExpression,
                       type: type));
        }
Exemple #44
0
 private static BoundExpression ExtractCastInvocation(BoundCall invocation)
 {
     int index = invocation.InvokedAsExtensionMethod ? 1 : 0;
     var c1 = invocation.Arguments[index] as BoundConversion;
     var l1 = c1 != null ? c1.Operand as BoundLambda : null;
     var r1 = l1 != null ? l1.Body.Statements[0] as BoundReturnStatement : null;
     var i1 = r1 != null ? r1.ExpressionOpt as BoundCall : null;
     return i1;
 }
Exemple #45
0
        private BoundExpression MakeUnaryOperator(
            BoundUnaryOperator oldNode,
            UnaryOperatorKind kind,
            SyntaxNode syntax,
            MethodSymbol method,
            BoundExpression loweredOperand,
            TypeSymbol type)
        {
            if (kind.IsDynamic())
            {
                Debug.Assert(kind == UnaryOperatorKind.DynamicTrue && type.SpecialType == SpecialType.System_Boolean || type.IsDynamic());
                Debug.Assert((object)method == null);

                // Logical operators on boxed Boolean constants:
                var constant = UnboxConstant(loweredOperand);
                if (constant == ConstantValue.True || constant == ConstantValue.False)
                {
                    if (kind == UnaryOperatorKind.DynamicTrue)
                    {
                        return(_factory.Literal(constant.BooleanValue));
                    }
                    else if (kind == UnaryOperatorKind.DynamicLogicalNegation)
                    {
                        return(MakeConversionNode(_factory.Literal(!constant.BooleanValue), type, @checked: false));
                    }
                }

                return(_dynamicFactory.MakeDynamicUnaryOperator(kind, loweredOperand, type).ToExpression());
            }
            else if (kind.IsLifted())
            {
                if (!_inExpressionLambda)
                {
                    return(LowerLiftedUnaryOperator(kind, syntax, method, loweredOperand, type));
                }
            }
            else if (kind.IsUserDefined())
            {
                Debug.Assert((object)method != null);
                Debug.Assert(type == method.ReturnType);
                if (!_inExpressionLambda || kind == UnaryOperatorKind.UserDefinedTrue || kind == UnaryOperatorKind.UserDefinedFalse)
                {
                    return(BoundCall.Synthesized(syntax, null, method, loweredOperand));
                }
            }
            else if (kind.Operator() == UnaryOperatorKind.UnaryPlus)
            {
                // We do not call the operator even for decimal; we simply optimize it away entirely.
                return(loweredOperand);
            }

            if (kind == UnaryOperatorKind.EnumBitwiseComplement)
            {
                var underlyingType       = loweredOperand.Type.GetEnumUnderlyingType();
                var upconvertSpecialType = Binder.GetEnumPromotedType(underlyingType.SpecialType);
                var upconvertType        = upconvertSpecialType == underlyingType.SpecialType ?
                                           underlyingType :
                                           _compilation.GetSpecialType(upconvertSpecialType);


                var newOperand            = MakeConversionNode(loweredOperand, upconvertType, false);
                UnaryOperatorKind newKind = kind.Operator().WithType(upconvertSpecialType);

                var newNode = (oldNode != null) ?
                              oldNode.Update(
                    newKind,
                    newOperand,
                    oldNode.ConstantValueOpt,
                    method,
                    newOperand.ResultKind,
                    upconvertType) :
                              new BoundUnaryOperator(
                    syntax,
                    newKind,
                    newOperand,
                    null,
                    method,
                    LookupResultKind.Viable,
                    upconvertType);

                return(MakeConversionNode(newNode.Syntax, newNode, Conversion.ExplicitEnumeration, type, @checked: false));
            }

            if (kind == UnaryOperatorKind.DecimalUnaryMinus)
            {
                method = (MethodSymbol)_compilation.Assembly.GetSpecialTypeMember(SpecialMember.System_Decimal__op_UnaryNegation);
                if (!_inExpressionLambda)
                {
                    return(BoundCall.Synthesized(syntax, null, method, loweredOperand));
                }
            }

            return((oldNode != null) ?
                   oldNode.Update(kind, loweredOperand, oldNode.ConstantValueOpt, method, oldNode.ResultKind, type) :
                   new BoundUnaryOperator(syntax, kind, loweredOperand, null, method, LookupResultKind.Viable, type));
        }
Exemple #46
0
 private static BoundCall ReverseLastTwoParameterOrder(BoundCall result)
 {
     // The input call has its arguments in the appropriate order for the invocation, but its last
     // two argument expressions appear in the reverse order from which they appeared in source.
     // Since we want region analysis to see them in source order, we rewrite the call so that these
     // two arguments are evaluated in source order.
     int n = result.Arguments.Length;
     var arguments = ArrayBuilder<BoundExpression>.GetInstance();
     arguments.AddRange(result.Arguments);
     var lastArgument = arguments[n - 1];
     arguments[n - 1] = arguments[n - 2];
     arguments[n - 2] = lastArgument;
     var argsToParams = ArrayBuilder<int>.GetInstance();
     argsToParams.AddRange(Enumerable.Range(0, n));
     argsToParams[n - 1] = n - 2;
     argsToParams[n - 2] = n - 1;
     return result.Update(
         result.ReceiverOpt, result.Method, arguments.ToImmutableAndFree(), default(ImmutableArray<string>),
         default(ImmutableArray<RefKind>), result.IsDelegateCall, result.Expanded, result.InvokedAsExtensionMethod,
         argsToParams.ToImmutableAndFree(), result.ResultKind, result.Type);
 }
 public override BoundNode VisitCall(BoundCall node)
 {
     if (node.Method.MethodKind == MethodKind.LocalFunction)
     {
         // Use OriginalDefinition to strip generic type parameters
         ReferenceVariable(node.Syntax, node.Method.OriginalDefinition);
     }
     return base.VisitCall(node);
 }
Exemple #48
0
        private BoundExpression MakeCall(
            BoundCall node,
            SyntaxNode syntax,
            BoundExpression rewrittenReceiver,
            MethodSymbol method,
            ImmutableArray<BoundExpression> rewrittenArguments,
            ImmutableArray<RefKind> argumentRefKinds,
            bool invokedAsExtensionMethod,
            LookupResultKind resultKind,
            TypeSymbol type,
            ImmutableArray<LocalSymbol> temps = default(ImmutableArray<LocalSymbol>))
        {
            BoundExpression rewrittenBoundCall;

            if (method.IsStatic &&
                method.ContainingType.IsObjectType() &&
                !_inExpressionLambda &&
                (object)method == (object)_compilation.GetSpecialTypeMember(SpecialMember.System_Object__ReferenceEquals))
            {
                Debug.Assert(rewrittenArguments.Length == 2);

                // ECMA - 335
                // I.8.2.5.1 Identity
                //           ...
                //           Identity is implemented on System.Object via the ReferenceEquals method.
                rewrittenBoundCall = new BoundBinaryOperator(
                    syntax,
                    BinaryOperatorKind.ObjectEqual,
                    rewrittenArguments[0],
                    rewrittenArguments[1],
                    null,
                    null,
                    resultKind,
                    type);
            }
            else if (node == null)
            {
                rewrittenBoundCall = new BoundCall(
                    syntax,
                    rewrittenReceiver,
                    method,
                    rewrittenArguments,
                    default(ImmutableArray<string>),
                    argumentRefKinds,
                    isDelegateCall: false,
                    expanded: false,
                    invokedAsExtensionMethod: invokedAsExtensionMethod,
                    argsToParamsOpt: default(ImmutableArray<int>),
                    resultKind: resultKind,
                    type: type);
            }
            else
            {
                rewrittenBoundCall = node.Update(
                    rewrittenReceiver,
                    method,
                    rewrittenArguments,
                    default(ImmutableArray<string>),
                    argumentRefKinds,
                    node.IsDelegateCall,
                    false,
                    node.InvokedAsExtensionMethod,
                    default(ImmutableArray<int>),
                    node.ResultKind,
                    node.Type);
            }

            if (!temps.IsDefaultOrEmpty)
            {
                return new BoundSequence(
                    syntax,
                    locals: temps,
                    sideEffects: ImmutableArray<BoundExpression>.Empty,
                    value: rewrittenBoundCall,
                    type: type);
            }

            return rewrittenBoundCall;
        }