예제 #1
0
        public static LoweredDynamicOperation Bad(TypeSymbol resultType, ImmutableArray <BoundExpression> children)
        {
            Debug.Assert(children.Length > 0);
            var bad = new BoundBadExpression(children[0].Syntax, LookupResultKind.Empty, ImmutableArray <Symbol> .Empty, children, resultType);

            return(new LoweredDynamicOperation(null, null, bad, resultType, default(ImmutableArray <LocalSymbol>)));
        }
예제 #2
0
        private void ReduceLet(LetClauseSyntax let, QueryTranslationState state, DiagnosticBag diagnostics)
        {
            // A query expression with a let clause
            //     from x in e
            //     let y = f
            //     ...
            // is translated into
            //     from * in ( e ) . Select ( x => new { x , y = f } )
            //     ...
            var x = state.rangeVariable;

            // We use a slightly different translation strategy.  We produce
            //     from * in ( e ) . Select ( x => new Pair<X,Y>(x, f) )
            // Where X is the type of x, and Y is the type of the expression f.
            // Subsequently, x (or members of x, if it is a transparent identifier)
            // are accessed as TRID.Item1 (or members of that), and y is accessed
            // as TRID.Item2, where TRID is the compiler-generated identifier used
            // to represent the transparent identifier in the result.
            LambdaBodyFactory bodyFactory = (LambdaSymbol lambdaSymbol, Binder lambdaBodyBinder, DiagnosticBag d) =>
            {
                var xExpression = new BoundParameter(let, lambdaSymbol.Parameters[0])
                {
                    WasCompilerGenerated = true
                };

                lambdaBodyBinder = lambdaBodyBinder.GetBinder(let.Expression);
                Debug.Assert(lambdaBodyBinder != null);

                var            yExpression   = lambdaBodyBinder.BindValue(let.Expression, d, BindValueKind.RValue);
                SourceLocation errorLocation = new SourceLocation(let.SyntaxTree, new TextSpan(let.Identifier.SpanStart, let.Expression.Span.End - let.Identifier.SpanStart));
                if (!yExpression.HasAnyErrors && !yExpression.HasExpressionType())
                {
                    Error(d, ErrorCode.ERR_QueryRangeVariableAssignedBadValue, errorLocation, yExpression.Display);
                    yExpression = new BoundBadExpression(yExpression.Syntax, LookupResultKind.Empty, ImmutableArray <Symbol> .Empty, ImmutableArray.Create(yExpression), CreateErrorType());
                }
                else if (!yExpression.HasAnyErrors && yExpression.Type.SpecialType == SpecialType.System_Void)
                {
                    Error(d, ErrorCode.ERR_QueryRangeVariableAssignedBadValue, errorLocation, yExpression.Type);
                    yExpression = new BoundBadExpression(yExpression.Syntax, LookupResultKind.Empty, ImmutableArray <Symbol> .Empty, ImmutableArray.Create(yExpression), yExpression.Type);
                }

                var construction = MakePair(let, x.Name, xExpression, let.Identifier.ValueText, yExpression, state, d);

                // The bound block represents a closure scope for transparent identifiers captured in the let clause.
                // Such closures shall be associated with the lambda body expression.
                return(lambdaBodyBinder.CreateLambdaBlockForQueryClause(let.Expression, construction, d));
            };

            var lambda = MakeQueryUnboundLambda(state.RangeVariableMap(), ImmutableArray.Create(x), let.Expression, bodyFactory);

            state.rangeVariable = state.TransparentRangeVariable(this);
            state.AddTransparentIdentifier(x.Name);
            var y = state.AddRangeVariable(this, let.Identifier, diagnostics);

            state.allRangeVariables[y].Add(let.Identifier.ValueText);
            var invocation = MakeQueryInvocation(let, state.fromExpression, "Select", lambda, diagnostics);

            state.fromExpression = MakeQueryClause(let, invocation, y, invocation);
        }
        private BoundExpression GenerateDisposeCall(SyntaxNode syntax, BoundExpression disposedExpression, MethodSymbol methodOpt, AwaitableInfo awaitOpt, SyntaxToken awaitKeyword)
        {
            Debug.Assert(awaitOpt is null || awaitKeyword != default);

            // If we don't have an explicit dispose method, try and get the special member for IDiposable/IAsyncDisposable
            if (methodOpt is null)
            {
                if (awaitOpt is null)
                {
                    // IDisposable.Dispose()
                    Binder.TryGetSpecialTypeMember(_compilation, SpecialMember.System_IDisposable__Dispose, syntax, _diagnostics, out methodOpt);
                }
                else
                {
                    // IAsyncDisposable.DisposeAsync()
                    TryGetWellKnownTypeMember(syntax: null, WellKnownMember.System_IAsyncDisposable__DisposeAsync, out methodOpt, location: awaitKeyword.GetLocation());
                }
            }

            BoundExpression disposeCall;

            if (methodOpt is null)
            {
                disposeCall = new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray.Create(disposedExpression), ErrorTypeSymbol.UnknownResultType);
            }
            else
            {
                disposeCall = MakeCallWithNoExplicitArgument(syntax, disposedExpression, methodOpt);

                if (!(awaitOpt is null))
                {
                    // await local.DisposeAsync()
                    _sawAwaitInExceptionHandler = true;

                    TypeSymbol awaitExpressionType = awaitOpt.GetResult?.ReturnType.TypeSymbol ?? _compilation.DynamicType;
                    disposeCall = RewriteAwaitExpression(syntax, disposeCall, awaitOpt, awaitExpressionType, false);
                }
            }

            return(disposeCall);
        }
예제 #4
0
        private BoundExpression MakePair(CSharpSyntaxNode node, string field1Name, BoundExpression field1Value, string field2Name, BoundExpression field2Value, QueryTranslationState state, DiagnosticBag diagnostics)
        {
            if (field1Name == field2Name)
            {
                // we will generate a diagnostic elsewhere
                field2Name  = state.TransparentRangeVariableName();
                field2Value = new BoundBadExpression(field2Value.Syntax, LookupResultKind.Empty, ImmutableArray <Symbol> .Empty, ImmutableArray.Create(field2Value), field2Value.Type, true);
            }

            AnonymousTypeDescriptor typeDescriptor = new AnonymousTypeDescriptor(
                ImmutableArray.Create <AnonymousTypeField>(
                    new AnonymousTypeField(field1Name, field1Value.Syntax.Location,
                                           TypeSymbolWithAnnotations.Create(TypeOrError(field1Value))),
                    new AnonymousTypeField(field2Name, field2Value.Syntax.Location,
                                           TypeSymbolWithAnnotations.Create(TypeOrError(field2Value)))
                    ),
                node.Location
                );

            AnonymousTypeManager manager       = this.Compilation.AnonymousTypeManager;
            NamedTypeSymbol      anonymousType = manager.ConstructAnonymousTypeSymbol(typeDescriptor);

            return(MakeConstruction(node, anonymousType, ImmutableArray.Create(field1Value, field2Value), diagnostics));
        }
예제 #5
0
 public override BoundNode VisitBadExpression(BoundBadExpression node)
 {
     // Cannot recurse into BadExpression children
     return(node);
 }
예제 #6
0
        public override BoundNode VisitNoPiaObjectCreationExpression(BoundNoPiaObjectCreationExpression node)
        {
            // For the NoPIA feature, we need to gather the GUID from the coclass, and
            // generate the following:
            //
            // (IPiaType)System.Activator.CreateInstance(System.Runtime.InteropServices.Marshal.GetTypeFromCLSID(new Guid(GUID)))
            //
            // If System.Runtime.InteropServices.Marshal.GetTypeFromCLSID is not available (older framework),
            // System.Type.GetTypeFromCLSID() is used to get the type for the CLSID:
            //
            // (IPiaType)System.Activator.CreateInstance(System.Type.GetTypeFromCLSID(new Guid(GUID)))

            SyntaxNode oldSyntax = _factory.Syntax;

            _factory.Syntax = node.Syntax;

            var             ctor = _factory.WellKnownMethod(WellKnownMember.System_Guid__ctor);
            BoundExpression newGuid;

            if ((object)ctor != null)
            {
                newGuid = _factory.New(ctor, _factory.Literal(node.GuidString));
            }
            else
            {
                newGuid = new BoundBadExpression(node.Syntax, LookupResultKind.NotCreatable, ImmutableArray <Symbol> .Empty, ImmutableArray <BoundExpression> .Empty, ErrorTypeSymbol.UnknownResultType);
            }

            var getTypeFromCLSID = _factory.WellKnownMethod(WellKnownMember.System_Runtime_InteropServices_Marshal__GetTypeFromCLSID, isOptional: true);

            if ((object)getTypeFromCLSID == null)
            {
                getTypeFromCLSID = _factory.WellKnownMethod(WellKnownMember.System_Type__GetTypeFromCLSID);
            }

            BoundExpression callGetTypeFromCLSID;

            if ((object)getTypeFromCLSID != null)
            {
                callGetTypeFromCLSID = _factory.Call(null, getTypeFromCLSID, newGuid);
            }
            else
            {
                callGetTypeFromCLSID = new BoundBadExpression(node.Syntax, LookupResultKind.OverloadResolutionFailure, ImmutableArray <Symbol> .Empty, ImmutableArray <BoundExpression> .Empty, ErrorTypeSymbol.UnknownResultType);
            }

            var             createInstance = _factory.WellKnownMethod(WellKnownMember.System_Activator__CreateInstance);
            BoundExpression rewrittenObjectCreation;

            if ((object)createInstance != null)
            {
                rewrittenObjectCreation = _factory.Convert(node.Type, _factory.Call(null, createInstance, callGetTypeFromCLSID));
            }
            else
            {
                rewrittenObjectCreation = new BoundBadExpression(node.Syntax, LookupResultKind.OverloadResolutionFailure, ImmutableArray <Symbol> .Empty, ImmutableArray <BoundExpression> .Empty, node.Type);
            }

            _factory.Syntax = oldSyntax;

            if (node.InitializerExpressionOpt == null || node.InitializerExpressionOpt.HasErrors)
            {
                return(rewrittenObjectCreation);
            }

            return(MakeObjectCreationWithInitializer(node.Syntax, rewrittenObjectCreation, node.InitializerExpressionOpt, node.Type));
        }
 public sealed override BoundNode VisitBadExpression(BoundBadExpression node)
 {
     // Cannot recurse into BadExpression
     return(node);
 }
        /// <summary>
        /// <![CDATA[
        /// fixed(int* ptr = arr){ ... }    == becomes ===>
        ///
        /// pinned int[] pinnedTemp = arr;         // pinning managed ref
        /// int* ptr = pinnedTemp != null && pinnedTemp.Length != 0
        ///                (int*)&pinnedTemp[0]:   // unsafe cast to unmanaged ptr
        ///                0;
        ///   . . .
        ///   ]]>
        /// </summary>
        private BoundStatement InitializeFixedStatementArrayLocal(
            BoundLocalDeclaration localDecl,
            LocalSymbol localSymbol,
            BoundFixedLocalCollectionInitializer fixedInitializer,
            SyntheticBoundNodeFactory factory,
            out LocalSymbol pinnedTemp)
        {
            TypeSymbol      localType       = localSymbol.Type.TypeSymbol;
            BoundExpression initializerExpr = VisitExpression(fixedInitializer.Expression);
            TypeSymbol      initializerType = initializerExpr.Type;

            pinnedTemp = factory.SynthesizedLocal(initializerType, isPinned: true);
            ArrayTypeSymbol           arrayType        = (ArrayTypeSymbol)pinnedTemp.Type.TypeSymbol;
            TypeSymbolWithAnnotations arrayElementType = arrayType.ElementType;

            // NOTE: we pin the array, not the pointer.
            Debug.Assert(pinnedTemp.IsPinned);
            Debug.Assert(!localSymbol.IsPinned);

            //(pinnedTemp = array)
            BoundExpression arrayTempInit = factory.AssignmentExpression(factory.Local(pinnedTemp), initializerExpr);

            //(pinnedTemp = array) != null
            BoundExpression notNullCheck = MakeNullCheck(factory.Syntax, arrayTempInit, BinaryOperatorKind.NotEqual);

            BoundExpression lengthCall;

            if (arrayType.IsSZArray)
            {
                lengthCall = factory.ArrayLength(factory.Local(pinnedTemp));
            }
            else
            {
                MethodSymbol lengthMethod;
                if (TryGetWellKnownTypeMember(fixedInitializer.Syntax, WellKnownMember.System_Array__get_Length, out lengthMethod))
                {
                    lengthCall = factory.Call(factory.Local(pinnedTemp), lengthMethod);
                }
                else
                {
                    lengthCall = new BoundBadExpression(fixedInitializer.Syntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray.Create <BoundExpression>(factory.Local(pinnedTemp)), ErrorTypeSymbol.UnknownResultType);
                }
            }

            // NOTE: dev10 comment says ">", but code actually checks "!="
            //temp.Length != 0
            BoundExpression lengthCheck = factory.Binary(BinaryOperatorKind.Int32NotEqual, factory.SpecialType(SpecialType.System_Boolean), lengthCall, factory.Literal(0));

            //((temp = array) != null && temp.Length != 0)
            BoundExpression condition = factory.Binary(BinaryOperatorKind.LogicalBoolAnd, factory.SpecialType(SpecialType.System_Boolean), notNullCheck, lengthCheck);

            //temp[0]
            BoundExpression firstElement = factory.ArrayAccessFirstElement(factory.Local(pinnedTemp));

            // NOTE: this is a fixed statement address-of in that it's the initial value of the pointer.
            //&temp[0]
            BoundExpression firstElementAddress          = new BoundAddressOfOperator(factory.Syntax, firstElement, type: new PointerTypeSymbol(arrayElementType));
            BoundExpression convertedFirstElementAddress = factory.Convert(
                localType,
                firstElementAddress,
                fixedInitializer.ElementPointerTypeConversion);

            //loc = &temp[0]
            BoundExpression consequenceAssignment = factory.AssignmentExpression(factory.Local(localSymbol), convertedFirstElementAddress);

            //loc = null
            BoundExpression alternativeAssignment = factory.AssignmentExpression(factory.Local(localSymbol), factory.Null(localType));

            //(((temp = array) != null && temp.Length != 0) ? loc = &temp[0] : loc = null)
            BoundStatement localInit = factory.ExpressionStatement(
                new BoundConditionalOperator(factory.Syntax, false, condition, consequenceAssignment, alternativeAssignment, ConstantValue.NotAvailable, localType));

            return(InstrumentLocalDeclarationIfNecessary(localDecl, localSymbol, localInit));
        }
        /// <summary>
        /// fixed(char* ptr = stringVar){ ... }    == becomes ===>
        ///
        /// pinned string pinnedTemp = stringVar;    // pinning managed ref
        /// char* ptr = (char*)pinnedTemp;           // unsafe cast to unmanaged ptr
        /// if (pinnedTemp != null) ptr += OffsetToStringData();
        ///   . . .
        /// </summary>
        private BoundStatement InitializeFixedStatementStringLocal(
            BoundLocalDeclaration localDecl,
            LocalSymbol localSymbol,
            BoundFixedLocalCollectionInitializer fixedInitializer,
            SyntheticBoundNodeFactory factory,
            out LocalSymbol pinnedTemp)
        {
            TypeSymbol      localType       = localSymbol.Type.TypeSymbol;
            BoundExpression initializerExpr = VisitExpression(fixedInitializer.Expression);
            TypeSymbol      initializerType = initializerExpr.Type;

            // intervening parens may have been skipped by the binder; find the declarator
            VariableDeclarationSyntax declarator = fixedInitializer.Syntax.FirstAncestorOrSelf <VariableDeclarationSyntax>();

            Debug.Assert(declarator != null);

            pinnedTemp = factory.SynthesizedLocal(
                initializerType,
                syntax: declarator,
                isPinned: true,
                kind: SynthesizedLocalKind.FixedReference);

            // NOTE: we pin the string, not the pointer.
            Debug.Assert(pinnedTemp.IsPinned);
            Debug.Assert(!localSymbol.IsPinned);

            BoundStatement stringTempInit = factory.Assignment(factory.Local(pinnedTemp), initializerExpr);

            // (char*)pinnedTemp;
            var addr = factory.Convert(
                fixedInitializer.ElementPointerType,
                factory.Local(pinnedTemp),
                Conversion.PinnedObjectToPointer);

            var convertedStringTemp = factory.Convert(
                localType,
                addr,
                fixedInitializer.ElementPointerTypeConversion);

            BoundStatement localInit = InstrumentLocalDeclarationIfNecessary(localDecl, localSymbol,
                                                                             factory.Assignment(factory.Local(localSymbol), convertedStringTemp));

            BoundExpression notNullCheck = MakeNullCheck(factory.Syntax, factory.Local(localSymbol), BinaryOperatorKind.NotEqual);
            BoundExpression helperCall;

            MethodSymbol offsetMethod;

            if (TryGetWellKnownTypeMember(fixedInitializer.Syntax, WellKnownMember.System_Runtime_CompilerServices_RuntimeHelpers__get_OffsetToStringData, out offsetMethod))
            {
                helperCall = factory.Call(receiver: null, method: offsetMethod);
            }
            else
            {
                helperCall = new BoundBadExpression(fixedInitializer.Syntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray <BoundExpression> .Empty, ErrorTypeSymbol.UnknownResultType);
            }

            BoundExpression addition       = factory.Binary(BinaryOperatorKind.PointerAndInt32Addition, localType, factory.Local(localSymbol), helperCall);
            BoundStatement  conditionalAdd = factory.If(notNullCheck, factory.Assignment(factory.Local(localSymbol), addition));

            return(factory.Block(stringTempInit, localInit, conditionalAdd));
        }
예제 #10
0
 public override BoundNode VisitBadExpression(BoundBadExpression node)
 {
     // Cannot recurse into BadExpression children since the BadExpression
     // may represent being unable to use the child as an lvalue or rvalue.
     return(node);
 }
예제 #11
0
        protected BoundCall MakeQueryInvocation(CSharpSyntaxNode node, BoundExpression receiver, string methodName, SeparatedSyntaxList <TypeSyntax> typeArgsSyntax, ImmutableArray <TypeSymbolWithAnnotations> typeArgs, ImmutableArray <BoundExpression> args, DiagnosticBag diagnostics)
        {
            // clean up the receiver
            var ultimateReceiver = receiver;

            while (ultimateReceiver.Kind == BoundKind.QueryClause)
            {
                ultimateReceiver = ((BoundQueryClause)ultimateReceiver).Value;
            }
            if ((object)ultimateReceiver.Type == null)
            {
                if (ultimateReceiver.HasAnyErrors || node.HasErrors)
                {
                    // report no additional errors
                }
                else if (ultimateReceiver.IsLiteralNull())
                {
                    diagnostics.Add(ErrorCode.ERR_NullNotValid, node.Location);
                }
                else if (ultimateReceiver.IsLiteralDefault())
                {
                    diagnostics.Add(ErrorCode.ERR_DefaultLiteralNotValid, node.Location);
                }
                else if (ultimateReceiver.Kind == BoundKind.NamespaceExpression)
                {
                    diagnostics.Add(ErrorCode.ERR_BadSKunknown, ultimateReceiver.Syntax.Location, ultimateReceiver.Syntax, MessageID.IDS_SK_NAMESPACE.Localize());
                }
                else if (ultimateReceiver.Kind == BoundKind.Lambda || ultimateReceiver.Kind == BoundKind.UnboundLambda)
                {
                    // Could not find an implementation of the query pattern for source type '{0}'.  '{1}' not found.
                    diagnostics.Add(ErrorCode.ERR_QueryNoProvider, node.Location, MessageID.IDS_AnonMethod.Localize(), methodName);
                }
                else if (ultimateReceiver.Kind == BoundKind.MethodGroup)
                {
                    var methodGroup = (BoundMethodGroup)ultimateReceiver;
                    HashSet <DiagnosticInfo> useSiteDiagnostics = null;
                    var resolution = this.ResolveMethodGroup(methodGroup, analyzedArguments: null, isMethodGroupConversion: false, useSiteDiagnostics: ref useSiteDiagnostics);
                    diagnostics.Add(node, useSiteDiagnostics);
                    diagnostics.AddRange(resolution.Diagnostics);
                    if (resolution.HasAnyErrors)
                    {
                        receiver = this.BindMemberAccessBadResult(methodGroup);
                    }
                    else
                    {
                        Debug.Assert(!resolution.IsEmpty);
                        diagnostics.Add(ErrorCode.ERR_QueryNoProvider, node.Location, MessageID.IDS_SK_METHOD.Localize(), methodName);
                    }
                    resolution.Free();
                }

                receiver = new BoundBadExpression(receiver.Syntax, LookupResultKind.NotAValue, ImmutableArray <Symbol> .Empty, ImmutableArray.Create(receiver), CreateErrorType());
            }
            else if (receiver.Type.SpecialType == SpecialType.System_Void)
            {
                if (!receiver.HasAnyErrors && !node.HasErrors)
                {
                    diagnostics.Add(ErrorCode.ERR_QueryNoProvider, node.Location, "void", methodName);
                }

                receiver = new BoundBadExpression(receiver.Syntax, LookupResultKind.NotAValue, ImmutableArray <Symbol> .Empty, ImmutableArray.Create(receiver), CreateErrorType());
            }

            return((BoundCall)MakeInvocationExpression(
                       node,
                       receiver,
                       methodName,
                       args,
                       diagnostics,
                       typeArgsSyntax,
                       typeArgs,
                       queryClause: node,
                       // Queries are syntactical rewrites, so we allow fields and properties of delegate types to be invoked,
                       // although no well-known non-generic query method is used atm.
                       allowFieldsAndProperties: true));
        }
        /// <summary>
        /// Lowers a lock statement to a try-finally block that calls Monitor.Enter and Monitor.Exit
        /// before and after the body, respectively.
        /// </summary>
        public override BoundNode VisitLockStatement(BoundLockStatement node)
        {
            LockStatementSyntax lockSyntax = (LockStatementSyntax)node.Syntax;

            BoundExpression rewrittenArgument = VisitExpression(node.Argument);
            BoundStatement  rewrittenBody     = (BoundStatement)Visit(node.Body);

            TypeSymbol argumentType = rewrittenArgument.Type;

            if ((object)argumentType == null)
            {
                // This isn't particularly elegant, but hopefully locking on null is
                // not very common.
                Debug.Assert(rewrittenArgument.ConstantValue == ConstantValue.Null);
                argumentType      = _compilation.GetSpecialType(SpecialType.System_Object);
                rewrittenArgument = MakeLiteral(
                    rewrittenArgument.Syntax,
                    rewrittenArgument.ConstantValue,
                    argumentType); //need to have a non-null type here for TempHelpers.StoreToTemp.
            }

            BoundAssignmentOperator assignmentToLockTemp;
            BoundLocal boundLockTemp = _factory.StoreToTemp(rewrittenArgument, out assignmentToLockTemp, syntaxOpt: lockSyntax, kind: SynthesizedLocalKind.Lock);

            BoundStatement  boundLockTempInit = new BoundExpressionStatement(lockSyntax, assignmentToLockTemp);
            BoundExpression exitCallExpr;

            MethodSymbol exitMethod;

            if (TryGetWellKnownTypeMember(lockSyntax, WellKnownMember.System_Threading_Monitor__Exit, out exitMethod))
            {
                exitCallExpr = BoundCall.Synthesized(
                    lockSyntax,
                    null,
                    exitMethod,
                    boundLockTemp);
            }
            else
            {
                exitCallExpr = new BoundBadExpression(lockSyntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray.Create <BoundExpression>(boundLockTemp), ErrorTypeSymbol.UnknownResultType);
            }

            BoundStatement exitCall = new BoundExpressionStatement(lockSyntax, exitCallExpr);

            MethodSymbol enterMethod;

            if ((TryGetWellKnownTypeMember(lockSyntax, WellKnownMember.System_Threading_Monitor__Enter2, out enterMethod, isOptional: true) ||
                 TryGetWellKnownTypeMember(lockSyntax, WellKnownMember.System_Threading_Monitor__Enter, out enterMethod)) && // If we didn't find the overload introduced in .NET 4.0, then use the older one.
                enterMethod.ParameterCount == 2)
            {
                // C# 4.0+ version
                // L $lock = `argument`;                      // sequence point
                // bool $lockTaken = false;
                // try
                // {
                //     Monitor.Enter($lock, ref $lockTaken);
                //     `body`                                 // sequence point
                // }
                // finally
                // {                                          // hidden sequence point
                //     if ($lockTaken) Monitor.Exit($lock);
                // }

                TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean);
                BoundAssignmentOperator assignmentToLockTakenTemp;

                BoundLocal boundLockTakenTemp = _factory.StoreToTemp(
                    MakeLiteral(rewrittenArgument.Syntax, ConstantValue.False, boolType),
                    store: out assignmentToLockTakenTemp,
                    syntaxOpt: lockSyntax,
                    kind: SynthesizedLocalKind.LockTaken);

                BoundStatement boundLockTakenTempInit = new BoundExpressionStatement(lockSyntax, assignmentToLockTakenTemp);

                BoundStatement enterCall = new BoundExpressionStatement(
                    lockSyntax,
                    BoundCall.Synthesized(
                        lockSyntax,
                        null,
                        enterMethod,
                        boundLockTemp,
                        boundLockTakenTemp));

                exitCall = RewriteIfStatement(
                    lockSyntax,
                    boundLockTakenTemp,
                    exitCall,
                    null,
                    node.HasErrors);

                return(new BoundBlock(
                           lockSyntax,
                           ImmutableArray.Create(boundLockTemp.LocalSymbol, boundLockTakenTemp.LocalSymbol),
                           ImmutableArray.Create(
                               InstrumentLockTargetCapture(node, boundLockTempInit),
                               boundLockTakenTempInit,
                               new BoundTryStatement(
                                   lockSyntax,
                                   BoundBlock.SynthesizedNoLocals(lockSyntax, ImmutableArray.Create(
                                                                      enterCall,
                                                                      rewrittenBody)),
                                   ImmutableArray <BoundCatchBlock> .Empty,
                                   BoundBlock.SynthesizedNoLocals(lockSyntax,
                                                                  exitCall)))));
            }
            else
            {
                // Pre-4.0 version
                // L $lock = `argument`;           // sequence point
                // Monitor.Enter($lock);           // NB: before try-finally so we don't Exit if an exception prevents us from acquiring the lock.
                // try
                // {
                //     `body`                      // sequence point
                // }
                // finally
                // {
                //     Monitor.Exit($lock);        // hidden sequence point
                // }

                BoundExpression enterCallExpr;

                if ((object)enterMethod != null)
                {
                    Debug.Assert(enterMethod.ParameterCount == 1);

                    enterCallExpr = BoundCall.Synthesized(
                        lockSyntax,
                        null,
                        enterMethod,
                        boundLockTemp);
                }
                else
                {
                    enterCallExpr = new BoundBadExpression(lockSyntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray.Create <BoundExpression>(boundLockTemp), ErrorTypeSymbol.UnknownResultType);
                }

                BoundStatement enterCall = new BoundExpressionStatement(
                    lockSyntax,
                    enterCallExpr);

                return(new BoundBlock(
                           lockSyntax,
                           ImmutableArray.Create(boundLockTemp.LocalSymbol),
                           ImmutableArray.Create(
                               InstrumentLockTargetCapture(node, boundLockTempInit),
                               enterCall,
                               new BoundTryStatement(
                                   lockSyntax,
                                   BoundBlock.SynthesizedNoLocals(lockSyntax, rewrittenBody),
                                   ImmutableArray <BoundCatchBlock> .Empty,
                                   BoundBlock.SynthesizedNoLocals(lockSyntax, exitCall)))));
            }
        }
예제 #13
0
        /// <summary>
        /// If we have a WinRT type event, we need to encapsulate the adder call
        /// (which returns an EventRegistrationToken) with a call to
        /// WindowsRuntimeMarshal.AddEventHandler or RemoveEventHandler, but these
        /// require us to create a new Func representing the adder and another
        /// Action representing the Remover.
        ///
        /// The rewritten call looks something like:
        ///
        /// WindowsRuntimeMarshal.AddEventHandler&lt;EventHandler&gt;
        ///     (new Func&lt;EventHandler, EventRegistrationToken&gt;(@object.add),
        ///      new Action&lt;EventRegistrationToken&gt;(@object.remove), handler);
        ///
        /// Where @object is a compiler-generated local temp if needed.
        /// </summary>
        /// <remarks>
        /// TODO: use or delete isDynamic.
        /// </remarks>
        private BoundExpression RewriteWindowsRuntimeEventAssignmentOperator(SyntaxNode syntax, EventSymbol eventSymbol, EventAssignmentKind kind, bool isDynamic, BoundExpression rewrittenReceiverOpt, BoundExpression rewrittenArgument)
        {
            BoundAssignmentOperator tempAssignment = null;
            BoundLocal boundTemp = null;

            if (!eventSymbol.IsStatic && CanChangeValueBetweenReads(rewrittenReceiverOpt))
            {
                boundTemp = _factory.StoreToTemp(rewrittenReceiverOpt, out tempAssignment);
            }

            NamedTypeSymbol tokenType   = _factory.WellKnownType(WellKnownType.core_runtime_WindowsRuntime_EventRegistrationToken);
            NamedTypeSymbol marshalType = _factory.WellKnownType(WellKnownType.core_runtime_WindowsRuntime_WindowsRuntimeMarshal);

            NamedTypeSymbol actionType = _factory.WellKnownType(WellKnownType.core_Action_T).Construct(tokenType);

            TypeSymbol eventType = eventSymbol.Type.TypeSymbol;

            BoundExpression delegateCreationArgument = boundTemp ?? rewrittenReceiverOpt ?? _factory.Type(eventType);

            BoundDelegateCreationExpression removeDelegate = new BoundDelegateCreationExpression(
                syntax: syntax,
                argument: delegateCreationArgument,
                methodOpt: eventSymbol.RemoveMethod,
                isExtensionMethod: false,
                type: actionType);

            BoundExpression clearCall = null;

            if (kind == EventAssignmentKind.Assignment)
            {
                MethodSymbol clearMethod;
                if (TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_WindowsRuntimeMarshal__RemoveAllEventHandlers, out clearMethod))
                {
                    clearCall = MakeCall(
                        syntax: syntax,
                        rewrittenReceiver: null,
                        method: clearMethod,
                        rewrittenArguments: ImmutableArray.Create <BoundExpression>(removeDelegate),
                        type: clearMethod.ReturnType.TypeSymbol);
                }
                else
                {
                    clearCall = new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray.Create <BoundExpression>(removeDelegate), ErrorTypeSymbol.UnknownResultType);
                }
            }

            ImmutableArray <BoundExpression> marshalArguments;
            WellKnownMember helper;

            if (kind == EventAssignmentKind.Subtraction)
            {
                helper           = WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_WindowsRuntimeMarshal__RemoveEventHandler_T;
                marshalArguments = ImmutableArray.Create <BoundExpression>(removeDelegate, rewrittenArgument);
            }
            else
            {
                NamedTypeSymbol func2Type = _factory.WellKnownType(WellKnownType.core_Func_T2).Construct(eventType, tokenType);

                BoundDelegateCreationExpression addDelegate = new BoundDelegateCreationExpression(
                    syntax: syntax,
                    argument: delegateCreationArgument,
                    methodOpt: eventSymbol.AddMethod,
                    isExtensionMethod: false,
                    type: func2Type);

                helper           = WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_WindowsRuntimeMarshal__AddEventHandler_T;
                marshalArguments = ImmutableArray.Create <BoundExpression>(addDelegate, removeDelegate, rewrittenArgument);
            }

            BoundExpression marshalCall;

            MethodSymbol marshalMethod;

            if (TryGetWellKnownTypeMember(syntax, helper, out marshalMethod))
            {
                marshalMethod = marshalMethod.Construct(eventType);

                marshalCall = MakeCall(
                    syntax: syntax,
                    rewrittenReceiver: null,
                    method: marshalMethod,
                    rewrittenArguments: marshalArguments,
                    type: marshalMethod.ReturnType.TypeSymbol);
            }
            else
            {
                marshalCall = new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, marshalArguments, ErrorTypeSymbol.UnknownResultType);
            }

            // In this case, we don't need a sequence.
            if (boundTemp == null && clearCall == null)
            {
                return(marshalCall);
            }

            ImmutableArray <LocalSymbol> tempSymbols = boundTemp == null
                ? ImmutableArray <LocalSymbol> .Empty
                : ImmutableArray.Create <LocalSymbol>(boundTemp.LocalSymbol);

            ArrayBuilder <BoundExpression> sideEffects = ArrayBuilder <BoundExpression> .GetInstance(2); //max size

            if (clearCall != null)
            {
                sideEffects.Add(clearCall);
            }
            if (tempAssignment != null)
            {
                sideEffects.Add(tempAssignment);
            }
            Debug.Assert(sideEffects.Any(), "Otherwise, we shouldn't be building a sequence");

            return(new BoundSequence(syntax, tempSymbols, sideEffects.ToImmutableAndFree(), marshalCall, marshalCall.Type));
        }
예제 #14
0
        private BoundExpression MakeEventAccess(
            SyntaxNode syntax,
            BoundExpression rewrittenReceiver,
            EventSymbol eventSymbol,
            ConstantValue constantValueOpt,
            LookupResultKind resultKind,
            TypeSymbol type)
        {
            Debug.Assert(eventSymbol.HasAssociatedField);

            FieldSymbol fieldSymbol = eventSymbol.AssociatedField;

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

            if (!eventSymbol.IsWindowsRuntimeEvent)
            {
                return(MakeFieldAccess(syntax, rewrittenReceiver, fieldSymbol, constantValueOpt, resultKind, type));
            }

            NamedTypeSymbol fieldType = (NamedTypeSymbol)fieldSymbol.Type.TypeSymbol;

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

            // _tokenTable
            BoundFieldAccess fieldAccess = new BoundFieldAccess(
                syntax,
                fieldSymbol.IsStatic ? null : rewrittenReceiver,
                fieldSymbol,
                constantValueOpt: null)
            {
                WasCompilerGenerated = true
            };

            BoundExpression getOrCreateCall;

            MethodSymbol getOrCreateMethod;

            if (TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__GetOrCreateEventRegistrationTokenTable, out getOrCreateMethod))
            {
                getOrCreateMethod = getOrCreateMethod.AsMember(fieldType);

                // EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable)
                getOrCreateCall = BoundCall.Synthesized(
                    syntax,
                    receiverOpt: null,
                    method: getOrCreateMethod,
                    arg0: fieldAccess);
            }
            else
            {
                getOrCreateCall = new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray.Create <BoundExpression>(fieldAccess), ErrorTypeSymbol.UnknownResultType);
            }

            PropertySymbol invocationListProperty;

            if (TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__InvocationList, out invocationListProperty))
            {
                MethodSymbol invocationListAccessor = invocationListProperty.GetMethod;

                if ((object)invocationListAccessor == null)
                {
                    string accessorName = SourcePropertyAccessorSymbol.GetAccessorName(invocationListProperty.Name,
                                                                                       getNotSet: true,
                                                                                       isWinMdOutput: invocationListProperty.IsCompilationOutputWinMdObj());
                    _diagnostics.Add(new CSDiagnosticInfo(ErrorCode.ERR_MissingPredefinedMember, invocationListProperty.ContainingType, accessorName), syntax.Location);
                }
                else
                {
                    invocationListAccessor = invocationListAccessor.AsMember(fieldType);
                    return(_factory.Call(getOrCreateCall, invocationListAccessor));
                }
            }

            return(new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray.Create(getOrCreateCall), ErrorTypeSymbol.UnknownResultType));
        }
예제 #15
0
        public override BoundNode VisitStackAllocArrayCreation(BoundStackAllocArrayCreation stackAllocNode)
        {
            var rewrittenCount = VisitExpression(stackAllocNode.Count);
            var type           = stackAllocNode.Type;

            if (rewrittenCount.ConstantValue?.Int32Value == 0)
            {
                // either default(span) or nullptr
                return(_factory.Default(type));
            }

            var elementType = stackAllocNode.ElementType;

            var initializerOpt = stackAllocNode.InitializerOpt;

            if (initializerOpt != null)
            {
                initializerOpt = initializerOpt.Update(VisitList(initializerOpt.Initializers));
            }

            if (type.IsPointerType())
            {
                var stackSize = RewriteStackAllocCountToSize(rewrittenCount, elementType);
                return(new BoundConvertedStackAllocExpression(stackAllocNode.Syntax, elementType, stackSize, initializerOpt, stackAllocNode.Type));
            }
            else if (TypeSymbol.Equals(type.OriginalDefinition, _compilation.GetWellKnownType(WellKnownType.core_Span_T), TypeCompareKind.ConsiderEverything2))
            {
                var spanType    = (NamedTypeSymbol)stackAllocNode.Type;
                var sideEffects = ArrayBuilder <BoundExpression> .GetInstance();

                var locals = ArrayBuilder <LocalSymbol> .GetInstance();

                var countTemp = CaptureExpressionInTempIfNeeded(rewrittenCount, sideEffects, locals);
                var stackSize = RewriteStackAllocCountToSize(countTemp, elementType);
                stackAllocNode = new BoundConvertedStackAllocExpression(stackAllocNode.Syntax, elementType, stackSize, initializerOpt, spanType);

                BoundExpression constructorCall;
                if (TryGetWellKnownTypeMember(stackAllocNode.Syntax, WellKnownMember.System_Span_T__ctor, out MethodSymbol spanConstructor))
                {
                    constructorCall = _factory.New((MethodSymbol)spanConstructor.SymbolAsMember(spanType), stackAllocNode, countTemp);
                }
                else
                {
                    constructorCall = new BoundBadExpression(
                        syntax: stackAllocNode.Syntax,
                        resultKind: LookupResultKind.NotInvocable,
                        symbols: ImmutableArray <Symbol> .Empty,
                        childBoundNodes: ImmutableArray <BoundExpression> .Empty,
                        type: ErrorTypeSymbol.UnknownResultType);
                }

                return(new BoundSequence(
                           syntax: stackAllocNode.Syntax,
                           locals: locals.ToImmutableAndFree(),
                           sideEffects: sideEffects.ToImmutableAndFree(),
                           value: constructorCall,
                           type: spanType));
            }
            else
            {
                throw ExceptionUtilities.UnexpectedValue(type);
            }
        }