Ejemplo n.º 1
0
        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);
            }
        }
Ejemplo n.º 6
0
        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);
            }
        }
Ejemplo n.º 7
0
        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);
        }
Ejemplo n.º 8
0
        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))
                           ));
            }
        }
Ejemplo n.º 9
0
        /// <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)));
        }
Ejemplo n.º 11
0
        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);
        }
Ejemplo n.º 12
0
        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);
        }
Ejemplo n.º 13
0
        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);
            }
Ejemplo n.º 15
0
        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);
        }
Ejemplo n.º 16
0
        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));
        }
Ejemplo n.º 17
0
        /// <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);
        }
Ejemplo n.º 18
0
        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);
        }
Ejemplo n.º 19
0
        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;
        }
Ejemplo n.º 20
0
        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));
            }
        }
Ejemplo n.º 21
0
        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&lt;DelegateType&gt;(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 };

        }
Ejemplo n.º 23
0
 public override BoundNode VisitFieldAccess(BoundFieldAccess node)
 {
     _syntaxWithReceiver = node.Syntax;
     return(base.VisitFieldAccess(node));
 }
Ejemplo n.º 24
0
 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));
        }
Ejemplo n.º 26
0
 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);
 }
Ejemplo n.º 27
0
        /// <summary>
        /// Generate a thread-safe accessor for a WinRT field-like event.
        ///
        /// Add:
        ///   return EventRegistrationTokenTable&lt;Event&gt;.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddEventHandler(value);
        ///
        /// Remove:
        ///   EventRegistrationTokenTable&lt;Event&gt;.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).RemoveEventHandler(value);
        /// </summary>
        internal static BoundBlock ConstructFieldLikeEventAccessorBody_WinRT(SourceEventSymbol eventSymbol, bool isAddMethod, CSharpCompilation compilation, DiagnosticBag diagnostics)
        {
            CSharpSyntaxNode syntax = eventSymbol.CSharpSyntaxNode;

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

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

            FieldSymbol field = eventSymbol.AssociatedField;

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

            NamedTypeSymbol fieldType = (NamedTypeSymbol)field.Type;

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

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

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

            getOrCreateMethod = getOrCreateMethod.AsMember(fieldType);

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

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

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

            processHandlerMethod = processHandlerMethod.AsMember(fieldType);

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

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

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

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

            if (isAddMethod)
            {
                // {
                //     return EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddHandler(value);
                // }
                BoundStatement returnStatement = BoundReturnStatement.Synthesized(syntax, processHandlerCall);
                return(BoundBlock.SynthesizedNoLocals(syntax, returnStatement));
            }
            else
            {
                // {
                //     EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).RemoveHandler(value);
                //     return;
                // }
                BoundStatement callStatement   = new BoundExpressionStatement(syntax, processHandlerCall);
                BoundStatement returnStatement = new BoundReturnStatement(syntax, expressionOpt: null);
                return(BoundBlock.SynthesizedNoLocals(syntax, callStatement, returnStatement));
            }
        }
Ejemplo n.º 28
0
        private BoundExpression MakeEventAccess(
            SyntaxNode syntax,
            BoundExpression rewrittenReceiver,
            EventSymbol eventSymbol,
            ConstantValue constantValueOpt,
            LookupResultKind resultKind,
            TypeSymbol type)
        {
            Debug.Assert(eventSymbol.HasAssociatedField);

            FieldSymbol fieldSymbol = eventSymbol.AssociatedField;
            Debug.Assert((object)fieldSymbol != null);

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

            NamedTypeSymbol fieldType = (NamedTypeSymbol)fieldSymbol.Type;
            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);
        }
Ejemplo n.º 29
0
 public override BoundNode VisitFieldAccess(BoundFieldAccess node)
 {
     CheckReceiverIfField(node.ReceiverOpt);
     return(base.VisitFieldAccess(node));
 }
Ejemplo n.º 30
0
        /// <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;
        }
Ejemplo n.º 32
0
        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);
            }
        }
Ejemplo n.º 33
0
 private void NoteReceiverRead(BoundFieldAccess expr)
 {
     NoteReceiverReadOrWritten(expr, _readInside);
 }
Ejemplo n.º 34
0
        private BoundExpression MakeEventAccess(
            SyntaxNode syntax,
            BoundExpression rewrittenReceiver,
            EventSymbol eventSymbol,
            ConstantValue constantValueOpt,
            LookupResultKind resultKind,
            TypeSymbol type)
        {
            Debug.Assert(eventSymbol.HasAssociatedField);

            FieldSymbol fieldSymbol = eventSymbol.AssociatedField;

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

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

            NamedTypeSymbol fieldType = (NamedTypeSymbol)fieldSymbol.Type;

            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);
        }
Ejemplo n.º 36
0
 public override BoundNode VisitFieldAccess(BoundFieldAccess node)
 {
     _syntaxWithReceiver = node.Syntax;
     return base.VisitFieldAccess(node);
 }
Ejemplo n.º 37
0
        /// <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);
        }
Ejemplo n.º 38
0
        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));
        }
Ejemplo n.º 39
0
 private void NoteReceiverRead(BoundFieldAccess expr)
 {
     NoteReceiverReadOrWritten(expr, _readInside);
 }
Ejemplo n.º 40
0
        /// <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;
            }
        }
Ejemplo n.º 41
0
 /// <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 };
        }
Ejemplo n.º 44
0
        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&lt;Event&gt;.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddEventHandler(value);
        /// 
        /// Remove:
        ///   EventRegistrationTokenTable&lt;Event&gt;.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).RemoveEventHandler(value);
        /// </summary>
        internal static BoundBlock ConstructFieldLikeEventAccessorBody_WinRT(SourceEventSymbol eventSymbol, bool isAddMethod, CSharpCompilation compilation, DiagnosticBag diagnostics)
        {
            CSharpSyntaxNode syntax = eventSymbol.CSharpSyntaxNode;

            MethodSymbol accessor = isAddMethod ? eventSymbol.AddMethod : eventSymbol.RemoveMethod;
            Debug.Assert((object)accessor != null);

            FieldSymbol field = eventSymbol.AssociatedField;
            Debug.Assert((object)field != null);

            NamedTypeSymbol fieldType = (NamedTypeSymbol)field.Type;
            Debug.Assert(fieldType.Name == "EventRegistrationTokenTable");

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

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

            getOrCreateMethod = getOrCreateMethod.AsMember(fieldType);

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

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

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

            processHandlerMethod = processHandlerMethod.AsMember(fieldType);

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

            // EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable)
            BoundCall getOrCreateCall = BoundCall.Synthesized(
                syntax,
                receiverOpt: null,
                method: getOrCreateMethod,
                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);
 }
Ejemplo n.º 48
0
        /// <summary>
        /// Generate a thread-safe accessor for a regular field-like event.
        ///
        /// DelegateType tmp0 = _event; //backing field
        /// DelegateType tmp1;
        /// DelegateType tmp2;
        /// do {
        ///     tmp1 = tmp0;
        ///     tmp2 = (DelegateType)Delegate.Combine(tmp1, value); //Remove for -=
        ///     tmp0 = Interlocked.CompareExchange&lt;DelegateType&gt;(ref _event, tmp2, tmp1);
        /// } while ((object)tmp0 != (object)tmp1);
        ///
        /// Note, if System.Threading.Interlocked.CompareExchange&lt;T&gt; is not available,
        /// we emit the following code and mark the method Synchronized (unless it is a struct).
        ///
        /// _event = (DelegateType)Delegate.Combine(_event, value); //Remove for -=
        ///
        /// </summary>
        internal static BoundBlock ConstructFieldLikeEventAccessorBody_Regular(SourceEventSymbol eventSymbol, bool isAddMethod, CSharpCompilation compilation, DiagnosticBag diagnostics)
        {
            CSharpSyntaxNode syntax = eventSymbol.CSharpSyntaxNode;

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

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

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

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

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

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

            Binder.ReportUseSiteDiagnostics(updateMethod, diagnostics, syntax);

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

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

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

            BoundExpression delegateUpdate;

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

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

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

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

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

            Binder.ReportUseSiteDiagnostics(compareExchangeMethod, diagnostics, syntax);

            GeneratedLabelSymbol loopLabel = new GeneratedLabelSymbol("loop");

            const int numTemps = 3;

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

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

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

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

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

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

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

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

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

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

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

            return(new BoundBlock(syntax,
                                  locals: tmps.AsImmutable(),
                                  statements: ImmutableArray.Create <BoundStatement>(
                                      tmp0Init,
                                      loopStart,
                                      tmp1Update,
                                      tmp2Update,
                                      tmp0Update,
                                      loopEnd,
                                      @return))
            {
                WasCompilerGenerated = true
            });
        }
Ejemplo n.º 49
0
            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);
            }
Ejemplo n.º 50
0
            /// <summary>
            /// Generates the `ValueTask&lt;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));
            }
Ejemplo n.º 51
0
        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);
        }