private BoundExpression MakePropertyGetAccess(
            SyntaxNode syntax,
            BoundExpression rewrittenReceiver,
            PropertySymbol property,
            ImmutableArray<BoundExpression> rewrittenArguments,
            MethodSymbol getMethodOpt = null,
            BoundPropertyAccess oldNodeOpt = null)
        {
            if (_inExpressionLambda && rewrittenArguments.IsEmpty)
            {
                return oldNodeOpt != null ?
                    oldNodeOpt.Update(rewrittenReceiver, property, LookupResultKind.Viable, property.Type) :
                    new BoundPropertyAccess(syntax, rewrittenReceiver, property, LookupResultKind.Viable, property.Type);
            }
            else
            {
                var getMethod = getMethodOpt ?? property.GetOwnOrInheritedGetMethod();

                Debug.Assert((object)getMethod != null);
                Debug.Assert(getMethod.ParameterCount == rewrittenArguments.Length);
                Debug.Assert(((object)getMethodOpt == null) || ReferenceEquals(getMethod, getMethodOpt));

                return BoundCall.Synthesized(
                    syntax,
                    rewrittenReceiver,
                    getMethod,
                    rewrittenArguments);
            }
        }
        private BoundExpression MakePropertyAccess(
            SyntaxNode syntax,
            BoundExpression rewrittenReceiverOpt,
            PropertySymbol propertySymbol,
            LookupResultKind resultKind,
            TypeSymbol type,
            bool isLeftOfAssignment,
            BoundPropertyAccess oldNodeOpt = null)
        {
            // check for System.Array.[Length|LongLength] on a single dimensional array,
            // we have a special node for such cases.
            if (rewrittenReceiverOpt != null && rewrittenReceiverOpt.Type.IsArray() && !isLeftOfAssignment)
            {
                var asArrayType = (ArrayTypeSymbol)rewrittenReceiverOpt.Type;
                if (asArrayType.IsSZArray)
                {
                    // NOTE: we are not interested in potential badness of Array.Length property.
                    // If it is bad reference compare will not succeed.
                    if (ReferenceEquals(propertySymbol, _compilation.GetSpecialTypeMember(SpecialMember.System_Array__Length)) ||
                        !_inExpressionLambda && ReferenceEquals(propertySymbol, _compilation.GetSpecialTypeMember(SpecialMember.System_Array__LongLength)))
                    {
                        return new BoundArrayLength(syntax, rewrittenReceiverOpt, type);
                    }
                }
            }

            if (isLeftOfAssignment && propertySymbol.RefKind == RefKind.None)
            {
                // This is a property set access. We return a BoundPropertyAccess node here.
                // This node will be rewritten with MakePropertyAssignment when rewriting the enclosing BoundAssignmentOperator.

                return oldNodeOpt != null ?
                    oldNodeOpt.Update(rewrittenReceiverOpt, propertySymbol, resultKind, type) :
                    new BoundPropertyAccess(syntax, rewrittenReceiverOpt, propertySymbol, resultKind, type);
            }
            else
            {
                // This is a property get access
                return MakePropertyGetAccess(syntax, rewrittenReceiverOpt, propertySymbol, oldNodeOpt);
            }
        }
Ejemplo n.º 3
0
        private BoundExpression VisitPropertyAccess(BoundPropertyAccess node)
        {
            var receiver  = node.PropertySymbol.IsStatic ? _bound.Null(ExpressionType) : Visit(node.ReceiverOpt);
            var getMethod = node.PropertySymbol.GetOwnOrInheritedGetMethod();

            // COMPAT: see https://github.com/dotnet/roslyn/issues/4471
            //         old compiler used to insert casts like this and
            //         there are known dependencies on this kind of tree shape.
            //
            //         While the casts are semantically incorrect, the conditions
            //         under which they are observable are extremely narrow:
            //         We would have to deal with a generic T receiver which is actually a struct
            //         that implements a property form an interface and
            //         the implementation of the getter must make observable mutations to the instance.
            //
            //         At this point it seems more appropriate to continue adding these casts.
            if (node.ReceiverOpt?.Type.IsTypeParameter() == true &&
                !node.ReceiverOpt.Type.IsReferenceType)
            {
                receiver = this.Convert(receiver, getMethod.ReceiverType, isChecked: false);
            }

            return(ExprFactory("Property", receiver, _bound.MethodInfo(getMethod)));
        }
Ejemplo n.º 4
0
 public override BoundNode VisitPropertyAccess(BoundPropertyAccess node)
 {
     _syntaxWithReceiver = node.Syntax;
     return(base.VisitPropertyAccess(node));
 }
Ejemplo n.º 5
0
 internal static bool AccessingAutopropertyFromConstructor(BoundPropertyAccess propertyAccess, Symbol fromMember)
 {
     return AccessingAutopropertyFromConstructor(propertyAccess.ReceiverOpt, propertyAccess.PropertySymbol, fromMember);
 }
Ejemplo n.º 6
0
 public override BoundNode VisitPropertyAccess(BoundPropertyAccess node)
 {
     _syntaxWithReceiver = node.Syntax;
     return base.VisitPropertyAccess(node);
 }
Ejemplo n.º 7
0
 private BoundExpression VisitPropertyAccess(BoundPropertyAccess node)
 {
     var receiver = node.PropertySymbol.IsStatic ? Bound.Null(ExpressionType) : Visit(node.ReceiverOpt);
     var getMethod = node.PropertySymbol.GetOwnOrInheritedGetMethod();
     return ExprFactory("Property", receiver, Bound.MethodInfo(getMethod));
 }
 public override BoundNode VisitPropertyAccess(BoundPropertyAccess node)
 {
     return VisitPropertyAccess(node, isLeftOfAssignment: false);
 }
Ejemplo n.º 9
0
 private BoundExpression MakePropertyGetAccess(CSharpSyntaxNode syntax, BoundExpression rewrittenReceiver, PropertySymbol property, BoundPropertyAccess oldNodeOpt)
 {
     return(MakePropertyGetAccess(syntax, rewrittenReceiver, property, ImmutableArray <BoundExpression> .Empty, null, oldNodeOpt));
 }
Ejemplo n.º 10
0
 public override BoundNode VisitPropertyAccess(BoundPropertyAccess node)
 {
     return(VisitPropertyAccess(node, isLeftOfAssignment: false));
 }
 public override BoundNode VisitPropertyAccess(BoundPropertyAccess node)
 {
     CheckReceiverIfField(node.ReceiverOpt);
     return base.VisitPropertyAccess(node);
 }
        private BoundPropertyAccess TransformPropertyAccess(BoundPropertyAccess prop, ArrayBuilder<BoundExpression> stores, ArrayBuilder<LocalSymbol> temps)
        {
            // We need to stash away the receiver so that it does not get evaluated twice.
            // If the receiver is classified as a value of reference type then we can simply say
            //
            // R temp = receiver
            // temp.prop = temp.prop + rhs
            //
            // But if the receiver is classified as a variable of struct type then we
            // cannot make a copy of the value; we need to make sure that we mutate
            // the original receiver, not the copy.  We have to generate
            //
            // ref R temp = ref receiver
            // temp.prop = temp.prop + rhs
            //
            // The rules of C# (in section 7.17.1) require that if you have receiver.prop 
            // as the target of an assignment such that receiver is a value type, it must
            // be classified as a variable. If we've gotten this far in the rewriting,
            // assume that was the case.

            // If the property is static or if the receiver is of kind "Base" or "this", then we can just generate prop = prop + value
            if (prop.ReceiverOpt == null || prop.PropertySymbol.IsStatic || !CanChangeValueBetweenReads(prop.ReceiverOpt))
            {
                return prop;
            }

            Debug.Assert(prop.ReceiverOpt.Kind != BoundKind.TypeExpression);

            BoundExpression rewrittenReceiver = VisitExpression(prop.ReceiverOpt);

            BoundAssignmentOperator assignmentToTemp;

            // SPEC VIOLATION: It is not very clear when receiver of constrained callvirt is dereferenced - when pushed (in lexical order),
            // SPEC VIOLATION: or when actual call is executed. The actual behavior seems to be implementation specific in different JITs.
            // SPEC VIOLATION: To not depend on that, the right thing to do here is to store the value of the variable 
            // SPEC VIOLATION: when variable has reference type (regular temp), and store variable's location when it has a value type. (ref temp)
            // SPEC VIOLATION: in a case of unconstrained generic type parameter a runtime test (default(T) == null) would be needed
            // SPEC VIOLATION: However, for compatibility with Dev12 we will continue treating all generic type parameters, constrained or not,
            // SPEC VIOLATION: as value types.
            var variableRepresentsLocation = rewrittenReceiver.Type.IsValueType || rewrittenReceiver.Type.Kind == SymbolKind.TypeParameter;

            var receiverTemp = _factory.StoreToTemp(rewrittenReceiver, out assignmentToTemp, refKind: variableRepresentsLocation ? RefKind.Ref : RefKind.None);
            stores.Add(assignmentToTemp);
            temps.Add(receiverTemp.LocalSymbol);

            // CONSIDER: this is a temporary object that will be rewritten away before this lowering completes.
            // Mitigation: this will only produce short-lived garbage for compound assignments and increments/decrements of properties.
            return new BoundPropertyAccess(prop.Syntax, receiverTemp, prop.PropertySymbol, prop.ResultKind, prop.Type);
        }
Ejemplo n.º 13
0
 public override BoundNode VisitPropertyAccess(BoundPropertyAccess node)
 {
     CheckReceiverIfField(node.ReceiverOpt);
     return(base.VisitPropertyAccess(node));
 }
 private BoundExpression MakePropertyGetAccess(SyntaxNode syntax, BoundExpression rewrittenReceiver, PropertySymbol property, BoundPropertyAccess oldNodeOpt)
 {
     return MakePropertyGetAccess(syntax, rewrittenReceiver, property, ImmutableArray<BoundExpression>.Empty, null, oldNodeOpt);
 }
 private BoundExpression VisitPropertyAccess(BoundPropertyAccess node, bool isLeftOfAssignment)
 {
     var rewrittenReceiverOpt = VisitExpression(node.ReceiverOpt);
     return MakePropertyAccess(node.Syntax, rewrittenReceiverOpt, node.PropertySymbol, node.ResultKind, node.Type, isLeftOfAssignment, node);
 }
        /// <summary>
        /// Generates a lowered form of the assignment operator for the given left and right sub-expressions.
        /// Left and right sub-expressions must be in lowered form.
        /// </summary>
        private BoundExpression MakeStaticAssignmentOperator(
            SyntaxNode syntax,
            BoundExpression rewrittenLeft,
            BoundExpression rewrittenRight,
            bool isRef,
            TypeSymbol type,
            bool used)
        {
            switch (rewrittenLeft.Kind)
            {
            case BoundKind.DynamicIndexerAccess:
            case BoundKind.DynamicMemberAccess:
                throw ExceptionUtilities.UnexpectedValue(rewrittenLeft.Kind);

            case BoundKind.PropertyAccess:
            {
                Debug.Assert(!isRef);
                BoundPropertyAccess propertyAccess    = (BoundPropertyAccess)rewrittenLeft;
                BoundExpression     rewrittenReceiver = propertyAccess.ReceiverOpt;
                PropertySymbol      property          = propertyAccess.PropertySymbol;
                Debug.Assert(!property.IsIndexer);
                return(MakePropertyAssignment(
                           syntax,
                           rewrittenReceiver,
                           property,
                           ImmutableArray <BoundExpression> .Empty,
                           default(ImmutableArray <RefKind>),
                           false,
                           default(ImmutableArray <int>),
                           rewrittenRight,
                           type,
                           used));
            }

            case BoundKind.IndexerAccess:
            {
                Debug.Assert(!isRef);
                BoundIndexerAccess indexerAccess     = (BoundIndexerAccess)rewrittenLeft;
                BoundExpression    rewrittenReceiver = indexerAccess.ReceiverOpt;
                ImmutableArray <BoundExpression> rewrittenArguments = indexerAccess.Arguments;
                PropertySymbol indexer = indexerAccess.Indexer;
                Debug.Assert(indexer.IsIndexer || indexer.IsIndexedProperty);
                return(MakePropertyAssignment(
                           syntax,
                           rewrittenReceiver,
                           indexer,
                           rewrittenArguments,
                           indexerAccess.ArgumentRefKindsOpt,
                           indexerAccess.Expanded,
                           indexerAccess.ArgsToParamsOpt,
                           rewrittenRight,
                           type,
                           used));
            }

            case BoundKind.Local:
            {
                Debug.Assert(!isRef || ((BoundLocal)rewrittenLeft).LocalSymbol.RefKind != RefKind.None);
                return(new BoundAssignmentOperator(
                           syntax,
                           rewrittenLeft,
                           rewrittenRight,
                           type,
                           isRef: isRef));
            }

            case BoundKind.DiscardExpression:
            {
                return(EnsureNotAssignableIfUsedAsMethodReceiver(rewrittenRight));
            }

            default:
            {
                Debug.Assert(!isRef);
                return(new BoundAssignmentOperator(
                           syntax,
                           rewrittenLeft,
                           rewrittenRight,
                           type));
            }
            }
        }
        private BoundExpression VisitPropertyAccess(BoundPropertyAccess node)
        {
            var receiver = node.PropertySymbol.IsStatic ? _bound.Null(ExpressionType) : Visit(node.ReceiverOpt);
            var getMethod = node.PropertySymbol.GetOwnOrInheritedGetMethod();

            // COMPAT: see https://github.com/dotnet/roslyn/issues/4471
            //         old compiler used to insert casts like this and 
            //         there are known dependencies on this kind of tree shape.
            //
            //         While the casts are semantically incorrect, the conditions
            //         under which they are observable are extremely narrow:
            //         We would have to deal with a generic T receiver which is actually a struct
            //         that implements a property form an interface and 
            //         the implementation of the getter must make observable mutations to the instance.
            //
            //         At this point it seems more appropriate to continue adding these casts.
            if (node.ReceiverOpt?.Type.IsTypeParameter() == true &&
                !node.ReceiverOpt.Type.IsReferenceType)
            {
                receiver = this.Convert(receiver, getMethod.ReceiverType, isChecked: false);
            }

            return ExprFactory("Property", receiver, _bound.MethodInfo(getMethod));
        }
Ejemplo n.º 18
0
 public override BoundNode VisitPropertyAccess(BoundPropertyAccess node)
 {
     return(base.VisitPropertyAccess(node));
 }
Ejemplo n.º 19
0
        private BoundExpression VisitPropertyAccess(BoundPropertyAccess node, bool isLeftOfAssignment)
        {
            var rewrittenReceiverOpt = VisitExpression(node.ReceiverOpt);

            return(MakePropertyAccess(node.Syntax, rewrittenReceiverOpt, node.PropertySymbol, node.ResultKind, node.Type, isLeftOfAssignment, node));
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Generates a lowered form of the assignment operator for the given left and right sub-expressions.
        /// Left and right sub-expressions must be in lowered form.
        /// </summary>
        private BoundExpression MakeStaticAssignmentOperator(
            SyntaxNode syntax,
            BoundExpression rewrittenLeft,
            BoundExpression rewrittenRight,
            bool isRef,
            TypeSymbol type,
            bool used)
        {
            switch (rewrittenLeft.Kind)
            {
            case BoundKind.DynamicIndexerAccess:
            case BoundKind.DynamicMemberAccess:
                throw ExceptionUtilities.UnexpectedValue(rewrittenLeft.Kind);

            case BoundKind.PropertyAccess:
            {
                Debug.Assert(!isRef);
                BoundPropertyAccess propertyAccess    = (BoundPropertyAccess)rewrittenLeft;
                BoundExpression?    rewrittenReceiver = propertyAccess.ReceiverOpt;
                PropertySymbol      property          = propertyAccess.PropertySymbol;
                Debug.Assert(!property.IsIndexer);
                return(MakePropertyAssignment(
                           syntax,
                           rewrittenReceiver,
                           property,
                           ImmutableArray <BoundExpression> .Empty,
                           default(ImmutableArray <RefKind>),
                           false,
                           default(ImmutableArray <int>),
                           rewrittenRight,
                           type,
                           used));
            }

            case BoundKind.IndexerAccess:
            {
                Debug.Assert(!isRef);
                BoundIndexerAccess indexerAccess           = (BoundIndexerAccess)rewrittenLeft;
                BoundExpression?   rewrittenReceiver       = indexerAccess.ReceiverOpt;
                ImmutableArray <BoundExpression> arguments = indexerAccess.Arguments;
                PropertySymbol indexer = indexerAccess.Indexer;
                Debug.Assert(indexer.IsIndexer || indexer.IsIndexedProperty);
                return(MakePropertyAssignment(
                           syntax,
                           rewrittenReceiver,
                           indexer,
                           arguments,
                           indexerAccess.ArgumentRefKindsOpt,
                           indexerAccess.Expanded,
                           indexerAccess.ArgsToParamsOpt,
                           rewrittenRight,
                           type,
                           used));
            }

            case BoundKind.Local:
            case BoundKind.Parameter:
            case BoundKind.FieldAccess:
            {
                Debug.Assert(!isRef || rewrittenLeft.GetRefKind() != RefKind.None);
                return(new BoundAssignmentOperator(
                           syntax,
                           rewrittenLeft,
                           rewrittenRight,
                           isRef,
                           type));
            }

            case BoundKind.DiscardExpression:
            {
                return(rewrittenRight);
            }

            case BoundKind.Sequence:
                // An Index or Range pattern-based indexer, or an interpolated string handler conversion
                // that uses an indexer argument, produces a sequence with a nested
                // BoundIndexerAccess. We need to lower the final expression and produce an
                // update sequence
                var sequence = (BoundSequence)rewrittenLeft;
                if (sequence.Value.Kind == BoundKind.IndexerAccess)
                {
                    return(sequence.Update(
                               sequence.Locals,
                               sequence.SideEffects,
                               MakeStaticAssignmentOperator(
                                   syntax,
                                   sequence.Value,
                                   rewrittenRight,
                                   isRef,
                                   type,
                                   used),
                               type));
                }
                goto default;

            default:
            {
                Debug.Assert(!isRef);
                return(new BoundAssignmentOperator(
                           syntax,
                           rewrittenLeft,
                           rewrittenRight,
                           type));
            }
            }
        }
Ejemplo n.º 21
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);
        }
Ejemplo n.º 22
0
 public override BoundNode VisitPropertyAccess(BoundPropertyAccess node)
 {
     var property = node.PropertySymbol;
     var method = property.GetMethod; // This is only checking for ref returns, so we don't fall back to the set method.
     if ((object)method != null && _inExpressionLambda && method.RefKind != RefKind.None)
     {
         Error(ErrorCode.ERR_RefReturningCallInExpressionTree, node);
     }
     CheckReceiverIfField(node.ReceiverOpt);
     return base.VisitPropertyAccess(node);
 }