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>))); }
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); }
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)); }
public override BoundNode VisitBadExpression(BoundBadExpression node) { // Cannot recurse into BadExpression children return(node); }
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)); }
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); }
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))))); } }
/// <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<EventHandler> /// (new Func<EventHandler, EventRegistrationToken>(@object.add), /// new Action<EventRegistrationToken>(@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)); }
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)); }
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); } }