private BoundExpression MakeFieldAccess( CSharpSyntaxNode syntax, BoundExpression rewrittenReceiver, FieldSymbol fieldSymbol, ConstantValue constantValueOpt, LookupResultKind resultKind, TypeSymbol type, BoundFieldAccess oldNodeOpt = null) { if (fieldSymbol.IsTupleField) { return MakeTupleFieldAccess(syntax, fieldSymbol, rewrittenReceiver, constantValueOpt, resultKind); } BoundExpression result = oldNodeOpt != null ? oldNodeOpt.Update(rewrittenReceiver, fieldSymbol, constantValueOpt, resultKind, type) : new BoundFieldAccess(syntax, rewrittenReceiver, fieldSymbol, constantValueOpt, resultKind, type); if (fieldSymbol.IsFixed) { // a reference to a fixed buffer is translated into its address result = new BoundConversion(syntax, new BoundAddressOfOperator(syntax, result, syntax != null && SyntaxFacts.IsFixedStatementExpression(syntax), type, false), new Conversion(ConversionKind.PointerToPointer), false, false, default(ConstantValue), type, false); } return result; }
/// <remarks> /// Based on OutputContext::IsNonAgileField. /// </remarks> internal static bool IsNonAgileFieldAccess(BoundFieldAccess fieldAccess, CSharpCompilation compilation) { // Warn if taking the address of a non-static field with a receiver other than this (possibly cast) // and a type that descends from System.MarshalByRefObject. if (IsInstanceFieldAccessWithNonThisReceiver(fieldAccess)) { // NOTE: We're only trying to produce a warning, so there's no point in producing an // error if the well-known type we need for the check is missing. NamedTypeSymbol marshalByRefType = compilation.GetWellKnownType(WellKnownType.System_MarshalByRefObject); TypeSymbol baseType = fieldAccess.FieldSymbol.ContainingType; while ((object)baseType != null) { if (baseType == marshalByRefType) { return true; } // NOTE: We're only trying to produce a warning, so there's no point in producing a // use site diagnostic if we can't walk up the base type hierarchy. baseType = baseType.BaseTypeNoUseSiteDiagnostics; } } return false; }
/// <remarks> /// This is for when we are dotting into a field. /// Distinguish from <see cref="CheckFieldAddress"/>. /// /// NOTE: dev11 also calls this on string initializers in fixed statements, /// but never accomplishes anything since string is a reference type. This /// is probably a bug, but fixing it would be a breaking change. /// </remarks> private void CheckFieldAsReceiver(BoundFieldAccess fieldAccess) { // From ExpressionBinder.cpp: // Taking the address of a field is suspect if the type is marshalbyref. // REVIEW ShonK: Is this really the best way to handle this? It'd be so much more // bullet proof for ilgen to error when it spits out the ldflda.... FieldSymbol fieldSymbol = fieldAccess.FieldSymbol; if (IsNonAgileFieldAccess(fieldAccess, _compilation) && !fieldSymbol.Type.IsReferenceType) { Error(ErrorCode.WRN_CallOnNonAgileField, fieldAccess, fieldSymbol); } }
private void CheckFieldAddress(BoundFieldAccess fieldAccess, Symbol consumerOpt) { FieldSymbol fieldSymbol = fieldAccess.FieldSymbol; // We can safely suppress this warning when calling an Interlocked API if (fieldSymbol.IsVolatile && ((object)consumerOpt == null || !IsInterlockedAPI(consumerOpt))) { Error(ErrorCode.WRN_VolatileByRef, fieldAccess, fieldSymbol); } if (IsNonAgileFieldAccess(fieldAccess, _compilation)) { Error(ErrorCode.WRN_ByRefNonAgileField, fieldAccess, fieldSymbol); } }
/// <remarks> /// This is for when we are taking the address of a field. /// Distinguish from <see cref="CheckFieldAsReceiver"/>. /// </remarks> private void CheckFieldAddress(BoundFieldAccess fieldAccess, Symbol consumerOpt) { FieldSymbol fieldSymbol = fieldAccess.FieldSymbol; // We can safely suppress this warning when calling an Interlocked API if (fieldSymbol.IsVolatile && ((object)consumerOpt == null || !IsInterlockedAPI(consumerOpt))) { Error(ErrorCode.WRN_VolatileByRef, fieldAccess, fieldSymbol); } if (IsNonAgileFieldAccess(fieldAccess, _compilation)) { Error(ErrorCode.WRN_ByRefNonAgileField, fieldAccess, fieldSymbol); } }
private void CheckFieldAsReceiver(BoundFieldAccess fieldAccess) { // From ExpressionBinder.cpp: // Taking the address of a field is suspect if the type is marshalbyref. // REVIEW ShonK: Is this really the best way to handle this? It'd be so much more // bullet proof for ilgen to error when it spits out the ldflda.... FieldSymbol fieldSymbol = fieldAccess.FieldSymbol; if ( IsNonAgileFieldAccess(fieldAccess, _compilation) && !fieldSymbol.Type.IsReferenceType ) { Error(ErrorCode.WRN_CallOnNonAgileField, fieldAccess, fieldSymbol); } }
private BoundExpression GetDefaultParameterSpecial(CSharpSyntaxNode syntax, ParameterSymbol parameter) { // We have a call to a method M([Optional] object x) which omits the argument. The value we generate // for the argument depends on the presence or absence of other attributes. The rules are: // // * If the parameter is marked as [MarshalAs(Interface)], [MarshalAs(IUnknown)] or [MarshalAs(IDispatch)] // then the argument is null. // * Otherwise, if the parameter is marked as [IUnknownConstant] then the argument is // new UnknownWrapper(null) // * Otherwise, if the parameter is marked as [IDispatchConstant] then the argument is // new DispatchWrapper(null) // * Otherwise, the argument is Type.Missing. BoundExpression defaultValue; if (parameter.IsMarshalAsObject) { // default(object) defaultValue = new BoundDefaultOperator(syntax, parameter.Type); } else if (parameter.IsIUnknownConstant) { // new UnknownWrapper(default(object)) var methodSymbol = (MethodSymbol)this.compilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_InteropServices_UnknownWrapper__ctor); var argument = new BoundDefaultOperator(syntax, parameter.Type); defaultValue = new BoundObjectCreationExpression(syntax, methodSymbol, argument); } else if (parameter.IsIDispatchConstant) { // new DispatchWrapper(default(object)) var methodSymbol = (MethodSymbol)this.compilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_InteropServices_DispatchWrapper__ctor); var argument = new BoundDefaultOperator(syntax, parameter.Type); defaultValue = new BoundObjectCreationExpression(syntax, methodSymbol, argument); } else { // Type.Missing var fieldSymbol = (FieldSymbol)compilation.GetWellKnownTypeMember(WellKnownMember.System_Type__Missing); defaultValue = new BoundFieldAccess(syntax, null, fieldSymbol, ConstantValue.NotAvailable); } defaultValue = MakeConversion(defaultValue, parameter.Type, @checked: false); return(defaultValue); }
protected override BoundStatement GenerateSetResultCall() { // ... _exprReturnLabel: ... // ... this.state = FinishedState; ... // if (this.combinedTokens != null) { this.combinedTokens.Dispose(); this.combinedTokens = null; } // for enumerables only // this.builder.Complete(); // this.promiseOfValueOrEnd.SetResult(false); // return; // _exprReturnLabelTrue: // this.promiseOfValueOrEnd.SetResult(true); // ... _exitLabel: ... // ... return; ... var builder = ArrayBuilder <BoundStatement> .GetInstance(); // if (this.combinedTokens != null) { this.combinedTokens.Dispose(); this.combinedTokens = null; } // for enumerables only AddDisposeCombinedTokensIfNeeded(builder); builder.AddRange( GenerateCompleteOnBuilder(), // this.promiseOfValueOrEnd.SetResult(false); generateSetResultOnPromise(false), F.Return(), F.Label(_exprReturnLabelTrue), // this.promiseOfValueOrEnd.SetResult(true); generateSetResultOnPromise(true) ); return(F.Block(builder.ToImmutableAndFree())); BoundExpressionStatement generateSetResultOnPromise(bool result) { // Produce: // this.promiseOfValueOrEnd.SetResult(result); BoundFieldAccess promiseField = F.InstanceField( _asyncIteratorInfo.PromiseOfValueOrEndField ); return(F.ExpressionStatement( F.Call(promiseField, _asyncIteratorInfo.SetResultMethod, F.Literal(result)) )); } }
/// <summary> /// Converts access to a tuple instance into access into the underlying ValueTuple(s). /// /// For instance, tuple.Item8 /// produces fieldAccess(field=Item1, receiver=fieldAccess(field=Rest, receiver=ValueTuple for tuple)) /// </summary> private BoundExpression MakeTupleFieldAccess( CSharpSyntaxNode syntax, FieldSymbol tupleField, BoundExpression rewrittenReceiver, ConstantValue constantValueOpt, LookupResultKind resultKind, TypeSymbol type) { var tupleType = tupleField.ContainingType; NamedTypeSymbol currentLinkType = tupleType.TupleUnderlyingType; FieldSymbol underlyingField = tupleField.TupleUnderlyingField; if ((object)underlyingField == null) { // Use-site error must have been reported elsewhere. return(new BoundFieldAccess(syntax, rewrittenReceiver, tupleField, constantValueOpt, resultKind, type, hasErrors: true)); } if (underlyingField.ContainingType != currentLinkType) { WellKnownMember wellKnownTupleRest = TupleTypeSymbol.GetTupleTypeMember(TupleTypeSymbol.RestPosition, TupleTypeSymbol.RestPosition); var tupleRestField = (FieldSymbol)TupleTypeSymbol.GetWellKnownMemberInType(currentLinkType.OriginalDefinition, wellKnownTupleRest, _diagnostics, syntax); if ((object)tupleRestField == null) { // error tolerance for cases when Rest is missing return(new BoundFieldAccess(syntax, rewrittenReceiver, tupleField, constantValueOpt, resultKind, type, hasErrors: true)); } // make nested field accesses to Rest do { FieldSymbol nestedFieldSymbol = tupleRestField.AsMember(currentLinkType); currentLinkType = currentLinkType.TypeArgumentsNoUseSiteDiagnostics[TupleTypeSymbol.RestPosition - 1].TupleUnderlyingType; rewrittenReceiver = new BoundFieldAccess(syntax, rewrittenReceiver, nestedFieldSymbol, ConstantValue.NotAvailable, LookupResultKind.Viable, currentLinkType); }while (underlyingField.ContainingType != currentLinkType); } // make a field access for the most local access return(new BoundFieldAccess(syntax, rewrittenReceiver, underlyingField, constantValueOpt, resultKind, type)); }
public override BoundNode VisitFieldAccess(BoundFieldAccess node) { BoundExpression receiverOpt = (BoundExpression)this.Visit(node.ReceiverOpt); TypeSymbol type = this.VisitType(node.Type); if (receiverOpt == null || receiverOpt.Kind != BoundKind.SpillSequence) { return(node.Update(receiverOpt, node.FieldSymbol, node.ConstantValueOpt, node.ResultKind, type)); } var spill = (BoundSpillSequence)receiverOpt; return(RewriteSpillSequence(spill, node.Update( spill.Value, node.FieldSymbol, node.ConstantValueOpt, node.ResultKind, type))); }
private static BoundExpressionStatement vulcanruntimeStateAssign(SyntaxNode syntax, FieldSymbol field, bool value) { var bfa = new BoundFieldAccess(syntax, null, field, ConstantValue.NotAvailable) { WasCompilerGenerated = true }; var lit = new BoundLiteral(syntax, ConstantValue.Create(value), field.Type) { WasCompilerGenerated = true }; var ass = new BoundAssignmentOperator(syntax, bfa, lit, isRef: false, lit.Type) { WasCompilerGenerated = true }; var stmt = new BoundExpressionStatement(syntax, ass) { WasCompilerGenerated = true }; return(stmt); }
private static BoundExpressionStatement ClearGlobal(CSharpCompilation compilation, SyntaxNode node, FieldSymbol field) { var lhs = new BoundFieldAccess(node, null, field, null) { WasCompilerGenerated = true }; var rhs = new BoundDefaultExpression(node, field.Type) { WasCompilerGenerated = true }; var op = new BoundAssignmentOperator(node, lhs, rhs, field.Type) { WasCompilerGenerated = true }; var stmt = new BoundExpressionStatement(node, op) { WasCompilerGenerated = true }; return(stmt); }
private static bool IsInstanceFieldAccessWithNonThisReceiver(BoundFieldAccess fieldAccess) { BoundExpression receiver = fieldAccess.ReceiverOpt; if (receiver == null || fieldAccess.FieldSymbol.IsStatic) { return(false); } while (receiver.Kind == BoundKind.Conversion) { BoundConversion conversion = (BoundConversion)receiver; if (conversion.ExplicitCastInCode) { break; } receiver = conversion.Operand; } return(receiver.Kind != BoundKind.ThisReference && receiver.Kind != BoundKind.BaseReference); }
private void GetPartsForStartingMachine(out BoundExpressionStatement callReset, out LocalSymbol instSymbol, out BoundStatement instAssignment, out BoundExpressionStatement startCall, out MethodSymbol promise_get_Version) { // Produce the following parts: // - _promiseOfValueOrEnd.Reset(); // - var inst = this; // - _builder.Start(ref inst); // - _valueOrEndPromise.Version // _promiseOfValueOrEnd.Reset(); BoundFieldAccess promiseField = F.InstanceField(_promiseOfValueOrEndField); var resetMethod = (MethodSymbol)F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__Reset, isOptional: true) .SymbolAsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type); callReset = F.ExpressionStatement(F.Call(promiseField, resetMethod)); // _builder.Start(ref inst); Debug.Assert(!_asyncMethodBuilderMemberCollection.CheckGenericMethodConstraints); MethodSymbol startMethod = _asyncMethodBuilderMemberCollection.Start.Construct(this.stateMachineType); instSymbol = F.SynthesizedLocal(this.stateMachineType); // var inst = this; var instLocal = F.Local(instSymbol); instAssignment = F.Assignment(instLocal, F.This()); // _builder.Start(ref inst); startCall = F.ExpressionStatement( F.Call( F.InstanceField(_builderField), startMethod, ImmutableArray.Create <BoundExpression>(instLocal))); // _valueOrEndPromise.Version promise_get_Version = F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__get_Version) .AsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type); }
private static BoundExpression MakeFieldAccess( CSharpSyntaxNode syntax, BoundExpression rewrittenReceiver, FieldSymbol fieldSymbol, ConstantValue constantValueOpt, LookupResultKind resultKind, TypeSymbol type, BoundFieldAccess oldNodeOpt = null) { BoundExpression result = oldNodeOpt != null? oldNodeOpt.Update(rewrittenReceiver, fieldSymbol, constantValueOpt, resultKind, type) : new BoundFieldAccess(syntax, rewrittenReceiver, fieldSymbol, constantValueOpt, resultKind, type); if (fieldSymbol.IsFixed) { // a reference to a fixed buffer is translated into its address result = new BoundConversion(syntax, new BoundAddressOfOperator(syntax, result, syntax != null && SyntaxFacts.IsFixedStatementExpression(syntax), type, false), new Conversion(ConversionKind.PointerToPointer), false, false, default(ConstantValue), type, false); } return(result); }
private BoundFieldAccess TransformReferenceTypeFieldAccess(BoundFieldAccess fieldAccess, BoundExpression receiver, ArrayBuilder <BoundExpression> stores, ArrayBuilder <LocalSymbol> temps) { Debug.Assert(receiver.Type.IsReferenceType); Debug.Assert(receiver.Kind != BoundKind.TypeExpression); BoundExpression rewrittenReceiver = VisitExpression(receiver); if (rewrittenReceiver.Type.IsTypeParameter()) { var memberContainingType = fieldAccess.FieldSymbol.ContainingType; // From the verifier prospective type parameters do not contain fields or methods. // the instance must be "boxed" to access the field // It makes sense to box receiver before storing into a temp - no need to box twice. rewrittenReceiver = BoxReceiver(rewrittenReceiver, memberContainingType); } BoundAssignmentOperator assignmentToTemp; var receiverTemp = _factory.StoreToTemp(rewrittenReceiver, out assignmentToTemp); stores.Add(assignmentToTemp); temps.Add(receiverTemp.LocalSymbol); return(new BoundFieldAccess(fieldAccess.Syntax, receiverTemp, fieldAccess.FieldSymbol, null)); }
/// <summary> /// Construct a body for an auto-property accessor (updating or returning the backing field). /// </summary> internal static BoundBlock ConstructAutoPropertyAccessorBody(SourceMemberMethodSymbol accessor) { Debug.Assert(accessor.MethodKind == MethodKind.PropertyGet || accessor.MethodKind == MethodKind.PropertySet); var property = (SourcePropertySymbol)accessor.AssociatedSymbol; CSharpSyntaxNode syntax = property.CSharpSyntaxNode; BoundExpression thisReference = null; if (!accessor.IsStatic) { var thisSymbol = accessor.ThisParameter; thisReference = new BoundThisReference(syntax, thisSymbol.Type) { WasCompilerGenerated = true }; } var field = property.BackingField; var fieldAccess = new BoundFieldAccess(syntax, thisReference, field, ConstantValue.NotAvailable) { WasCompilerGenerated = true }; BoundStatement statement; if (accessor.MethodKind == MethodKind.PropertyGet) { statement = new BoundReturnStatement(accessor.SyntaxNode, RefKind.None, fieldAccess); } else { Debug.Assert(accessor.MethodKind == MethodKind.PropertySet); var parameter = accessor.Parameters[0]; statement = new BoundExpressionStatement( accessor.SyntaxNode, new BoundAssignmentOperator( syntax, fieldAccess, new BoundParameter(syntax, parameter) { WasCompilerGenerated = true }, property.Type) { WasCompilerGenerated = true }); } return BoundBlock.SynthesizedNoLocals(syntax, statement); }
internal static bool IsNonAgileFieldAccess( BoundFieldAccess fieldAccess, CSharpCompilation compilation ) { // Warn if taking the address of a non-static field with a receiver other than this (possibly cast) // and a type that descends from System.MarshalByRefObject. if (IsInstanceFieldAccessWithNonThisReceiver(fieldAccess)) { // NOTE: We're only trying to produce a warning, so there's no point in producing an // error if the well-known type we need for the check is missing. NamedTypeSymbol marshalByRefType = compilation.GetWellKnownType( WellKnownType.System_MarshalByRefObject ); TypeSymbol baseType = fieldAccess.FieldSymbol.ContainingType; while ((object)baseType != null) { if ( TypeSymbol.Equals( baseType, marshalByRefType, TypeCompareKind.ConsiderEverything ) ) { return(true); } // NOTE: We're only trying to produce a warning, so there's no point in producing a // use site diagnostic if we can't walk up the base type hierarchy. baseType = baseType.BaseTypeNoUseSiteDiagnostics; } } return(false); }
private BoundExpression GetDefaultParameterSpecial(SyntaxNode syntax, ParameterSymbol parameter) { // We have a call to a method M([Optional] object x) which omits the argument. The value we generate // for the argument depends on the presence or absence of other attributes. The rules are: // // * If the parameter is marked as [MarshalAs(Interface)], [MarshalAs(IUnknown)] or [MarshalAs(IDispatch)] // then the argument is null. // * Otherwise, if the parameter is marked as [IUnknownConstant] then the argument is // new UnknownWrapper(null) // * Otherwise, if the parameter is marked as [IDispatchConstant] then the argument is // new DispatchWrapper(null) // * Otherwise, the argument is Type.Missing. BoundExpression defaultValue; if (parameter.IsMarshalAsObject) { // default(object) defaultValue = new BoundDefaultOperator(syntax, parameter.Type); } else if (parameter.IsIUnknownConstant) { // new UnknownWrapper(default(object)) var methodSymbol = (MethodSymbol)_compilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_InteropServices_UnknownWrapper__ctor); var argument = new BoundDefaultOperator(syntax, parameter.Type); defaultValue = new BoundObjectCreationExpression(syntax, methodSymbol, argument); } else if (parameter.IsIDispatchConstant) { // new DispatchWrapper(default(object)) var methodSymbol = (MethodSymbol)_compilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_InteropServices_DispatchWrapper__ctor); var argument = new BoundDefaultOperator(syntax, parameter.Type); defaultValue = new BoundObjectCreationExpression(syntax, methodSymbol, argument); } else { // Type.Missing var fieldSymbol = (FieldSymbol)_compilation.GetWellKnownTypeMember(WellKnownMember.System_Type__Missing); defaultValue = new BoundFieldAccess(syntax, null, fieldSymbol, ConstantValue.NotAvailable); } defaultValue = MakeConversionNode(defaultValue, parameter.Type, @checked: false); return defaultValue; }
private BoundPattern BindDeclarationPattern( DeclarationPatternSyntax node, TypeSymbol operandType, bool hasErrors, DiagnosticBag diagnostics) { Debug.Assert(operandType != (object)null); var typeSyntax = node.Type; bool isVar; AliasSymbol aliasOpt; TypeSymbol declType = BindTypeOrVarKeyword(typeSyntax, diagnostics, out isVar, out aliasOpt); if (isVar) { declType = operandType; } if (declType == (object)null) { Debug.Assert(hasErrors); declType = this.CreateErrorType("var"); } var boundDeclType = new BoundTypeExpression(typeSyntax, aliasOpt, inferredType: isVar, type: declType); if (IsOperatorErrors(node, operandType, boundDeclType, diagnostics)) { hasErrors = true; } else { hasErrors |= CheckValidPatternType(typeSyntax, operandType, declType, isVar: isVar, patternTypeWasInSource: true, diagnostics: diagnostics); } switch (node.Designation.Kind()) { case SyntaxKind.SingleVariableDesignation: break; case SyntaxKind.DiscardDesignation: return(new BoundDeclarationPattern(node, null, boundDeclType, isVar, hasErrors)); default: throw ExceptionUtilities.UnexpectedValue(node.Designation.Kind()); } var designation = (SingleVariableDesignationSyntax)node.Designation; var identifier = designation.Identifier; SourceLocalSymbol localSymbol = this.LookupLocal(identifier); if (localSymbol != (object)null) { if ((InConstructorInitializer || InFieldInitializer) && ContainingMemberOrLambda.ContainingSymbol.Kind == SymbolKind.NamedType) { CheckFeatureAvailability(node, MessageID.IDS_FeatureExpressionVariablesInQueriesAndInitializers, diagnostics); } localSymbol.SetType(declType); // Check for variable declaration errors. hasErrors |= localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics); if (!hasErrors) { hasErrors = CheckRestrictedTypeInAsync(this.ContainingMemberOrLambda, declType, diagnostics, typeSyntax); } return(new BoundDeclarationPattern(node, localSymbol, boundDeclType, isVar, hasErrors)); } else { // We should have the right binder in the chain for a script or interactive, so we use the field for the pattern. Debug.Assert(node.SyntaxTree.Options.Kind != SourceCodeKind.Regular); GlobalExpressionVariable expressionVariableField = LookupDeclaredField(designation); DiagnosticBag tempDiagnostics = DiagnosticBag.GetInstance(); expressionVariableField.SetType(declType, tempDiagnostics); tempDiagnostics.Free(); BoundExpression receiver = SynthesizeReceiver(node, expressionVariableField, diagnostics); var variableAccess = new BoundFieldAccess(node, receiver, expressionVariableField, null, hasErrors); return(new BoundDeclarationPattern(node, expressionVariableField, variableAccess, boundDeclType, isVar, hasErrors)); } }
private BoundPattern BindDeclarationPattern( DeclarationPatternSyntax node, BoundExpression operand, TypeSymbol operandType, bool hasErrors, DiagnosticBag diagnostics) { Debug.Assert(operand != null && operandType != (object)null); var typeSyntax = node.Type; var identifier = node.Identifier; bool isVar; AliasSymbol aliasOpt; TypeSymbol declType = BindType(typeSyntax, diagnostics, out isVar, out aliasOpt); if (isVar) { declType = operandType; } if (declType == (object)null) { Debug.Assert(hasErrors); declType = this.CreateErrorType("var"); } var boundDeclType = new BoundTypeExpression(typeSyntax, aliasOpt, inferredType: isVar, type: declType); if (IsOperatorErrors(node, operandType, boundDeclType, diagnostics)) { hasErrors = true; } else { hasErrors |= CheckValidPatternType(typeSyntax, operand, operandType, declType, isVar: isVar, patternTypeWasInSource: true, diagnostics: diagnostics); } SourceLocalSymbol localSymbol = this.LookupLocal(identifier); if (localSymbol != (object)null) { if (InConstructorInitializer || InFieldInitializer) { Error(diagnostics, ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, node); } localSymbol.SetType(declType); // Check for variable declaration errors. hasErrors |= localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics); if (!hasErrors) { hasErrors = CheckRestrictedTypeInAsync(this.ContainingMemberOrLambda, declType, diagnostics, typeSyntax); } return(new BoundDeclarationPattern(node, localSymbol, boundDeclType, isVar, hasErrors)); } else { // We should have the right binder in the chain for a script or interactive, so we use the field for the pattern. Debug.Assert(node.SyntaxTree.Options.Kind != SourceCodeKind.Regular); GlobalExpressionVariable expressionVariableField = LookupDeclaredField(node); DiagnosticBag tempDiagnostics = DiagnosticBag.GetInstance(); expressionVariableField.SetType(declType, tempDiagnostics); tempDiagnostics.Free(); BoundExpression receiver = SynthesizeReceiver(node, expressionVariableField, diagnostics); var variableAccess = new BoundFieldAccess(node, receiver, expressionVariableField, null, hasErrors); return(new BoundDeclarationPattern(node, expressionVariableField, variableAccess, boundDeclType, isVar, hasErrors)); } }
/// <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<DelegateType>(ref _event, tmp2, tmp1); /// } while ((object)tmp0 != (object)tmp1); /// </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); MethodSymbol updateMethod = (MethodSymbol)compilation.GetSpecialTypeMember(isAddMethod ? SpecialMember.System_Delegate__Combine : SpecialMember.System_Delegate__Remove); MethodSymbol compareExchangeMethod = GetConstructedCompareExchangeMethod(delegateType, compilation, accessor.Locations[0], diagnostics); if ((object)compareExchangeMethod == null) { return new BoundBlock(syntax, locals: ImmutableArray<LocalSymbol>.Empty, statements: ImmutableArray.Create<BoundStatement>( new BoundReturnStatement(syntax, expressionOpt: null) { WasCompilerGenerated = true })) { WasCompilerGenerated = true }; } 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); } 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 }; // 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) BoundExpression 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 }; BoundStatement @return = new BoundReturnStatement(syntax, expressionOpt: null) { WasCompilerGenerated = true }; return new BoundBlock(syntax, locals: tmps.AsImmutable(), statements: ImmutableArray.Create<BoundStatement>( tmp0Init, loopStart, tmp1Update, tmp2Update, tmp0Update, loopEnd, @return)) { WasCompilerGenerated = true }; }
public override BoundNode VisitFieldAccess(BoundFieldAccess node) { _syntaxWithReceiver = node.Syntax; return(base.VisitFieldAccess(node)); }
public override BoundNode VisitFieldAccess(BoundFieldAccess node) { BoundSpillSequence2 ss = null; var receiver = VisitExpression(ref ss, node.ReceiverOpt); return UpdateExpression(ss, node.Update(receiver, node.FieldSymbol, node.ConstantValueOpt, node.ResultKind, node.Type)); }
public override BoundNode VisitFieldAccess(BoundFieldAccess node) { BoundExpression receiverOpt = (BoundExpression)this.Visit(node.ReceiverOpt); TypeSymbol type = this.VisitType(node.Type); if (receiverOpt == null || receiverOpt.Kind != BoundKind.SpillSequence) { return node.Update(receiverOpt, node.FieldSymbol, node.ConstantValueOpt, node.ResultKind, type); } var spill = (BoundSpillSequence)receiverOpt; return RewriteSpillSequence(spill, node.Update( spill.Value, node.FieldSymbol, node.ConstantValueOpt, node.ResultKind, type)); }
public override BoundNode VisitFieldAccess(BoundFieldAccess node) { BoundExpression rewrittenReceiver = VisitExpression(node.ReceiverOpt); return MakeFieldAccess(node.Syntax, rewrittenReceiver, node.FieldSymbol, node.ConstantValue, node.ResultKind, node.Type, node); }
/// <summary> /// Generate a thread-safe accessor for a WinRT field-like event. /// /// Add: /// return EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddEventHandler(value); /// /// Remove: /// EventRegistrationTokenTable<Event>.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 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; 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<BoundNode>(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<BoundNode>(getOrCreateCall), ErrorTypeSymbol.UnknownResultType); }
public override BoundNode VisitFieldAccess(BoundFieldAccess node) { CheckReceiverIfField(node.ReceiverOpt); return(base.VisitFieldAccess(node)); }
/// <summary> /// Introduce a frame around the translation of the given node. /// </summary> /// <param name="node">The node whose translation should be translated to contain a frame</param> /// <param name="frame">The frame for the translated node</param> /// <param name="F">A function that computes the translation of the node. It receives lists of added statements and added symbols</param> /// <returns>The translated statement, as returned from F</returns> private T IntroduceFrame <T>(BoundNode node, LambdaFrame frame, Func <ArrayBuilder <BoundExpression>, ArrayBuilder <LocalSymbol>, T> F) { NamedTypeSymbol frameType = frame.ConstructIfGeneric(StaticCast <TypeSymbol> .From(currentTypeParameters)); LocalSymbol framePointer = new LambdaFrameLocalSymbol(this.topLevelMethod, frameType, CompilationState); CSharpSyntaxNode syntax = node.Syntax; // assign new frame to the frame variable CompilationState.AddSynthesizedMethod(frame.Constructor, FlowAnalysisPass.AppendImplicitReturn(MethodCompiler.BindMethodBody(frame.Constructor, CompilationState, null), frame.Constructor)); var prologue = ArrayBuilder <BoundExpression> .GetInstance(); MethodSymbol constructor = frame.Constructor.AsMember(frameType); Debug.Assert(frameType == constructor.ContainingType); var newFrame = new BoundObjectCreationExpression( syntax: syntax, constructor: constructor); prologue.Add(new BoundAssignmentOperator(syntax, new BoundLocal(syntax, framePointer, null, frameType), newFrame, frameType)); CapturedSymbolReplacement oldInnermostFrameProxy = null; if ((object)innermostFramePointer != null) { proxies.TryGetValue(innermostFramePointer, out oldInnermostFrameProxy); if (analysis.needsParentFrame.Contains(node)) { var capturedFrame = new LambdaCapturedVariable(frame, innermostFramePointer); FieldSymbol frameParent = capturedFrame.AsMember(frameType); BoundExpression left = new BoundFieldAccess(syntax, new BoundLocal(syntax, framePointer, null, frameType), frameParent, null); BoundExpression right = FrameOfType(syntax, frameParent.Type as NamedTypeSymbol); BoundExpression assignment = new BoundAssignmentOperator(syntax, left, right, left.Type); if (this.currentMethod.MethodKind == MethodKind.Constructor && capturedFrame.Type == this.currentMethod.ContainingType && !this.seenBaseCall) { // Containing method is a constructor // Initialization statement for the "this" proxy must be inserted // after the constructor initializer statement block // This insertion will be done by the delegate F Debug.Assert(thisProxyInitDeferred == null); thisProxyInitDeferred = assignment; } else { prologue.Add(assignment); } if (CompilationState.Emitting) { CompilationState.ModuleBuilderOpt.AddSynthesizedDefinition(frame, capturedFrame); } proxies[innermostFramePointer] = new CapturedToFrameSymbolReplacement(capturedFrame); } } // Capture any parameters of this block. This would typically occur // at the top level of a method or lambda with captured parameters. // TODO: speed up the following by computing it in analysis. foreach (var v in analysis.variablesCaptured) { BoundNode varNode; if (!analysis.variableBlock.TryGetValue(v, out varNode) || varNode != node || analysis.declaredInsideExpressionLambda.Contains(v)) { continue; } InitVariableProxy(syntax, v, framePointer, prologue); } Symbol oldInnermostFramePointer = innermostFramePointer; innermostFramePointer = framePointer; var addedLocals = ArrayBuilder <LocalSymbol> .GetInstance(); addedLocals.Add(framePointer); framePointers.Add(frame, framePointer); var result = F(prologue, addedLocals); framePointers.Remove(frame); innermostFramePointer = oldInnermostFramePointer; if ((object)innermostFramePointer != null) { if (oldInnermostFrameProxy != null) { proxies[innermostFramePointer] = oldInnermostFrameProxy; } else { proxies.Remove(innermostFramePointer); } } return(result); }
private static bool IsInstanceFieldAccessWithNonThisReceiver(BoundFieldAccess fieldAccess) { BoundExpression receiver = fieldAccess.ReceiverOpt; if (receiver == null || fieldAccess.FieldSymbol.IsStatic) { return false; } while (receiver.Kind == BoundKind.Conversion) { BoundConversion conversion = (BoundConversion)receiver; if (conversion.ExplicitCastInCode) break; receiver = conversion.Operand; } return receiver.Kind != BoundKind.ThisReference && receiver.Kind != BoundKind.BaseReference; }
private BoundPattern BindDeclarationPattern( DeclarationPatternSyntax node, BoundExpression operand, TypeSymbol operandType, bool hasErrors, DiagnosticBag diagnostics) { Debug.Assert(operand != null && operandType != (object)null); var typeSyntax = node.Type; bool isVar; AliasSymbol aliasOpt; TypeSymbol declType = BindType(typeSyntax, diagnostics, out isVar, out aliasOpt); if (isVar) { declType = operandType; } if (declType == (object)null) { Debug.Assert(hasErrors); declType = this.CreateErrorType("var"); } var boundDeclType = new BoundTypeExpression(typeSyntax, aliasOpt, inferredType: isVar, type: declType); if (IsOperatorErrors(node, operandType, boundDeclType, diagnostics)) { hasErrors = true; } else { hasErrors |= CheckValidPatternType(typeSyntax, operand, operandType, declType, isVar: isVar, patternTypeWasInSource: true, diagnostics: diagnostics); } switch (node.Designation.Kind()) { case SyntaxKind.SingleVariableDesignation: break; case SyntaxKind.DiscardedDesignation: return new BoundDeclarationPattern(node, null, boundDeclType, isVar, hasErrors); default: throw ExceptionUtilities.UnexpectedValue(node.Designation.Kind()); } var designation = (SingleVariableDesignationSyntax)node.Designation; var identifier = designation.Identifier; SourceLocalSymbol localSymbol = this.LookupLocal(identifier); if (localSymbol != (object)null) { if (InConstructorInitializer || InFieldInitializer) { Error(diagnostics, ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, node); } localSymbol.SetType(declType); // Check for variable declaration errors. hasErrors |= localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics); if (!hasErrors) { hasErrors = CheckRestrictedTypeInAsync(this.ContainingMemberOrLambda, declType, diagnostics, typeSyntax); } return new BoundDeclarationPattern(node, localSymbol, boundDeclType, isVar, hasErrors); } else { // We should have the right binder in the chain for a script or interactive, so we use the field for the pattern. Debug.Assert(node.SyntaxTree.Options.Kind != SourceCodeKind.Regular); GlobalExpressionVariable expressionVariableField = LookupDeclaredField(designation); DiagnosticBag tempDiagnostics = DiagnosticBag.GetInstance(); expressionVariableField.SetType(declType, tempDiagnostics); tempDiagnostics.Free(); BoundExpression receiver = SynthesizeReceiver(node, expressionVariableField, diagnostics); var variableAccess = new BoundFieldAccess(node, receiver, expressionVariableField, null, hasErrors); return new BoundDeclarationPattern(node, expressionVariableField, variableAccess, boundDeclType, isVar, hasErrors); } }
private void NoteReceiverRead(BoundFieldAccess expr) { NoteReceiverReadOrWritten(expr, _readInside); }
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; 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)); }
private BoundFieldAccess TransformReferenceTypeFieldAccess(BoundFieldAccess fieldAccess, BoundExpression receiver, ArrayBuilder<BoundExpression> stores, ArrayBuilder<LocalSymbol> temps) { Debug.Assert(receiver.Type.IsReferenceType); Debug.Assert(receiver.Kind != BoundKind.TypeExpression); BoundExpression rewrittenReceiver = VisitExpression(receiver); if (rewrittenReceiver.Type.IsTypeParameter()) { var memberContainingType = fieldAccess.FieldSymbol.ContainingType; // From the verifier prospective type parameters do not contain fields or methods. // the instance must be "boxed" to access the field // It makes sense to box receiver before storing into a temp - no need to box twice. rewrittenReceiver = BoxReceiver(rewrittenReceiver, memberContainingType); } BoundAssignmentOperator assignmentToTemp; var receiverTemp = _factory.StoreToTemp(rewrittenReceiver, out assignmentToTemp); stores.Add(assignmentToTemp); temps.Add(receiverTemp.LocalSymbol); return new BoundFieldAccess(fieldAccess.Syntax, receiverTemp, fieldAccess.FieldSymbol, null); }
public override BoundNode VisitFieldAccess(BoundFieldAccess node) { _syntaxWithReceiver = node.Syntax; return base.VisitFieldAccess(node); }
/// <summary> /// Converts access to a tuple instance into access into the underlying ValueTuple(s). /// /// For instance, tuple.Item8 /// produces fieldAccess(field=Item1, receiver=fieldAccess(field=Rest, receiver=ValueTuple for tuple)) /// </summary> private BoundExpression MakeTupleFieldAccess( CSharpSyntaxNode syntax, FieldSymbol tupleField, BoundExpression rewrittenReceiver, ConstantValue constantValueOpt, LookupResultKind resultKind, TypeSymbol type) { var tupleType = tupleField.ContainingType; NamedTypeSymbol currentLinkType = tupleType.TupleUnderlyingType; FieldSymbol underlyingField = tupleField.TupleUnderlyingField; if ((object)underlyingField == null) { // Use-site error must have been reported elsewhere. return new BoundFieldAccess(syntax, rewrittenReceiver, tupleField, constantValueOpt, resultKind, type, hasErrors: true); } if (underlyingField.ContainingType != currentLinkType) { WellKnownMember wellKnownTupleRest = TupleTypeSymbol.GetTupleTypeMember(TupleTypeSymbol.RestPosition, TupleTypeSymbol.RestPosition); var tupleRestField = (FieldSymbol)TupleTypeSymbol.GetWellKnownMemberInType(currentLinkType.OriginalDefinition, wellKnownTupleRest, _diagnostics, syntax); if ((object)tupleRestField == null) { // error tolerance for cases when Rest is missing return new BoundFieldAccess(syntax, rewrittenReceiver, tupleField, constantValueOpt, resultKind, type, hasErrors: true); } // make nested field accesses to Rest do { FieldSymbol nestedFieldSymbol = tupleRestField.AsMember(currentLinkType); currentLinkType = currentLinkType.TypeArgumentsNoUseSiteDiagnostics[TupleTypeSymbol.RestPosition - 1].TupleUnderlyingType; rewrittenReceiver = new BoundFieldAccess(syntax, rewrittenReceiver, nestedFieldSymbol, ConstantValue.NotAvailable, LookupResultKind.Viable, currentLinkType); } while (underlyingField.ContainingType != currentLinkType); } // make a field access for the most local access return new BoundFieldAccess(syntax, rewrittenReceiver, underlyingField, constantValueOpt, resultKind, type); }
public override BoundNode VisitFieldAccess(BoundFieldAccess node) { BoundExpression rewrittenReceiver = VisitExpression(node.ReceiverOpt); return(MakeFieldAccess(node.Syntax, rewrittenReceiver, node.FieldSymbol, node.ConstantValue, node.ResultKind, node.Type, node)); }
private void NoteReceiverRead(BoundFieldAccess expr) { NoteReceiverReadOrWritten(expr, _readInside); }
/// <summary> /// When we read a field from a struct, the receiver isn't seen as being read until we get to the /// end of the field access expression, because we only read the relevant piece of the struct. /// But we want the receiver to be considered to be read in the region in that case. /// For example, if an rvalue expression is x.y.z and the region is x.y, we want x to be included /// in the ReadInside set. That is implemented here. /// </summary> private void NoteReceiverReadOrWritten(BoundFieldAccess expr, HashSet <Symbol> readOrWritten) { if (expr.FieldSymbol.IsStatic) { return; } if (expr.FieldSymbol.ContainingType.IsReferenceType) { return; } var receiver = expr.ReceiverOpt; if (receiver == null) { return; } var receiverSyntax = receiver.Syntax; if (receiverSyntax == null) { return; } switch (receiver.Kind) { case BoundKind.Local: if (RegionContains(receiverSyntax.Span)) { readOrWritten.Add(((BoundLocal)receiver).LocalSymbol); } break; case BoundKind.ThisReference: if (RegionContains(receiverSyntax.Span)) { readOrWritten.Add(this.MethodThisParameter); } break; case BoundKind.BaseReference: if (RegionContains(receiverSyntax.Span)) { readOrWritten.Add(this.MethodThisParameter); } break; case BoundKind.Parameter: if (RegionContains(receiverSyntax.Span)) { readOrWritten.Add(((BoundParameter)receiver).ParameterSymbol); } break; case BoundKind.RangeVariable: if (RegionContains(receiverSyntax.Span)) { readOrWritten.Add(((BoundRangeVariable)receiver).RangeVariableSymbol); } break; case BoundKind.FieldAccess: if (receiver.Type.IsStructType() && receiverSyntax.Span.OverlapsWith(RegionSpan)) { NoteReceiverReadOrWritten(receiver as BoundFieldAccess, readOrWritten); } break; } }
/// <summary> /// When we read a field from a struct, the receiver isn't seen as being read until we get to the /// end of the field access expression, because we only read the relevant piece of the struct. /// But we want the receiver to be considered to be read in the region in that case. /// For example, if an rvalue expression is x.y.z and the region is x.y, we want x to be included /// in the ReadInside set. That is implemented here. /// </summary> private void NoteReceiverReadOrWritten(BoundFieldAccess expr, HashSet<Symbol> readOrWritten) { if (expr.FieldSymbol.IsStatic) return; if (expr.FieldSymbol.ContainingType.IsReferenceType) return; var receiver = expr.ReceiverOpt; if (receiver == null) return; var receiverSyntax = receiver.Syntax; if (receiverSyntax == null) return; switch (receiver.Kind) { case BoundKind.Local: if (RegionContains(receiverSyntax.Span)) { readOrWritten.Add(((BoundLocal)receiver).LocalSymbol); } break; case BoundKind.ThisReference: if (RegionContains(receiverSyntax.Span)) { readOrWritten.Add(this.MethodThisParameter); } break; case BoundKind.BaseReference: if (RegionContains(receiverSyntax.Span)) { readOrWritten.Add(this.MethodThisParameter); } break; case BoundKind.Parameter: if (RegionContains(receiverSyntax.Span)) { readOrWritten.Add(((BoundParameter)receiver).ParameterSymbol); } break; case BoundKind.RangeVariable: if (RegionContains(receiverSyntax.Span)) { readOrWritten.Add(((BoundRangeVariable)receiver).RangeVariableSymbol); } break; case BoundKind.FieldAccess: if (receiver.Type.IsStructType() && receiverSyntax.Span.OverlapsWith(RegionSpan)) { NoteReceiverReadOrWritten(receiver as BoundFieldAccess, readOrWritten); } break; } }
public override BoundNode VisitFieldAccess(BoundFieldAccess node) { if (node.ReceiverOpt != null && node.ReceiverOpt.Kind == BoundKind.ThisReference) { var thisSymbol = topLevelMethod.ThisParameter; CaptureVariable(thisSymbol, node.Syntax); } return base.VisitFieldAccess(node); }
/// <summary> /// Construct a body for an auto-property accessor (updating or returning the backing field). /// </summary> internal static BoundBlock ConstructAutoPropertyAccessorBody(SourceMethodSymbol accessor) { Debug.Assert(accessor.MethodKind == MethodKind.PropertyGet || accessor.MethodKind == MethodKind.PropertySet); var property = (SourcePropertySymbol)accessor.AssociatedSymbol; CSharpSyntaxNode syntax = property.CSharpSyntaxNode; BoundExpression thisReference = null; if (!accessor.IsStatic) { var thisSymbol = accessor.ThisParameter; thisReference = new BoundThisReference(syntax, thisSymbol.Type) { WasCompilerGenerated = true }; } var field = property.BackingField; var fieldAccess = new BoundFieldAccess(syntax, thisReference, field, ConstantValue.NotAvailable) { WasCompilerGenerated = true }; BoundStatement statement; if (accessor.MethodKind == MethodKind.PropertyGet) { statement = new BoundReturnStatement(syntax, fieldAccess) { WasCompilerGenerated = true }; } else { Debug.Assert(accessor.MethodKind == MethodKind.PropertySet); var parameter = accessor.Parameters[0]; statement = new BoundExpressionStatement( syntax, new BoundAssignmentOperator( syntax, fieldAccess, new BoundParameter(syntax, parameter) { WasCompilerGenerated = true }, property.Type) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }; } statement = new BoundSequencePoint(accessor.SyntaxNode, statement) { WasCompilerGenerated = true }; return new BoundBlock(syntax, ImmutableArray<LocalSymbol>.Empty, ImmutableArray.Create<BoundStatement>(statement)) { WasCompilerGenerated = true }; }
private BoundExpression BindNamedAttributeArgument(AttributeArgumentSyntax namedArgument, NamedTypeSymbol attributeType, DiagnosticBag diagnostics) { bool wasError; LookupResultKind resultKind; Symbol namedArgumentNameSymbol = BindNamedAttributeArgumentName(namedArgument, attributeType, diagnostics, out wasError, out resultKind); ReportDiagnosticsIfObsolete(diagnostics, namedArgumentNameSymbol, namedArgument, hasBaseReceiver: false); Debug.Assert(resultKind == LookupResultKind.Viable || wasError); TypeSymbol namedArgumentType; if (wasError) { namedArgumentType = CreateErrorType(); // don't generate cascaded errors. } else { namedArgumentType = BindNamedAttributeArgumentType(namedArgument, namedArgumentNameSymbol, attributeType, diagnostics); } // BindRValue just binds the expression without doing any validation (if its a valid expression for attribute argument). // Validation is done later by AttributeExpressionVisitor BoundExpression namedArgumentValue = this.BindValue(namedArgument.Expression, diagnostics, BindValueKind.RValue); namedArgumentValue = GenerateConversionForAssignment(namedArgumentType, namedArgumentValue, diagnostics); // TODO: should we create an entry even if there are binding errors? var fieldSymbol = namedArgumentNameSymbol as FieldSymbol; IdentifierNameSyntax nameSyntax = namedArgument.NameEquals.Name; BoundExpression lvalue; if ((object)fieldSymbol != null) { var containingAssembly = fieldSymbol.ContainingAssembly as SourceAssemblySymbol; // We do not want to generate any unassigned field or unreferenced field diagnostics. containingAssembly?.NoteFieldAccess(fieldSymbol, read: true, write: true); lvalue = new BoundFieldAccess(nameSyntax, null, fieldSymbol, ConstantValue.NotAvailable, resultKind, fieldSymbol.Type); } else { var propertySymbol = namedArgumentNameSymbol as PropertySymbol; if ((object)propertySymbol != null) { lvalue = new BoundPropertyAccess(nameSyntax, null, propertySymbol, resultKind, namedArgumentType); } else { lvalue = BadExpression(nameSyntax, resultKind); } } return new BoundAssignmentOperator(namedArgument, lvalue, namedArgumentValue, namedArgumentType); }
/// <summary> /// Generate a thread-safe accessor for a WinRT field-like event. /// /// Add: /// return EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddEventHandler(value); /// /// Remove: /// EventRegistrationTokenTable<Event>.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, arguments: 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, arguments: 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 VisitFieldAccess(BoundFieldAccess node) { var receiver = node.FieldSymbol.IsStatic ? _bound.Null(ExpressionType) : Visit(node.ReceiverOpt); return ExprFactory( "Field", receiver, _bound.FieldInfo(node.FieldSymbol)); }
public override BoundNode VisitFieldAccess(BoundFieldAccess node) { CheckReceiverIfField(node.ReceiverOpt); return base.VisitFieldAccess(node); }
/// <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<DelegateType>(ref _event, tmp2, tmp1); /// } while ((object)tmp0 != (object)tmp1); /// /// Note, if System.Threading.Interlocked.CompareExchange<T> 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 }); }
protected override BoundStatement InitializeParameterField( MethodSymbol getEnumeratorMethod, ParameterSymbol parameter, BoundExpression resultParameter, BoundExpression parameterProxy ) { BoundStatement result; if ( _combinedTokensField is object && parameter.IsSourceParameterWithEnumeratorCancellationAttribute() && parameter.Type.Equals( F.Compilation.GetWellKnownType( WellKnownType.System_Threading_CancellationToken ), TypeCompareKind.ConsiderEverything ) ) { // For a parameter of type CancellationToken with [EnumeratorCancellation] // if (this.parameterProxy.Equals(default)) // { // result.parameter = token; // } // else if (token.Equals(this.parameterProxy) || token.Equals(default)) // { // result.parameter = this.parameterProxy; // } // else // { // result.combinedTokens = CancellationTokenSource.CreateLinkedTokenSource(this.parameterProxy, token); // result.parameter = combinedTokens.Token; // } BoundParameter tokenParameter = F.Parameter(getEnumeratorMethod.Parameters[0]); BoundFieldAccess combinedTokens = F.Field(F.This(), _combinedTokensField); result = F.If( // if (this.parameterProxy.Equals(default)) F.Call( parameterProxy, WellKnownMember.System_Threading_CancellationToken__Equals, F.Default(parameterProxy.Type) ), // result.parameter = token; thenClause: F.Assignment(resultParameter, tokenParameter), elseClauseOpt: F.If( // else if (token.Equals(this.parameterProxy) || token.Equals(default)) F.LogicalOr( F.Call( tokenParameter, WellKnownMember.System_Threading_CancellationToken__Equals, parameterProxy ), F.Call( tokenParameter, WellKnownMember.System_Threading_CancellationToken__Equals, F.Default(tokenParameter.Type) ) ), // result.parameter = this.parameterProxy; thenClause: F.Assignment(resultParameter, parameterProxy), elseClauseOpt: F.Block( // result.combinedTokens = CancellationTokenSource.CreateLinkedTokenSource(this.parameterProxy, token); F.Assignment( combinedTokens, F.StaticCall( WellKnownMember.System_Threading_CancellationTokenSource__CreateLinkedTokenSource, parameterProxy, tokenParameter ) ), // result.parameter = result.combinedTokens.Token; F.Assignment( resultParameter, F.Property( combinedTokens, WellKnownMember.System_Threading_CancellationTokenSource__Token ) ) ) ) ); } else { // For parameters that don't have [EnumeratorCancellation], initialize their parameter fields // result.parameter = this.parameterProxy; result = F.Assignment(resultParameter, parameterProxy); } return(result); }
/// <summary> /// Generates the `ValueTask<bool> MoveNextAsync()` method. /// </summary> private void GenerateIAsyncEnumeratorImplementation_MoveNextAsync() { // Produce: // if (State == StateMachineStates.FinishedStateMachine) // { // return default(ValueTask<bool>) // } // _valueOrEndPromise.Reset(); // var inst = this; // _builder.Start(ref inst); // return new ValueTask<bool>(this, _valueOrEndPromise.Version); NamedTypeSymbol IAsyncEnumeratorOfElementType = F.WellKnownType(WellKnownType.System_Collections_Generic_IAsyncEnumerator_T) .Construct(_currentField.Type.TypeSymbol); MethodSymbol IAsyncEnumerableOfElementType_MoveNextAsync = F.WellKnownMethod(WellKnownMember.System_Collections_Generic_IAsyncEnumerator_T__MoveNextAsync) .AsMember(IAsyncEnumeratorOfElementType); // The implementation doesn't depend on the method body of the iterator method. OpenMethodImplementation(IAsyncEnumerableOfElementType_MoveNextAsync, hasMethodBodyDependency: false); var ifFinished = F.If( // if (State == StateMachineStates.FinishedStateMachine) F.IntEqual(F.Field(F.This(), stateField), F.Literal(StateMachineStates.FinishedStateMachine)), // return default(ValueTask<bool>) thenClause: F.Return(F.Default(IAsyncEnumerableOfElementType_MoveNextAsync.ReturnType.TypeSymbol))); // _promiseOfValueOrEnd.Reset(); BoundFieldAccess promiseField = F.Field(F.This(), _promiseOfValueOrEndField); var resetMethod = (MethodSymbol)F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__Reset, isOptional: true) .SymbolAsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type.TypeSymbol); var callReset = F.ExpressionStatement(F.Call(promiseField, resetMethod)); // _builder.Start(ref inst); Debug.Assert(!_asyncMethodBuilderMemberCollection.CheckGenericMethodConstraints); MethodSymbol startMethod = _asyncMethodBuilderMemberCollection.Start.Construct(this.stateMachineType); LocalSymbol instSymbol = F.SynthesizedLocal(this.stateMachineType); BoundLocal instLocal = F.Local(instSymbol); BoundExpressionStatement startCall = F.ExpressionStatement( F.Call( F.Field(F.This(), _builderField), startMethod, ImmutableArray.Create <BoundExpression>(instLocal))); MethodSymbol valueTask_ctor = F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_ValueTask_T__ctor) .AsMember((NamedTypeSymbol)IAsyncEnumerableOfElementType_MoveNextAsync.ReturnType.TypeSymbol); MethodSymbol promise_get_Version = F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__get_Version) .AsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type.TypeSymbol); // return new ValueTask<bool>(this, _valueOrEndPromise.Version); var returnStatement = F.Return(F.New(valueTask_ctor, F.This(), F.Call(F.Field(F.This(), _promiseOfValueOrEndField), promise_get_Version))); F.CloseMethod(F.Block( ImmutableArray.Create(instSymbol), ifFinished, callReset, // _promiseOfValueOrEnd.Reset(); F.Assignment(instLocal, F.This()), // var inst = this; startCall, // _builder.Start(ref inst); returnStatement)); }
private static BoundStatement RewriteFieldInitializer(BoundFieldEqualsValue fieldInit) { var syntax = fieldInit.Syntax; syntax = (syntax as EqualsValueClauseSyntax)?.Value ?? syntax; //we want the attached sequence point to indicate the value node var boundReceiver = fieldInit.Field.IsStatic ? null : new BoundThisReference(syntax, fieldInit.Field.ContainingType); #if XSHARP var initValue = fieldInit.Value; // a generated initial value for VO NULL_STRING initialization // should not overwrite a value set in a child class // not that we recommend that <g> bool wasGenerated = fieldInit.WasCompilerGenerated; if (!wasGenerated) { var xNode = initValue.Syntax as LiteralExpressionSyntax; if (xNode != null && xNode.XGenerated) { wasGenerated = true; } } if (wasGenerated && fieldInit.Field.Type.IsStringType() && boundReceiver != null && fieldInit.Field.DeclaringCompilation.Options.HasOption(CompilerOption.NullStrings, boundReceiver.Syntax)) { var fldaccess = new BoundFieldAccess(syntax, boundReceiver, fieldInit.Field, constantValueOpt: null) { WasCompilerGenerated = true }; initValue = new BoundNullCoalescingOperator(syntax, fldaccess, initValue, Conversion.Identity, fieldInit.Field.Type) { WasCompilerGenerated = true }; } BoundStatement boundStatement = new BoundExpressionStatement(syntax, new BoundAssignmentOperator(syntax, new BoundFieldAccess(syntax, boundReceiver, fieldInit.Field, constantValueOpt: null), initValue, fieldInit.Field.Type) { WasCompilerGenerated = true }) { WasCompilerGenerated = fieldInit.WasCompilerGenerated }; #else BoundStatement boundStatement = new BoundExpressionStatement(syntax, new BoundAssignmentOperator(syntax, new BoundFieldAccess(syntax, boundReceiver, fieldInit.Field, constantValueOpt: null), fieldInit.Value, fieldInit.Field.Type) { WasCompilerGenerated = true }) { WasCompilerGenerated = !fieldInit.Locals.IsEmpty || fieldInit.WasCompilerGenerated }; #endif if (!fieldInit.Locals.IsEmpty) { boundStatement = new BoundBlock(syntax, fieldInit.Locals, ImmutableArray.Create(boundStatement)) { WasCompilerGenerated = fieldInit.WasCompilerGenerated }; } Debug.Assert(LocalRewriter.IsFieldOrPropertyInitializer(boundStatement)); return(boundStatement); }