Пример #1
0
        internal static Symbol GetRuntimeMember(NamedTypeSymbol declaringType, ref MemberDescriptor descriptor, SignatureComparer <MethodSymbol, FieldSymbol, PropertySymbol, TypeSymbol, ParameterSymbol> comparer, IAssemblySymbol accessWithinOpt)
        {
            Symbol     result = null;
            SymbolKind targetSymbolKind;
            MethodKind targetMethodKind = MethodKind.Ordinary;
            bool       isStatic         = (descriptor.Flags & MemberFlags.Static) != 0;

            switch (descriptor.Flags & MemberFlags.KindMask)
            {
            case MemberFlags.Constructor:
                targetSymbolKind = SymbolKind.Method;
                targetMethodKind = MethodKind.Constructor;
                //  static constructors are never called explicitly
                Debug.Assert(!isStatic);
                break;

            case MemberFlags.Method:
                targetSymbolKind = SymbolKind.Method;
                break;

            case MemberFlags.PropertyGet:
                targetSymbolKind = SymbolKind.Method;
                targetMethodKind = MethodKind.PropertyGet;
                break;

            case MemberFlags.Field:
                targetSymbolKind = SymbolKind.Field;
                break;

            case MemberFlags.Property:
                targetSymbolKind = SymbolKind.Property;
                break;

            default:
                throw ExceptionUtilities.UnexpectedValue(descriptor.Flags);
            }

            foreach (var member in declaringType.GetMembers(descriptor.Name))
            {
                Debug.Assert(member.Name.Equals(descriptor.Name));

                if (member.Kind != targetSymbolKind || member.IsStatic != isStatic || !(member.DeclaredAccessibility == Accessibility.Public))
                {
                    continue;
                }

                switch (targetSymbolKind)
                {
                case SymbolKind.Method:
                {
                    MethodSymbol method     = (MethodSymbol)member;
                    MethodKind   methodKind = method.MethodKind;
                    // Treat user-defined conversions and operators as ordinary methods for the purpose
                    // of matching them here.
                    if (methodKind == MethodKind.Conversion || methodKind == MethodKind.UserDefinedOperator)
                    {
                        methodKind = MethodKind.Ordinary;
                    }

                    if (method.Arity != descriptor.Arity || methodKind != targetMethodKind ||
                        ((descriptor.Flags & MemberFlags.Virtual) != 0) != (method.IsVirtual || method.IsOverride || method.IsAbstract))
                    {
                        continue;
                    }

                    if (!comparer.MatchMethodSignature(method, descriptor.Signature))
                    {
                        continue;
                    }
                }

                break;

                case SymbolKind.Property:
                {
                    PropertySymbol property = (PropertySymbol)member;
                    if (((descriptor.Flags & MemberFlags.Virtual) != 0) != (property.IsVirtual || property.IsOverride || property.IsAbstract))
                    {
                        continue;
                    }

                    if (!comparer.MatchPropertySignature(property, descriptor.Signature))
                    {
                        continue;
                    }
                }

                break;

                case SymbolKind.Field:
                    if (!comparer.MatchFieldSignature((FieldSymbol)member, descriptor.Signature))
                    {
                        continue;
                    }

                    break;

                default:
                    throw ExceptionUtilities.UnexpectedValue(targetSymbolKind);
                }

                // ambiguity
                if ((object)result != null)
                {
                    result = null;
                    break;
                }

                result = member;
            }
            return(result);
        }
Пример #2
0
            /// <summary>
            /// Return the side-effect expression corresponding to an evaluation.
            /// </summary>
            protected BoundExpression LowerEvaluation(BoundDagEvaluation evaluation)
            {
                BoundExpression input = _tempAllocator.GetTemp(evaluation.Input);

                switch (evaluation)
                {
                case BoundDagFieldEvaluation f:
                {
                    FieldSymbol     field      = f.Field;
                    var             outputTemp = new BoundDagTemp(f.Syntax, field.Type, f);
                    BoundExpression output     = _tempAllocator.GetTemp(outputTemp);
                    BoundExpression access     = _localRewriter.MakeFieldAccess(f.Syntax, input, field, null, LookupResultKind.Viable, field.Type);
                    access.WasCompilerGenerated = true;
                    return(_factory.AssignmentExpression(output, access));
                }

                case BoundDagPropertyEvaluation p:
                {
                    PropertySymbol  property   = p.Property;
                    var             outputTemp = new BoundDagTemp(p.Syntax, property.Type, p);
                    BoundExpression output     = _tempAllocator.GetTemp(outputTemp);
                    return(_factory.AssignmentExpression(output, _factory.Property(input, property)));
                }

                case BoundDagDeconstructEvaluation d:
                {
                    MethodSymbol method         = d.DeconstructMethod;
                    var          refKindBuilder = ArrayBuilder <RefKind> .GetInstance();

                    var argBuilder = ArrayBuilder <BoundExpression> .GetInstance();

                    BoundExpression receiver;
                    void addArg(RefKind refKind, BoundExpression expression)
                    {
                        refKindBuilder.Add(refKind);
                        argBuilder.Add(expression);
                    }

                    Debug.Assert(method.Name == WellKnownMemberNames.DeconstructMethodName);
                    int extensionExtra;
                    if (method.IsStatic)
                    {
                        Debug.Assert(method.IsExtensionMethod);
                        receiver = _factory.Type(method.ContainingType);
                        addArg(method.ParameterRefKinds[0], input);
                        extensionExtra = 1;
                    }
                    else
                    {
                        receiver       = input;
                        extensionExtra = 0;
                    }

                    for (int i = extensionExtra; i < method.ParameterCount; i++)
                    {
                        ParameterSymbol parameter = method.Parameters[i];
                        Debug.Assert(parameter.RefKind == RefKind.Out);
                        var outputTemp = new BoundDagTemp(d.Syntax, parameter.Type, d, i - extensionExtra);
                        addArg(RefKind.Out, _tempAllocator.GetTemp(outputTemp));
                    }

                    return(_factory.Call(receiver, method, refKindBuilder.ToImmutableAndFree(), argBuilder.ToImmutableAndFree()));
                }

                case BoundDagTypeEvaluation t:
                {
                    TypeSymbol inputType = input.Type;
                    if (inputType.IsDynamic())
                    {
                        // Avoid using dynamic conversions for pattern-matching.
                        inputType = _factory.SpecialType(SpecialType.System_Object);
                        input     = _factory.Convert(inputType, input);
                    }

                    TypeSymbol               type               = t.Type;
                    var                      outputTemp         = new BoundDagTemp(t.Syntax, type, t);
                    BoundExpression          output             = _tempAllocator.GetTemp(outputTemp);
                    HashSet <DiagnosticInfo> useSiteDiagnostics = null;
                    Conversion               conversion         = _factory.Compilation.Conversions.ClassifyBuiltInConversion(inputType, output.Type, ref useSiteDiagnostics);
                    _localRewriter._diagnostics.Add(t.Syntax, useSiteDiagnostics);
                    BoundExpression evaluated;
                    if (conversion.Exists)
                    {
                        if (conversion.Kind == ConversionKind.ExplicitNullable &&
                            inputType.GetNullableUnderlyingType().Equals(output.Type, TypeCompareKind.AllIgnoreOptions) &&
                            _localRewriter.TryGetNullableMethod(t.Syntax, inputType, SpecialMember.System_Nullable_T_GetValueOrDefault, out MethodSymbol getValueOrDefault))
                        {
                            // As a special case, since the null test has already been done we can use Nullable<T>.GetValueOrDefault
                            evaluated = _factory.Call(input, getValueOrDefault);
                        }
                        else
                        {
                            evaluated = _factory.Convert(type, input, conversion);
                        }
                    }
                    else
                    {
                        evaluated = _factory.As(input, type);
                    }

                    return(_factory.AssignmentExpression(output, evaluated));
                }

                case BoundDagIndexEvaluation e:
                {
                    // This is an evaluation of an indexed property with a constant int value.
                    // The input type must be ITuple, and the property must be a property of ITuple.
                    Debug.Assert(e.Property.ContainingSymbol.Equals(input.Type));
                    Debug.Assert(e.Property.GetMethod.ParameterCount == 1);
                    Debug.Assert(e.Property.GetMethod.Parameters[0].Type.SpecialType == SpecialType.System_Int32);
                    TypeSymbol      type       = e.Property.GetMethod.ReturnType;
                    var             outputTemp = new BoundDagTemp(e.Syntax, type, e);
                    BoundExpression output     = _tempAllocator.GetTemp(outputTemp);
                    return(_factory.AssignmentExpression(output, _factory.Call(input, e.Property.GetMethod, _factory.Literal(e.Index))));
                }

                default:
                    throw ExceptionUtilities.UnexpectedValue(evaluation);
                }
            }
        /// <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:
            {
                Debug.Assert(!isRef || ((BoundLocal)rewrittenLeft).LocalSymbol.RefKind != RefKind.None);
                return(new BoundAssignmentOperator(
                           syntax,
                           rewrittenLeft,
                           rewrittenRight,
                           type,
                           isRef: isRef));
            }

            case BoundKind.Parameter:
            {
                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));
            }
            }
        }
Пример #4
0
 private BoundExpression MakePropertyGetAccess(SyntaxNode syntax, BoundExpression rewrittenReceiver, PropertySymbol property, BoundPropertyAccess oldNodeOpt)
 {
     return(MakePropertyGetAccess(syntax, rewrittenReceiver, property, ImmutableArray <BoundExpression> .Empty, null, oldNodeOpt));
 }
 /// <summary>
 /// Creates a SemanticModel for an autoprop initializer of a named type
 /// </summary>
 internal static InitializerSemanticModel Create(CSharpCompilation compilation, CSharpSyntaxNode syntax, PropertySymbol propertySymbol, Binder rootBinder)
 {
     Debug.Assert(syntax.IsKind(SyntaxKind.PropertyDeclaration));
     return(new InitializerSemanticModel(compilation, syntax, propertySymbol, rootBinder));
 }
Пример #6
0
        internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, TypeMap typeMap, out AsyncMethodBuilderMemberCollection collection)
        {
            if (method.IsIterator)
            {
                var builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder);
                Debug.Assert((object)builderType != null);

                TryGetBuilderMember <MethodSymbol>(
                    F,
                    WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__Create,
                    builderType,
                    customBuilder: false,
                    out MethodSymbol createBuilderMethod);

                if (createBuilderMethod is null)
                {
                    collection = default;
                    return(false);
                }

                return(TryCreate(
                           F,
                           customBuilder: false,
                           builderType: builderType,
                           resultType: F.SpecialType(SpecialType.System_Void),
                           createBuilderMethod: createBuilderMethod,
                           taskProperty: null,
                           setException: null,                                                                              // unused
                           setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__Complete, // AsyncIteratorMethodBuilder.Complete is the corresponding method to AsyncTaskMethodBuilder.SetResult
                           awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__AwaitOnCompleted,
                           awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__AwaitUnsafeOnCompleted,
                           start: WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__MoveNext_T,
                           setStateMachine: null, // unused
                           collection: out collection));
            }

            if (method.IsAsyncReturningVoid())
            {
                var builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncVoidMethodBuilder);
                Debug.Assert((object)builderType != null);
                MethodSymbol createBuilderMethod;
                bool         customBuilder = false;
                TryGetBuilderMember <MethodSymbol>(
                    F,
                    WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__Create,
                    builderType,
                    customBuilder,
                    out createBuilderMethod);
                if ((object)createBuilderMethod == null)
                {
                    collection = default(AsyncMethodBuilderMemberCollection);
                    return(false);
                }
                return(TryCreate(
                           F,
                           customBuilder: customBuilder,
                           builderType: builderType,
                           resultType: F.SpecialType(SpecialType.System_Void),
                           createBuilderMethod: createBuilderMethod,
                           taskProperty: null,
                           setException: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__SetException,
                           setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__SetResult,
                           awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__AwaitOnCompleted,
                           awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__AwaitUnsafeOnCompleted,
                           start: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__Start_T,
                           setStateMachine: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__SetStateMachine,
                           collection: out collection));
            }

            if (method.IsAsyncReturningTask(F.Compilation))
            {
                var             returnType = (NamedTypeSymbol)method.ReturnType;
                NamedTypeSymbol builderType;
                MethodSymbol    createBuilderMethod = null;
                PropertySymbol  taskProperty        = null;

                object builderArgument;
                bool   customBuilder = returnType.IsCustomTaskType(out builderArgument);
                if (customBuilder)
                {
                    builderType = ValidateBuilderType(F, builderArgument, returnType.DeclaredAccessibility, isGeneric: false);
                    if ((object)builderType != null)
                    {
                        taskProperty        = GetCustomTaskProperty(F, builderType, returnType);
                        createBuilderMethod = GetCustomCreateMethod(F, builderType);
                    }
                }
                else
                {
                    builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncTaskMethodBuilder);
                    Debug.Assert((object)builderType != null);
                    TryGetBuilderMember <MethodSymbol>(
                        F,
                        WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__Create,
                        builderType,
                        customBuilder,
                        out createBuilderMethod);
                    TryGetBuilderMember <PropertySymbol>(
                        F,
                        WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__Task,
                        builderType,
                        customBuilder,
                        out taskProperty);
                }
                if ((object)builderType == null ||
                    (object)createBuilderMethod == null ||
                    (object)taskProperty == null)
                {
                    collection = default(AsyncMethodBuilderMemberCollection);
                    return(false);
                }
                return(TryCreate(
                           F,
                           customBuilder: customBuilder,
                           builderType: builderType,
                           resultType: F.SpecialType(SpecialType.System_Void),
                           createBuilderMethod: createBuilderMethod,
                           taskProperty: taskProperty,
                           setException: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__SetException,
                           setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__SetResult,
                           awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__AwaitOnCompleted,
                           awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__AwaitUnsafeOnCompleted,
                           start: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__Start_T,
                           setStateMachine: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__SetStateMachine,
                           collection: out collection));
            }

            if (method.IsAsyncReturningGenericTask(F.Compilation))
            {
                var returnType = (NamedTypeSymbol)method.ReturnType;
                var resultType = returnType.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics.Single().Type;
                if (resultType.IsDynamic())
                {
                    resultType = F.SpecialType(SpecialType.System_Object);
                }
                if (typeMap != null)
                {
                    resultType = typeMap.SubstituteType(resultType).Type;
                }
                returnType = returnType.ConstructedFrom.Construct(resultType);
                NamedTypeSymbol builderType;
                MethodSymbol    createBuilderMethod = null;
                PropertySymbol  taskProperty        = null;

                object builderArgument;
                bool   customBuilder = returnType.IsCustomTaskType(out builderArgument);
                if (customBuilder)
                {
                    builderType = ValidateBuilderType(F, builderArgument, returnType.DeclaredAccessibility, isGeneric: true);
                    if ((object)builderType != null)
                    {
                        builderType         = builderType.ConstructedFrom.Construct(resultType);
                        taskProperty        = GetCustomTaskProperty(F, builderType, returnType);
                        createBuilderMethod = GetCustomCreateMethod(F, builderType);
                    }
                }
                else
                {
                    builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T);
                    Debug.Assert((object)builderType != null);
                    builderType = builderType.Construct(resultType);
                    TryGetBuilderMember <MethodSymbol>(
                        F,
                        WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__Create,
                        builderType,
                        customBuilder,
                        out createBuilderMethod);
                    TryGetBuilderMember <PropertySymbol>(
                        F,
                        WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__Task,
                        builderType,
                        customBuilder,
                        out taskProperty);
                }
                if ((object)builderType == null ||
                    (object)taskProperty == null ||
                    (object)createBuilderMethod == null)
                {
                    collection = default(AsyncMethodBuilderMemberCollection);
                    return(false);
                }
                return(TryCreate(
                           F,
                           customBuilder: customBuilder,
                           builderType: builderType,
                           resultType: resultType,
                           createBuilderMethod: createBuilderMethod,
                           taskProperty: taskProperty,
                           setException: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__SetException,
                           setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__SetResult,
                           awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__AwaitOnCompleted,
                           awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__AwaitUnsafeOnCompleted,
                           start: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__Start_T,
                           setStateMachine: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__SetStateMachine,
                           collection: out collection));
            }

            throw ExceptionUtilities.UnexpectedValue(method);
        }
Пример #7
0
        // There are two situations in which the language permits passing rvalues by reference.
        // (technically there are 4, but we can ignore COM and dynamic here, since that results in byval semantics regardless of the parameter ref kind)
        //
        // #1: Receiver of a struct/generic method call.
        //
        // The language only requires that receivers of method calls must be readable (RValues are ok).
        //
        // However the underlying implementation passes receivers of struct methods by reference.
        // In such situations it may be possible for the call to cause or observe writes to the receiver variable.
        // As a result it is not valid to replace receiver variable with a reference to it or the other way around.
        //
        // Example1:
        //        static int x = 123;
        //        async static Task<string> Test1()
        //        {
        //            // cannot capture "x" by value, since write in M1 is observable
        //            return x.ToString(await M1());
        //        }
        //
        //        async static Task<string> M1()
        //        {
        //            x = 42;
        //            await Task.Yield();
        //            return "";
        //        }
        //
        // Example2:
        //        static int x = 123;
        //        static string Test1()
        //        {
        //            // cannot replace value of "x" with a reference to "x"
        //            // since that would make the method see the mutations in M1();
        //            return (x + 0).ToString(M1());
        //        }
        //
        //        static string M1()
        //        {
        //            x = 42;
        //            return "";
        //        }
        //
        // #2: Ordinary byval argument passed to an "in" parameter.
        //
        // The language only requires that ordinary byval arguments must be readable (RValues are ok).
        // However if the target parameter is an "in" parameter, the underlying implementation passes by reference.
        //
        // Example:
        //        static int x = 123;
        //        static void Main(string[] args)
        //        {
        //            // cannot replace value of "x" with a direct reference to x
        //            // since Test will see unexpected changes due to aliasing.
        //            Test(x + 0);
        //        }
        //
        //        static void Test(in int y)
        //        {
        //            Console.WriteLine(y);
        //            x = 42;
        //            Console.WriteLine(y);
        //        }
        //
        // NB: The readonliness is not considered here.
        //     We only care about possible introduction of aliasing. I.E. RValue->LValue change.
        //     Even if we start with a readonly variable, it cannot be lowered into a writeable one,
        //     with one exception - spilling of the value into a local, which is ok.
        //
        internal static bool CanBePassedByReference(BoundExpression expr)
        {
            if (expr.ConstantValue != null)
            {
                return(false);
            }

            switch (expr.Kind)
            {
            case BoundKind.Parameter:
            case BoundKind.Local:
            case BoundKind.ArrayAccess:
            case BoundKind.ThisReference:
            case BoundKind.PointerIndirectionOperator:
            case BoundKind.PointerElementAccess:
            case BoundKind.RefValueOperator:
            case BoundKind.PseudoVariable:
            case BoundKind.DiscardExpression:
                return(true);

            case BoundKind.DeconstructValuePlaceholder:
                // we will consider that placeholder always represents a temp local
                // the assumption should be confirmed or changed when https://github.com/dotnet/roslyn/issues/24160 is fixed
                return(true);

            case BoundKind.EventAccess:
                var eventAccess = (BoundEventAccess)expr;
                if (eventAccess.IsUsableAsField)
                {
                    return(eventAccess.EventSymbol.IsStatic ||
                           CanBePassedByReference(eventAccess.ReceiverOpt));
                }

                return(false);

            case BoundKind.FieldAccess:
                var fieldAccess = (BoundFieldAccess)expr;
                if (!fieldAccess.FieldSymbol.IsStatic)
                {
                    return(CanBePassedByReference(fieldAccess.ReceiverOpt));
                }

                return(true);

            case BoundKind.Sequence:
                return(CanBePassedByReference(((BoundSequence)expr).Value));

            case BoundKind.AssignmentOperator:
                return(((BoundAssignmentOperator)expr).IsRef);

            case BoundKind.ConditionalOperator:
                return(((BoundConditionalOperator)expr).IsRef);

            case BoundKind.Call:
                return(((BoundCall)expr).Method.RefKind != RefKind.None);

            case BoundKind.PropertyAccess:
                return(((BoundPropertyAccess)expr).PropertySymbol.RefKind != RefKind.None);

            case BoundKind.IndexerAccess:
                return(((BoundIndexerAccess)expr).Indexer.RefKind != RefKind.None);

            case BoundKind.IndexOrRangePatternIndexerAccess:
                var patternIndexer = (BoundIndexOrRangePatternIndexerAccess)expr;
                var refKind        = patternIndexer.PatternSymbol switch
                {
                    PropertySymbol p => p.RefKind,
                    MethodSymbol m => m.RefKind,
                    _ => throw ExceptionUtilities.UnexpectedValue(patternIndexer.PatternSymbol)
                };
                return(refKind != RefKind.None);
            }

            return(false);
        }
        protected internal override object VisitProperty(PropertySymbol symbol, ArrayBuilder<SymbolDescriptionPart> builder)
        {
            AddAccessibilityIfRequired(symbol, builder);

            AddMemberModifiersIfRequired(symbol, builder);

            //TODO: custom modifiers

            if (format.MemberFlags.HasFlag(MemberFlags.IncludeType))
            {
                VisitType(symbol.Type, builder);
                AddSpace(builder);
            }

            if (format.MemberFlags.HasFlag(MemberFlags.IncludeExplicitInterface))
            {
                var implementedProperties = symbol.ExplicitInterfaceImplementation;
                if (implementedProperties.Any())
                {
                    if (implementedProperties.Skip(1).Any())
                    {
                        throw new NotImplementedException(); //TODO: multiple implemented properties?
                    }

                    var implementedProperty = implementedProperties.First();

                    VisitType(implementedProperty.ContainingType, builder);
                    AddPunctuation(SyntaxKind.DotToken, builder);
                }
            }

            if (symbol.IsIndexer)
            {
                AddKeyword(SyntaxKind.ThisKeyword, builder);

                if (format.MemberFlags.HasFlag(MemberFlags.IncludeParameters))
                {
                    AddPunctuation(SyntaxKind.OpenBraceToken, builder);
                    AddParameters(hasThisParameter: false, parameters: symbol.Parameters, builder: builder);
                    AddPunctuation(SyntaxKind.CloseBraceToken, builder);
                }
            }
            else
            {
                builder.Add(new SymbolDescriptionPart
                {
                    Kind = SymbolDescriptionPartKind.PropertyName,
                    Text = symbol.Name,
                });
            }

            if (format.PropertyStyle == PropertyStyle.GetSet)
            {
                AddPunctuation(SyntaxKind.OpenBraceToken, builder);

                AddGetOrSet(symbol, symbol.GetMethod, SyntaxKind.GetKeyword, builder);
                AddGetOrSet(symbol, symbol.SetMethod, SyntaxKind.SetKeyword, builder);

                AddSpace(builder);
                AddPunctuation(SyntaxKind.CloseBraceToken, builder);
            }

            return null;
        }
Пример #9
0
 public override object VisitProperty(PropertySymbol symbol, TypeCompilationState argument)
 {
     throw ExceptionUtilities.Unreachable;
 }
        private BoundIndexerAccess TransformIndexerAccess(BoundIndexerAccess indexerAccess, ArrayBuilder <BoundExpression> stores, ArrayBuilder <LocalSymbol> temps)
        {
            var receiverOpt = indexerAccess.ReceiverOpt;

            Debug.Assert(receiverOpt != null);

            BoundExpression transformedReceiver;

            if (CanChangeValueBetweenReads(receiverOpt))
            {
                BoundExpression rewrittenReceiver = VisitExpression(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);
                transformedReceiver = receiverTemp;
                stores.Add(assignmentToTemp);
                temps.Add(receiverTemp.LocalSymbol);
            }
            else
            {
                transformedReceiver = VisitExpression(receiverOpt);
            }

            // Dealing with the arguments is a bit tricky because they can be named out-of-order arguments;
            // we have to preserve both the source-code order of the side effects and the side effects
            // only being executed once.
            //
            // This is a subtly different problem than the problem faced by the conventional call
            // rewriter; with the conventional call rewriter we already know that the side effects
            // will only be executed once because the arguments are only being pushed on the stack once.
            // In a compound equality operator on an indexer the indices are placed on the stack twice.
            // That is to say, if you have:
            //
            // C().M(z : Z(), x : X(), y : Y())
            //
            // then we can rewrite that into
            //
            // tempc = C()
            // tempz = Z()
            // tempc.M(X(), Y(), tempz)
            //
            // See, we can optimize away two of the temporaries, for x and y. But we cannot optimize away any of the
            // temporaries in
            //
            // C().Collection[z : Z(), x : X(), y : Y()] += 1;
            //
            // because we have to ensure not just that Z() happens first, but in addition that X() and Y() are only
            // called once.  We have to generate this as
            //
            // tempc = C().Collection
            // tempz = Z()
            // tempx = X()
            // tempy = Y()
            // tempc[tempx, tempy, tempz] = tempc[tempx, tempy, tempz] + 1;
            //
            // Fortunately arguments to indexers are never ref or out, so we don't need to worry about that.
            // However, we can still do the optimization where constants are not stored in
            // temporaries; if we have
            //
            // C().Collection[z : 123, y : Y(), x : X()] += 1;
            //
            // Then we can generate that as
            //
            // tempc = C().Collection
            // tempx = X()
            // tempy = Y()
            // tempc[tempx, tempy, 123] = tempc[tempx, tempy, 123] + 1;

            ImmutableArray <BoundExpression> rewrittenArguments = VisitList(indexerAccess.Arguments);

            CSharpSyntaxNode         syntax           = indexerAccess.Syntax;
            PropertySymbol           indexer          = indexerAccess.Indexer;
            ImmutableArray <RefKind> argumentRefKinds = indexerAccess.ArgumentRefKindsOpt;
            bool expanded = indexerAccess.Expanded;
            ImmutableArray <int> argsToParamsOpt = indexerAccess.ArgsToParamsOpt;

            ImmutableArray <ParameterSymbol> parameters = indexer.Parameters;

            BoundExpression[] actualArguments = new BoundExpression[parameters.Length]; // The actual arguments that will be passed; one actual argument per formal parameter.
            ArrayBuilder <BoundAssignmentOperator> storesToTemps = ArrayBuilder <BoundAssignmentOperator> .GetInstance(rewrittenArguments.Length);

            ArrayBuilder <RefKind> refKinds = ArrayBuilder <RefKind> .GetInstance(parameters.Length, RefKind.None);

            // Step one: Store everything that is non-trivial into a temporary; record the
            // stores in storesToTemps and make the actual argument a reference to the temp.
            // Do not yet attempt to deal with params arrays or optional arguments.
            BuildStoresToTemps(expanded, argsToParamsOpt, argumentRefKinds, rewrittenArguments, actualArguments, refKinds, storesToTemps);

            // Step two: If we have a params array, build the array and fill in the argument.
            if (expanded)
            {
                BoundExpression         array = BuildParamsArray(syntax, indexer, argsToParamsOpt, rewrittenArguments, parameters, actualArguments[actualArguments.Length - 1]);
                BoundAssignmentOperator storeToTemp;
                var boundTemp = _factory.StoreToTemp(array, out storeToTemp);
                stores.Add(storeToTemp);
                temps.Add(boundTemp.LocalSymbol);
                actualArguments[actualArguments.Length - 1] = boundTemp;
            }

            // Step three: Now fill in the optional arguments. (Dev11 uses the
            // getter for optional arguments in compound assignments.)
            var getMethod = indexer.GetOwnOrInheritedGetMethod();

            Debug.Assert((object)getMethod != null);
            InsertMissingOptionalArguments(syntax, getMethod.Parameters, actualArguments);

            // For a call, step four would be to optimize away some of the temps.  However, we need them all to prevent
            // duplicate side-effects, so we'll skip that step.

            if (indexer.ContainingType.IsComImport)
            {
                RewriteArgumentsForComCall(parameters, actualArguments, refKinds, temps);
            }

            rewrittenArguments = actualArguments.AsImmutableOrNull();

            foreach (BoundAssignmentOperator tempAssignment in storesToTemps)
            {
                temps.Add(((BoundLocal)tempAssignment.Left).LocalSymbol);
                stores.Add(tempAssignment);
            }

            storesToTemps.Free();
            argumentRefKinds = GetRefKindsOrNull(refKinds);
            refKinds.Free();

            // 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 indexers.
            return(new BoundIndexerAccess(
                       syntax,
                       transformedReceiver,
                       indexer,
                       rewrittenArguments,
                       default(ImmutableArray <string>),
                       argumentRefKinds,
                       false,
                       default(ImmutableArray <int>),
                       indexerAccess.Type));
        }
Пример #11
0
        private static void CheckAccessorShape(MethodSymbol accessor, bool accessorIsGetMethod, PropertySymbol property, bool propertyIsIndexer, bool suppressAssociatedPropertyCheck)
        {
            Assert.NotNull(accessor);
            if (propertyIsIndexer)
            {
                if (!suppressAssociatedPropertyCheck)
                {
                    Assert.Same(property, accessor.AssociatedSymbol);
                }
            }
            else
            {
                Assert.Null(accessor.AssociatedSymbol);
                Assert.Equal(MethodKind.Ordinary, accessor.MethodKind);
            }

            if (accessorIsGetMethod)
            {
                Assert.Equal(propertyIsIndexer ? MethodKind.PropertyGet : MethodKind.Ordinary, accessor.MethodKind);

                Assert.Equal(property.Type, accessor.ReturnType);
                Assert.Equal(property.ParameterCount, accessor.ParameterCount);
            }
            else
            {
                Assert.Equal(propertyIsIndexer ? MethodKind.PropertySet : MethodKind.Ordinary, accessor.MethodKind);

                Assert.Equal(SpecialType.System_Void, accessor.ReturnType.SpecialType);
                Assert.Equal(property.Type, accessor.Parameters.Last().Type);
                Assert.Equal(property.ParameterCount + 1, accessor.ParameterCount);
            }

            // NOTE: won't check last param of setter - that was handled above.
            for (int i = 0; i < property.ParameterCount; i++)
            {
                Assert.Equal(property.Parameters[i].Type, accessor.Parameters[i].Type);
            }

            Assert.Equal(property.IsAbstract, accessor.IsAbstract);
            Assert.Equal(property.IsOverride, @accessor.IsOverride);
            Assert.Equal(property.IsVirtual, @accessor.IsVirtual);
            Assert.Equal(property.IsSealed, @accessor.IsSealed);
            Assert.Equal(property.IsExtern, @accessor.IsExtern);
        }
Пример #12
0
 private static void CheckNonIndexer(PropertySymbol property, bool expectGetter, bool expectSetter, string propertyDisplayString)
 {
     CheckParameterizedProperty(property, expectGetter, expectSetter, propertyDisplayString, false, true);
 }
Пример #13
0
 private static void CheckIndexer(PropertySymbol indexer, bool expectGetter, bool expectSetter, string indexerDisplayString, bool suppressAssociatedPropertyCheck = false)
 {
     CheckParameterizedProperty(indexer, expectGetter, expectSetter, indexerDisplayString, true, suppressAssociatedPropertyCheck);
 }
Пример #14
0
 public static FlatValue StaticProperty(PropertySymbol value)
 {
     return new FlatValue() { ValueType = FlatValueType.VT_StaticProperty, Object = value };
 }
Пример #15
0
        private BoundExpression MakeIndexerAccess(
            SyntaxNode syntax,
            BoundExpression rewrittenReceiver,
            PropertySymbol indexer,
            ImmutableArray <BoundExpression> rewrittenArguments,
            ImmutableArray <string> argumentNamesOpt,
            ImmutableArray <RefKind> argumentRefKindsOpt,
            bool expanded,
            ImmutableArray <int> argsToParamsOpt,
            TypeSymbol type,
            BoundIndexerAccess oldNodeOpt,
            bool isLeftOfAssignment)
        {
            // check for System.Array.[Length|LongLength] on a single dimensional array,
            // we have a special node for such cases.
            if (rewrittenReceiver != null && rewrittenReceiver.Type.IsArray() && !isLeftOfAssignment)
            {
                // NOTE: we are not interested in potential badness of Array.Length property.
                // If it is bad reference compare will not succeed.

                var specialIndexer = _compilation.GetSpecialTypeMember(SpecialMember.core_Array_T__item);

                if (ReferenceEquals(indexer.OriginalDefinition, specialIndexer))
                {
                    return(new BoundArrayAccess(syntax, rewrittenReceiver, rewrittenArguments[0], indexer.Type.TypeSymbol));
                }
            }


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

                return(oldNodeOpt != null?
                       oldNodeOpt.Update(rewrittenReceiver, indexer, rewrittenArguments, argumentNamesOpt, argumentRefKindsOpt, expanded, argsToParamsOpt, null, isLeftOfAssignment, type) :
                           new BoundIndexerAccess(syntax, rewrittenReceiver, indexer, rewrittenArguments, argumentNamesOpt, argumentRefKindsOpt, expanded, argsToParamsOpt, null, isLeftOfAssignment, type));
            }
            else
            {
                var getMethod = indexer.GetOwnOrInheritedGetMethod();
                Debug.Assert((object)getMethod != null);

                // We have already lowered each argument, but we may need some additional rewriting for the arguments,
                // such as generating a params array, re-ordering arguments based on argsToParamsOpt map, inserting arguments for optional parameters, etc.
                ImmutableArray <LocalSymbol> temps;
                rewrittenArguments = MakeArguments(
                    syntax,
                    rewrittenArguments,
                    indexer,
                    getMethod,
                    expanded,
                    argsToParamsOpt,
                    ref argumentRefKindsOpt,
                    out temps,
                    enableCallerInfo: ThreeState.True);

                BoundExpression call = MakePropertyGetAccess(syntax, rewrittenReceiver, indexer, rewrittenArguments, getMethod);

                if (temps.IsDefaultOrEmpty)
                {
                    return(call);
                }
                else
                {
                    return(new BoundSequence(
                               syntax,
                               temps,
                               ImmutableArray <BoundExpression> .Empty,
                               call,
                               type));
                }
            }
        }
 internal AnonymousTypeSpecializedPropertySymbol(SubstitutedNamedTypeSymbol containingType, PropertySymbol originalDefinition, AnonymousTypeField field)
     : base(containingType, originalDefinition)
 {
     this.locations = ReadOnlyArray<Location>.CreateFrom(field.Location);
 }
Пример #17
0
 public override void VisitProperty(PropertySymbol property)
 {
     Visit(property.GetMethod);
     Visit(property.SetMethod);
 }
Пример #18
0
 public override bool VisitProperty(PropertySymbol symbol)
 {
     return(AddIfUsesIsNullable(symbol, symbol.TypeWithAnnotations, inProgress: null) ||
            AddIfUsesIsNullable(symbol, symbol.Parameters, inProgress: null));
 }
        /// <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.Parameter:
            {
                Debug.Assert(!isRef || rewrittenLeft.GetRefKind() != RefKind.None);
                return(new BoundAssignmentOperator(
                           syntax,
                           rewrittenLeft,
                           rewrittenRight,
                           isRef,
                           type));
            }

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

            default:
            {
                Debug.Assert(!isRef);
                return(new BoundAssignmentOperator(
                           syntax,
                           rewrittenLeft,
                           rewrittenRight,
                           type));
            }
            }
        }
Пример #20
0
        /// <summary>
        /// Finds the IsCompleted property of an Awaiter type.
        /// </summary>
        /// <remarks>
        /// Spec 7.7.7.1:
        /// An Awaiter A has an accessible, readable instance property IsCompleted of type bool.
        /// </remarks>
        private bool GetIsCompletedProperty(TypeSymbol awaiterType, SyntaxNode node, TypeSymbol awaitedExpressionType, DiagnosticBag diagnostics, out PropertySymbol isCompletedProperty)
        {
            var receiver  = new BoundLiteral(node, ConstantValue.Null, awaiterType);
            var name      = WellKnownMemberNames.IsCompleted;
            var qualified = BindInstanceMemberAccess(node, node, receiver, name, 0, default(SeparatedSyntaxList <TypeSyntax>), default(ImmutableArray <TypeWithAnnotations>), invoked: false, indexed: false, diagnostics);

            if (qualified.HasAnyErrors)
            {
                isCompletedProperty = null;
                return(false);
            }

            if (qualified.Kind != BoundKind.PropertyAccess)
            {
                Error(diagnostics, ErrorCode.ERR_NoSuchMember, node, awaiterType, WellKnownMemberNames.IsCompleted);
                isCompletedProperty = null;
                return(false);
            }

            isCompletedProperty = ((BoundPropertyAccess)qualified).PropertySymbol;
            if (isCompletedProperty.IsWriteOnly)
            {
                Error(diagnostics, ErrorCode.ERR_PropertyLacksGet, node, isCompletedProperty);
                isCompletedProperty = null;
                return(false);
            }

            if (isCompletedProperty.Type.SpecialType != SpecialType.System_Boolean)
            {
                Error(diagnostics, ErrorCode.ERR_BadAwaiterPattern, node, awaiterType, awaitedExpressionType);
                isCompletedProperty = null;
                return(false);
            }

            return(true);
        }
        private BoundExpression MakePropertyAssignment(
            SyntaxNode syntax,
            BoundExpression rewrittenReceiver,
            PropertySymbol property,
            ImmutableArray <BoundExpression> rewrittenArguments,
            ImmutableArray <RefKind> argumentRefKindsOpt,
            bool expanded,
            ImmutableArray <int> argsToParamsOpt,
            BoundExpression rewrittenRight,
            TypeSymbol type,
            bool used)
        {
            // Rewrite property assignment into call to setter.
            var setMethod = property.GetOwnOrInheritedSetMethod();

            if ((object)setMethod == null)
            {
                Debug.Assert((property as SourcePropertySymbol)?.IsAutoProperty == true,
                             "only autoproperties can be assignable without having setters");

                var backingField = (property as SourcePropertySymbol).BackingField;
                return(_factory.AssignmentExpression(
                           _factory.Field(rewrittenReceiver, backingField),
                           rewrittenRight));
            }

#if XSHARP
            if (property is XsVariableSymbol xsvar)
            {
                return(MemVarFieldAssign(syntax, xsvar, rewrittenRight));
            }
#endif
            // We have already lowered each argument, but we may need some additional rewriting for the arguments,
            // such as generating a params array, re-ordering arguments based on argsToParamsOpt map, inserting arguments for optional parameters, etc.
            ImmutableArray <LocalSymbol> argTemps;
            rewrittenArguments = MakeArguments(syntax, rewrittenArguments, property, setMethod, expanded, argsToParamsOpt, ref argumentRefKindsOpt, out argTemps, enableCallerInfo: ThreeState.True);

            if (used)
            {
                // Save expression value to a temporary before calling the
                // setter, and restore the temporary after the setter, so the
                // assignment can be used as an embedded expression.
                TypeSymbol exprType = rewrittenRight.Type;

                LocalSymbol rhsTemp = _factory.SynthesizedLocal(exprType);

                BoundExpression boundRhs = new BoundLocal(syntax, rhsTemp, null, exprType);

                BoundExpression rhsAssignment = new BoundAssignmentOperator(
                    syntax,
                    boundRhs,
                    rewrittenRight,
                    exprType);

                BoundExpression setterCall = BoundCall.Synthesized(
                    syntax,
                    rewrittenReceiver,
                    setMethod,
#if XSHARP
                    setMethod.IsAccessor() ? AppendToPossibleNull(rewrittenArguments, rhsAssignment) :
                    rewrittenArguments.NullToEmpty().Insert(0, rhsAssignment));
#else
                    AppendToPossibleNull(rewrittenArguments, rhsAssignment));
#endif

                return(new BoundSequence(
                           syntax,
                           AppendToPossibleNull(argTemps, rhsTemp),
                           ImmutableArray.Create(setterCall),
                           boundRhs,
                           type));
            }
            else
            {
                BoundCall setterCall = BoundCall.Synthesized(
                    syntax,
                    rewrittenReceiver,
                    setMethod,
#if XSHARP
                    setMethod.IsAccessor() ? AppendToPossibleNull(rewrittenArguments, rewrittenRight) :
                    rewrittenArguments.NullToEmpty().Insert(0, rewrittenRight));
#else
                    AppendToPossibleNull(rewrittenArguments, rewrittenRight));
#endif

                if (argTemps.IsDefaultOrEmpty)
                {
                    return(setterCall);
                }
                else
                {
                    return(new BoundSequence(
                               syntax,
                               argTemps,
                               ImmutableArray <BoundExpression> .Empty,
                               setterCall,
                               setMethod.ReturnType));
                }
            }
        }
Пример #22
0
 public virtual void VisitProperty(PropertySymbol symbol)
 {
     DefaultVisit(symbol);
 }
Пример #23
0
 public object GetPropertyValue(PropertySymbol sym)
     {
     return this.GetPropertyValue(PropertySymbol.Descopify(sym.Name));
     }
Пример #24
0
 private bool ArePropertiesEqual(PropertySymbol property, PropertySymbol other)
 {
     Debug.Assert(NameComparer.Equals(property.Name, other.Name));
     return(this.comparer.Equals(property.Type, other.Type) &&
            property.Parameters.SequenceEqual(other.Parameters, AreParametersEqual));
 }
            private static bool TryGetWellKnownPropertyAsMember(SyntheticBoundNodeFactory F, WellKnownMember wellKnownProperty, NamedTypeSymbol containingType, out PropertySymbol propertySymbol)
            {
                propertySymbol = F.WellKnownMember(wellKnownProperty) as PropertySymbol;
                if ((object)propertySymbol == null)
                {
                    return(false);
                }

                propertySymbol = propertySymbol.AsMember(containingType);
                return(true);
            }
Пример #26
0
 public override Symbol VisitProperty(PropertySymbol symbol)
 {
     return(this.VisitNamedTypeMember(symbol, ArePropertiesEqual));
 }
Пример #27
0
 internal static InitializerSemanticModel Create(SyntaxTreeSemanticModel containingSemanticModel, CSharpSyntaxNode syntax, PropertySymbol propertySymbol, Binder rootBinder)
 {
     Debug.Assert(containingSemanticModel != null);
     Debug.Assert(syntax.IsKind(SyntaxKind.PropertyDeclaration));
     return(new InitializerSemanticModel(syntax, propertySymbol, rootBinder, containingSemanticModel));
 }
        protected void ErrAppendMethod(MethodSymbol meth, SubstContext pctx, bool fArgs)
        {
            if (meth.IsExpImpl() && meth.swtSlot)
            {
                ErrAppendParentSym(meth, pctx);

                // Get the type args from the explicit impl type and substitute using pctx (if there is one).
                SubstContext ctx = new SubstContext(GetTypeManager().SubstType(meth.swtSlot.GetType(), pctx).AsAggregateType());
                ErrAppendSym(meth.swtSlot.Sym, ctx, fArgs);

                // args already added
                return;
            }

            if (meth.isPropertyAccessor())
            {
                PropertySymbol prop = meth.getProperty();

                // this includes the parent class
                ErrAppendSym(prop, pctx);

                // add accessor name
                if (prop.methGet == meth)
                {
                    ErrAppendString(".get");
                }
                else
                {
                    Debug.Assert(meth == prop.methSet);
                    ErrAppendString(".set");
                }

                // args already added
                return;
            }

            if (meth.isEventAccessor())
            {
                EventSymbol @event = meth.getEvent();

                // this includes the parent class
                ErrAppendSym(@event, pctx);

                // add accessor name
                if (@event.methAdd == meth)
                {
                    ErrAppendString(".add");
                }
                else
                {
                    Debug.Assert(meth == @event.methRemove);
                    ErrAppendString(".remove");
                }

                // args already added
                return;
            }

            TypeArray replacementTypeArray = null;

            ErrAppendMethodParentSym(meth, pctx, out replacementTypeArray);
            if (meth.IsConstructor())
            {
                // Use the name of the parent class instead of the name "<ctor>".
                ErrAppendName(meth.getClass().name);
            }
            else if (meth.IsDestructor())
            {
                // Use the name of the parent class instead of the name "Finalize".
                ErrAppendChar('~');
                ErrAppendName(meth.getClass().name);
            }
            else if (meth.isConversionOperator())
            {
                // implicit/explicit
                ErrAppendString(meth.isImplicit() ? "implicit" : "explicit");
                ErrAppendString(" operator ");

                // destination type name
                ErrAppendType(meth.RetType, pctx);
            }
            else if (meth.isOperator)
            {
                // handle user defined operators
                // map from CLS predefined names to "operator <X>"
                ErrAppendString("operator ");

                //
                // <UNDONE>UNDONE: This is kinda slow, but the alternative is to add bits to methsym.</UNDONE>
                //
                string       operatorName;
                OperatorKind op = Operators.OperatorOfMethodName(GetNameManager(), meth.name);
                if (Operators.HasDisplayName(op))
                {
                    operatorName = Operators.GetDisplayName(op);
                }
                else
                {
                    //
                    // either equals or compare
                    //
                    if (meth.name == GetNameManager().GetPredefName(PredefinedName.PN_OPEQUALS))
                    {
                        operatorName = "equals";
                    }
                    else
                    {
                        Debug.Assert(meth.name == GetNameManager().GetPredefName(PredefinedName.PN_OPCOMPARE));
                        operatorName = "compare";
                    }
                }
                ErrAppendString(operatorName);
            }
            else if (meth.IsExpImpl())
            {
                if (meth.errExpImpl != null)
                {
                    ErrAppendType(meth.errExpImpl, pctx, fArgs);
                }
            }
            else
            {
                // regular method
                ErrAppendName(meth.name);
            }

            if (null == replacementTypeArray)
            {
                ErrAppendTypeParameters(meth.typeVars, pctx, false);
            }

            if (fArgs)
            {
                // append argument types
                ErrAppendChar('(');

                if (!meth.computeCurrentBogusState())
                {
                    ErrAppendParamList(GetTypeManager().SubstTypeArray(meth.Params, pctx), meth.isVarargs, meth.isParamArray);
                }

                ErrAppendChar(')');
            }
        }
        public override void Emit(EmitContext context)
        {
            var blockScope = context.OpenBlockScope();

            TypeSymbol intType       = context.GetTypeSymbol(SpecialType.System_Int32);
            TypeSymbol transformType = context.GetTypeSymbol(typeof(Transform));

            MethodSymbol   getChildMethod = transformType.GetMember <MethodSymbol>("GetChild", context);
            PropertySymbol lengthProperty = transformType.GetMember <PropertySymbol>("childCount", context);

            Value iteratorValue = context.EmitValue(IteratorSource);

            iteratorValue.MarkUsedRecursively();
            var iteratorAccess = BoundAccessExpression.BindAccess(iteratorValue);

            Value arraySize = context.CreateInternalValue(intType);

            arraySize.MarkUsedRecursively();

            BoundAccessExpression getLength = BoundAccessExpression.BindAccess(context, SyntaxNode, lengthProperty, iteratorAccess);

            context.EmitValueAssignment(arraySize, getLength);

            // Declare and reset incrementor value
            Value incrementorValue = context.CreateInternalValue(intType);

            incrementorValue.MarkUsedRecursively();
            context.EmitValueAssignment(incrementorValue, BoundAccessExpression.BindAccess(context.GetConstantValue(intType, 0)));

            JumpLabel loopLabel = context.Module.CreateLabel();

            context.Module.LabelJump(loopLabel);

            var incrementorAccess = BoundAccessExpression.BindAccess(incrementorValue);

            BoundExpression increment = new BoundInvocationExpression.BoundPrefixOperatorExpression(context, SyntaxNode,
                                                                                                    incrementorAccess, new ExternSynthesizedOperatorSymbol(BuiltinOperatorType.Addition, intType, context));

            var lengthCheck = BoundInvocationExpression.CreateBoundInvocation(context, SyntaxNode,
                                                                              new ExternSynthesizedOperatorSymbol(BuiltinOperatorType.LessThan, intType, context), null,
                                                                              new BoundExpression[]
            {
                incrementorAccess,
                BoundAccessExpression.BindAccess(arraySize)
            });

            JumpLabel exitLoopLabel = context.PushBreakLabel();
            JumpLabel continueLabel = context.PushContinueLabel();

            Value lengthCheckResult = context.EmitValue(lengthCheck);

            context.Module.AddJumpIfFalse(exitLoopLabel, lengthCheckResult);

            context.EmitValueAssignment(context.GetUserValue(ValueSymbol),
                                        BoundInvocationExpression.CreateBoundInvocation(context, SyntaxNode, getChildMethod, iteratorAccess,
                                                                                        new BoundExpression[] { incrementorAccess }));

            context.Emit(BodyStatement);

            context.Module.LabelJump(continueLabel);

            context.Emit(increment);

            context.Module.AddJump(loopLabel);

            context.Module.LabelJump(exitLoopLabel);

            context.PopBreakLabel();
            context.PopContinueLabel();

            blockScope.Dispose();
        }
Пример #30
0
 public virtual TResult VisitProperty(PropertySymbol symbol)
 {
     return(DefaultVisit(symbol));
 }
Пример #31
0
        private void GenerateEnumerableImplementation(ref BoundExpression managedThreadId)
        {
            var IEnumerable_GetEnumerator = F.SpecialMethod(SpecialMember.System_Collections_IEnumerable__GetEnumerator);

            var IEnumerableOfElementType = F.SpecialType(SpecialType.System_Collections_Generic_IEnumerable_T).Construct(elementType);
            var IEnumerableOfElementType_GetEnumerator = F.SpecialMethod(SpecialMember.System_Collections_Generic_IEnumerable_T__GetEnumerator).AsMember(IEnumerableOfElementType);

            // generate the code for GetEnumerator()
            // .NET Core has removed the Thread class. We can the managed thread id by making a call to
            // Environment.CurrentManagedThreadId. If that method is not present (pre 4.5) fall back to the old behavior.
            //    IEnumerable<elementType> result;
            //    if (this.initialThreadId == Thread.CurrentThread.ManagedThreadId && this.state == -2)
            //    {
            //        this.state = 0;
            //        result = this;
            //    }
            //    else
            //    {
            //        result = new Ints0_Impl(0);
            //    }
            //    result.parameter = this.parameterProxy; // copy all of the parameter proxies

            // Add IEnumerator<elementType> IEnumerable<elementType>.GetEnumerator()

            // The implementation doesn't depend on the method body of the iterator method.
            // Only on it's parameters and staticness.
            var getEnumeratorGeneric = OpenMethodImplementation(
                IEnumerableOfElementType_GetEnumerator,
                debuggerHidden: true,
                generateDebugInfo: false,
                hasMethodBodyDependency: false);

            var bodyBuilder = ArrayBuilder <BoundStatement> .GetInstance();

            var            resultVariable = F.SynthesizedLocal(stateMachineType, null);                                               // iteratorClass result;
            BoundStatement makeIterator   = F.Assignment(F.Local(resultVariable), F.New(stateMachineType.Constructor, F.Literal(0))); // result = new IteratorClass(0)

            var thisInitialized = F.GenerateLabel("thisInitialized");

            if ((object)initialThreadIdField != null)
            {
                MethodSymbol currentManagedThreadIdMethod = null;

                PropertySymbol currentManagedThreadIdProperty = F.WellKnownMember(WellKnownMember.System_Environment__CurrentManagedThreadId, isOptional: true) as PropertySymbol;

                if ((object)currentManagedThreadIdProperty != null)
                {
                    currentManagedThreadIdMethod = currentManagedThreadIdProperty.GetMethod;
                }

                if ((object)currentManagedThreadIdMethod != null)
                {
                    managedThreadId = F.Call(null, currentManagedThreadIdMethod);
                }
                else
                {
                    managedThreadId = F.Property(F.Property(WellKnownMember.System_Threading_Thread__CurrentThread), WellKnownMember.System_Threading_Thread__ManagedThreadId);
                }

                makeIterator = F.If(
                    condition: F.LogicalAnd(                                   // if (this.state == -2 && this.initialThreadId == Thread.CurrentThread.ManagedThreadId)
                        F.IntEqual(F.Field(F.This(), stateField), F.Literal(StateMachineStates.FinishedStateMachine)),
                        F.IntEqual(F.Field(F.This(), initialThreadIdField), managedThreadId)),
                    thenClause: F.Block(                                                                             // then
                        F.Assignment(F.Field(F.This(), stateField), F.Literal(StateMachineStates.FirstUnusedState)), // this.state = 0;
                        F.Assignment(F.Local(resultVariable), F.This()),                                             // result = this;
                        method.IsStatic || method.ThisParameter.Type.IsReferenceType ?                               // if this is a reference type, no need to copy it since it is not assignable
                        F.Goto(thisInitialized) :                                                                    // goto thisInitialized
                        (BoundStatement)F.Block()),
                    elseClauseOpt:
                    makeIterator     // else result = new IteratorClass(0)
                    );
            }

            bodyBuilder.Add(makeIterator);

            // Initialize all the parameter copies
            var copySrc  = initialParameters;
            var copyDest = nonReusableLocalProxies;

            if (!method.IsStatic)
            {
                // starting with "this"
                CapturedSymbolReplacement proxy;
                if (copyDest.TryGetValue(method.ThisParameter, out proxy))
                {
                    bodyBuilder.Add(
                        F.Assignment(
                            proxy.Replacement(F.Syntax, stateMachineType => F.Local(resultVariable)),
                            copySrc[method.ThisParameter].Replacement(F.Syntax, stateMachineType => F.This())));
                }
            }

            bodyBuilder.Add(F.Label(thisInitialized));

            foreach (var parameter in method.Parameters)
            {
                CapturedSymbolReplacement proxy;
                if (copyDest.TryGetValue(parameter, out proxy))
                {
                    bodyBuilder.Add(
                        F.Assignment(
                            proxy.Replacement(F.Syntax, stateMachineType => F.Local(resultVariable)),
                            copySrc[parameter].Replacement(F.Syntax, stateMachineType => F.This())));
                }
            }

            bodyBuilder.Add(F.Return(F.Local(resultVariable)));
            F.CloseMethod(F.Block(ImmutableArray.Create(resultVariable), bodyBuilder.ToImmutableAndFree()));

            // Generate IEnumerable.GetEnumerator
            var getEnumerator = OpenMethodImplementation(IEnumerable_GetEnumerator, debuggerHidden: true, generateDebugInfo: false);

            F.CloseMethod(F.Return(F.Call(F.This(), getEnumeratorGeneric)));
        }
Пример #32
0
        public FlatOperand Resolve(PropertySymbol property, FlatOperand fop_type, FlatOperand into_lvalue, List<FlatStatement> instructions)
        {
            string property_name = property.Name;

            if (into_lvalue == null)
            {
                FlatOperand register_fop = AllocateRegister("");
                into_lvalue = register_fop.GetLValue(this, instructions);
            }

            FlatOperand fop_methodname = FlatOperand.Immediate(FlatValue.String(property_name));

            if (property.IsStatic)
            {
                instructions.Add(FlatStatement.RESOLVESTATICPROPERTY(into_lvalue, fop_type, fop_methodname));
                return into_lvalue.AsRValue(FlatValue.StaticProperty(property));
            }

            instructions.Add(FlatStatement.RESOLVEPROPERTY(into_lvalue, fop_type, fop_methodname));
            return into_lvalue.AsRValue(FlatValue.Property(property));
        }
Пример #33
0
 internal AwaitableInfo(MethodSymbol getAwaiterMethod, PropertySymbol isCompletedProperty, MethodSymbol getResultMethod)
 {
     this.GetAwaiter  = getAwaiterMethod;
     this.IsCompleted = isCompletedProperty;
     this.GetResult   = getResultMethod;
 }
Пример #34
0
    PropertySymbol CreatePropertyDefinition(string unscopedName, IType type, bool fDom, bool fStr, bool inheritedByStrand, bool inheritedByComplement, bool inheritedBySubset, bool builtinSequenceProperty)
    // ^(PropertyDef ^(Name ID) typeSpec)
        {
        string scopedName = PropertySymbol.ScopeNameFor(unscopedName);

        PropertySymbol symPropDef = new PropertySymbol(scopedName, type, 
            inheritedByStrand:       inheritedByStrand, 
            inheritedByComplement:   inheritedByComplement, 
            inheritedBySubset:       inheritedBySubset,
            builtinSequenceProperty: builtinSequenceProperty
            );
        NadirAST nodePropDef = new NadirAST(NadirParser.PropertyDef);
        NadirAST nodeType = CreateBuiltinTypeNode(type);
        //
        nodePropDef.AddChild(CreateNameNode(scopedName));
        nodePropDef.AddChild(nodeType);
        //
        NadirASTDefineSymbols.LinkSymbolWithDefinition(nodePropDef, symPropDef);
        NadirASTDefineTypes.SetResolvedTypeOfDefinition(nodePropDef, type);
        //
        if (fDom) this.DefinedDomainProperties[unscopedName] = symPropDef;
        if (fStr) this.DefinedStrandProperties[unscopedName] = symPropDef;
        //
        return symPropDef;
        }
        /// <summary>
        /// Adds a synthedized property to the class.
        /// </summary>
        public void AddProperty(TypeSymbol container, PropertySymbol property)
        {
            Contract.ThrowIfNull(property);

            AddMember(container, property);
        }
 private void AddGetOrSet(PropertySymbol property, MethodSymbol method, SyntaxKind keyword, ArrayBuilder<SymbolDescriptionPart> builder)
 {
     if (method != null)
     {
         AddSpace(builder);
         if (method.DeclaredAccessibility != property.DeclaredAccessibility)
         {
             AddAccessibilityIfRequired(method, builder);
         }
         AddKeyword(keyword, builder);
         AddPunctuation(SyntaxKind.SemicolonToken, builder);
     }
 }
Пример #37
0
 public override object VisitProperty(PropertySymbol symbol, object argument)
 {
     throw ExceptionUtilities.Unreachable;
 }