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); }
/// <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)); } } }
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)); }
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); }
// 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; }
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)); }
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); }
private static void CheckNonIndexer(PropertySymbol property, bool expectGetter, bool expectSetter, string propertyDisplayString) { CheckParameterizedProperty(property, expectGetter, expectSetter, propertyDisplayString, false, true); }
private static void CheckIndexer(PropertySymbol indexer, bool expectGetter, bool expectSetter, string indexerDisplayString, bool suppressAssociatedPropertyCheck = false) { CheckParameterizedProperty(indexer, expectGetter, expectSetter, indexerDisplayString, true, suppressAssociatedPropertyCheck); }
public static FlatValue StaticProperty(PropertySymbol value) { return new FlatValue() { ValueType = FlatValueType.VT_StaticProperty, Object = value }; }
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); }
public override void VisitProperty(PropertySymbol property) { Visit(property.GetMethod); Visit(property.SetMethod); }
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)); } } }
/// <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)); } } }
public virtual void VisitProperty(PropertySymbol symbol) { DefaultVisit(symbol); }
public object GetPropertyValue(PropertySymbol sym) { return this.GetPropertyValue(PropertySymbol.Descopify(sym.Name)); }
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); }
public override Symbol VisitProperty(PropertySymbol symbol) { return(this.VisitNamedTypeMember(symbol, ArePropertiesEqual)); }
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(); }
public virtual TResult VisitProperty(PropertySymbol symbol) { return(DefaultVisit(symbol)); }
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))); }
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)); }
internal AwaitableInfo(MethodSymbol getAwaiterMethod, PropertySymbol isCompletedProperty, MethodSymbol getResultMethod) { this.GetAwaiter = getAwaiterMethod; this.IsCompleted = isCompletedProperty; this.GetResult = getResultMethod; }
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); } }
public override object VisitProperty(PropertySymbol symbol, object argument) { throw ExceptionUtilities.Unreachable; }