private void UnwrapCollectionExpressionIfNullable(ref BoundExpression collectionExpr, DiagnosticBag diagnostics) { TypeSymbol collectionExprType = collectionExpr.Type; // If collectionExprType is a nullable type, then use the underlying type and take the value (i.e. .Value) of collectionExpr. // This behavior is not spec'd, but it's what Dev10 does. if ((object)collectionExprType != null && collectionExprType.IsNullableType()) { CSharpSyntaxNode exprSyntax = collectionExpr.Syntax; MethodSymbol nullableValueGetter = (MethodSymbol)GetSpecialTypeMember(SpecialMember.System_Nullable_T_get_Value, diagnostics, exprSyntax); if ((object)nullableValueGetter != null) { nullableValueGetter = nullableValueGetter.AsMember((NamedTypeSymbol)collectionExprType); // Synthesized call, because we don't want to modify the type in the SemanticModel. collectionExpr = BoundCall.Synthesized( syntax: exprSyntax, receiverOpt: collectionExpr, method: nullableValueGetter); } else { collectionExpr = new BoundBadExpression( exprSyntax, LookupResultKind.Empty, ImmutableArray <Symbol> .Empty, ImmutableArray.Create <BoundNode>(collectionExpr), collectionExprType.GetNullableUnderlyingType()) { WasCompilerGenerated = true }; // Don't affect the type in the SemanticModel. } } }
private static bool TryGetWellKnownMethodAsMember(SyntheticBoundNodeFactory F, WellKnownMember wellKnownMethod, NamedTypeSymbol containingType, out MethodSymbol methodSymbol) { methodSymbol = F.WellKnownMember(wellKnownMethod) as MethodSymbol; if ((object)methodSymbol == null) { return(false); } methodSymbol = methodSymbol.AsMember(containingType); return(true); }
internal EEMethodSymbol( EENamedTypeSymbol container, string name, Location location, MethodSymbol sourceMethod, ImmutableArray <LocalSymbol> sourceLocals, ImmutableArray <LocalSymbol> sourceLocalsForBinding, ImmutableDictionary <string, DisplayClassVariable> sourceDisplayClassVariables, GenerateMethodBody generateMethodBody) { Debug.Assert(sourceMethod.IsDefinition); Debug.Assert(sourceMethod.ContainingSymbol == container.SubstitutedSourceType.OriginalDefinition); Debug.Assert(sourceLocals.All(l => l.ContainingSymbol == sourceMethod)); _container = container; _name = name; _locations = ImmutableArray.Create(location); // What we want is to map all original type parameters to the corresponding new type parameters // (since the old ones have the wrong owners). Unfortunately, we have a circular dependency: // 1) Each new type parameter requires the entire map in order to be able to construct its constraint list. // 2) The map cannot be constructed until all new type parameters exist. // Our solution is to pass each new type parameter a lazy reference to the type map. We then // initialize the map as soon as the new type parameters are available - and before they are // handed out - so that there is never a period where they can require the type map and find // it uninitialized. var sourceMethodTypeParameters = sourceMethod.TypeParameters; var allSourceTypeParameters = container.SourceTypeParameters.Concat(sourceMethodTypeParameters); var getTypeMap = new Func <TypeMap>(() => this.TypeMap); _typeParameters = sourceMethodTypeParameters.SelectAsArray( (tp, i, arg) => (TypeParameterSymbol) new EETypeParameterSymbol(this, tp, i, getTypeMap), (object)null); _allTypeParameters = container.TypeParameters.Concat(_typeParameters); this.TypeMap = new TypeMap(allSourceTypeParameters, _allTypeParameters); EENamedTypeSymbol.VerifyTypeParameters(this, _typeParameters); var substitutedSourceType = container.SubstitutedSourceType; this.SubstitutedSourceMethod = sourceMethod.AsMember(substitutedSourceType); if (sourceMethod.Arity > 0) { this.SubstitutedSourceMethod = this.SubstitutedSourceMethod.Construct(_typeParameters.As <TypeSymbol>()); } TypeParameterChecker.Check(this.SubstitutedSourceMethod, _allTypeParameters); // Create a map from original parameter to target parameter. var parameterBuilder = ArrayBuilder <ParameterSymbol> .GetInstance(); var substitutedSourceThisParameter = this.SubstitutedSourceMethod.ThisParameter; var substitutedSourceHasThisParameter = (object)substitutedSourceThisParameter != null; if (substitutedSourceHasThisParameter) { _thisParameter = MakeParameterSymbol(0, GeneratedNames.ThisProxyFieldName(), substitutedSourceThisParameter); Debug.Assert(_thisParameter.Type == this.SubstitutedSourceMethod.ContainingType); parameterBuilder.Add(_thisParameter); } var ordinalOffset = (substitutedSourceHasThisParameter ? 1 : 0); foreach (var substitutedSourceParameter in this.SubstitutedSourceMethod.Parameters) { var ordinal = substitutedSourceParameter.Ordinal + ordinalOffset; Debug.Assert(ordinal == parameterBuilder.Count); var parameter = MakeParameterSymbol(ordinal, substitutedSourceParameter.Name, substitutedSourceParameter); parameterBuilder.Add(parameter); } _parameters = parameterBuilder.ToImmutableAndFree(); var localsBuilder = ArrayBuilder <LocalSymbol> .GetInstance(); var localsMap = PooledDictionary <LocalSymbol, LocalSymbol> .GetInstance(); foreach (var sourceLocal in sourceLocals) { var local = sourceLocal.ToOtherMethod(this, this.TypeMap); localsMap.Add(sourceLocal, local); localsBuilder.Add(local); } this.Locals = localsBuilder.ToImmutableAndFree(); localsBuilder = ArrayBuilder <LocalSymbol> .GetInstance(); foreach (var sourceLocal in sourceLocalsForBinding) { LocalSymbol local; if (!localsMap.TryGetValue(sourceLocal, out local)) { local = sourceLocal.ToOtherMethod(this, this.TypeMap); localsMap.Add(sourceLocal, local); } localsBuilder.Add(local); } this.LocalsForBinding = localsBuilder.ToImmutableAndFree(); // Create a map from variable name to display class field. var displayClassVariables = PooledDictionary <string, DisplayClassVariable> .GetInstance(); foreach (var pair in sourceDisplayClassVariables) { var variable = pair.Value; var oldDisplayClassInstance = variable.DisplayClassInstance; // Note: we don't call ToOtherMethod in the local case because doing so would produce // a new LocalSymbol that would not be ReferenceEquals to the one in this.LocalsForBinding. var oldDisplayClassInstanceFromLocal = oldDisplayClassInstance as DisplayClassInstanceFromLocal; var newDisplayClassInstance = (oldDisplayClassInstanceFromLocal == null) ? oldDisplayClassInstance.ToOtherMethod(this, this.TypeMap) : new DisplayClassInstanceFromLocal((EELocalSymbol)localsMap[oldDisplayClassInstanceFromLocal.Local]); variable = variable.SubstituteFields(newDisplayClassInstance, this.TypeMap); displayClassVariables.Add(pair.Key, variable); } _displayClassVariables = displayClassVariables.ToImmutableDictionary(); displayClassVariables.Free(); localsMap.Free(); _generateMethodBody = generateMethodBody; }
/// <summary> /// Generate a thread-safe accessor for a WinRT field-like event. /// /// Add: /// return EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddEventHandler(value); /// /// Remove: /// EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).RemoveEventHandler(value); /// </summary> internal static BoundBlock ConstructFieldLikeEventAccessorBody_WinRT(SourceEventSymbol eventSymbol, bool isAddMethod, CSharpCompilation compilation, DiagnosticBag diagnostics) { CSharpSyntaxNode syntax = eventSymbol.CSharpSyntaxNode; MethodSymbol accessor = isAddMethod ? eventSymbol.AddMethod : eventSymbol.RemoveMethod; Debug.Assert((object)accessor != null); FieldSymbol field = eventSymbol.AssociatedField; Debug.Assert((object)field != null); NamedTypeSymbol fieldType = (NamedTypeSymbol)field.Type; Debug.Assert(fieldType.Name == "EventRegistrationTokenTable"); MethodSymbol getOrCreateMethod = (MethodSymbol)Binder.GetWellKnownTypeMember( compilation, WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__GetOrCreateEventRegistrationTokenTable, diagnostics, syntax: syntax); if ((object)getOrCreateMethod == null) { Debug.Assert(diagnostics.HasAnyErrors()); return(null); } getOrCreateMethod = getOrCreateMethod.AsMember(fieldType); WellKnownMember processHandlerMember = isAddMethod ? WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__AddEventHandler : WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__RemoveEventHandler; MethodSymbol processHandlerMethod = (MethodSymbol)Binder.GetWellKnownTypeMember( compilation, processHandlerMember, diagnostics, syntax: syntax); if ((object)processHandlerMethod == null) { Debug.Assert(diagnostics.HasAnyErrors()); return(null); } processHandlerMethod = processHandlerMethod.AsMember(fieldType); // _tokenTable BoundFieldAccess fieldAccess = new BoundFieldAccess( syntax, field.IsStatic ? null : new BoundThisReference(syntax, accessor.ThisParameter.Type), field, constantValueOpt: null) { WasCompilerGenerated = true }; // EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable) BoundCall getOrCreateCall = BoundCall.Synthesized( syntax, receiverOpt: null, method: getOrCreateMethod, arg0: fieldAccess); // value BoundParameter parameterAccess = new BoundParameter( syntax, accessor.Parameters.Single()); // EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddHandler(value) // or RemoveHandler BoundCall processHandlerCall = BoundCall.Synthesized( syntax, receiverOpt: getOrCreateCall, method: processHandlerMethod, arg0: parameterAccess); if (isAddMethod) { // { // return EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddHandler(value); // } BoundStatement returnStatement = BoundReturnStatement.Synthesized(syntax, processHandlerCall); return(BoundBlock.SynthesizedNoLocals(syntax, returnStatement)); } else { // { // EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).RemoveHandler(value); // return; // } BoundStatement callStatement = new BoundExpressionStatement(syntax, processHandlerCall); BoundStatement returnStatement = new BoundReturnStatement(syntax, expressionOpt: null); return(BoundBlock.SynthesizedNoLocals(syntax, callStatement, returnStatement)); } }
internal LoweredDynamicOperation MakeDynamicOperation( BoundExpression binderConstruction, BoundExpression loweredReceiver, RefKind receiverRefKind, ImmutableArray <BoundExpression> loweredArguments, ImmutableArray <RefKind> refKinds, BoundExpression loweredRight, TypeSymbol resultType) { Debug.Assert(!loweredArguments.IsDefault); // get well-known types and members we need: NamedTypeSymbol delegateTypeOverMethodTypeParameters = GetDelegateType(loweredReceiver, receiverRefKind, loweredArguments, refKinds, loweredRight, resultType); NamedTypeSymbol callSiteTypeGeneric = _factory.WellKnownType(WellKnownType.core_runtime_compiler_CallSite_T); MethodSymbol callSiteFactoryGeneric = _factory.WellKnownMethod(WellKnownMember.System_Runtime_CompilerServices_CallSite_T__Create); FieldSymbol callSiteTargetFieldGeneric = (FieldSymbol)_factory.WellKnownMember(WellKnownMember.System_Runtime_CompilerServices_CallSite_T__Target); MethodSymbol delegateInvoke; if (binderConstruction == null || (object)delegateTypeOverMethodTypeParameters == null || delegateTypeOverMethodTypeParameters.IsErrorType() || (object)(delegateInvoke = delegateTypeOverMethodTypeParameters.DelegateInvokeMethod) == null || callSiteTypeGeneric.IsErrorType() || (object)callSiteFactoryGeneric == null || (object)callSiteTargetFieldGeneric == null) { // CS1969: One or more types required to compile a dynamic expression cannot be found. // Dev11 reports it with source location for each dynamic operation, which results in many error messages. // The diagnostic that names the specific missing type or member has already been reported. _factory.Diagnostics.Add(ErrorCode.ERR_DynamicRequiredTypesMissing, NoLocation.Singleton); return(LoweredDynamicOperation.Bad(loweredReceiver, loweredArguments, loweredRight, resultType)); } if ((object)_currentDynamicCallSiteContainer == null) { _currentDynamicCallSiteContainer = CreateCallSiteContainer(_factory, _methodOrdinal); } var containerDef = (SynthesizedContainer)_currentDynamicCallSiteContainer.OriginalDefinition; var methodToContainerTypeParametersMap = containerDef.TypeMap; ImmutableArray <LocalSymbol> temps = MakeTempsForDiscardArguments(ref loweredArguments); var callSiteType = callSiteTypeGeneric.Construct(new[] { delegateTypeOverMethodTypeParameters }); var callSiteFactoryMethod = callSiteFactoryGeneric.AsMember(callSiteType); var callSiteTargetField = callSiteTargetFieldGeneric.AsMember(callSiteType); var callSiteField = DefineCallSiteStorageSymbol(containerDef, delegateTypeOverMethodTypeParameters, methodToContainerTypeParametersMap); var callSiteFieldAccess = _factory.Field(null, callSiteField); var callSiteArguments = GetCallSiteArguments(callSiteFieldAccess, loweredReceiver, loweredArguments, loweredRight); var nullCallSite = _factory.Null(callSiteField.Type.TypeSymbol); var siteInitialization = _factory.Conditional( _factory.ObjectEqual(callSiteFieldAccess, nullCallSite), _factory.AssignmentExpression(callSiteFieldAccess, _factory.Call(null, callSiteFactoryMethod, binderConstruction)), nullCallSite, callSiteField.Type.TypeSymbol); var siteInvocation = _factory.Call( _factory.Field(callSiteFieldAccess, callSiteTargetField), delegateInvoke, callSiteArguments); return(new LoweredDynamicOperation(_factory, siteInitialization, siteInvocation, resultType, temps)); }
/// <summary> /// The spec describes an algorithm for finding the following types: /// 1) Collection type /// 2) Enumerator type /// 3) Element type /// /// The implementation details are a bit difference. If we're iterating over a string or an array, then we don't need to record anything /// but the inferredType (in case the iteration variable is implicitly typed). If we're iterating over anything else, then we want the /// inferred type plus a ForEachEnumeratorInfo.Builder with: /// 1) Collection type /// 2) Element type /// 3) GetEnumerator method of the collection type (return type will be the enumerator type from the spec) /// 4) Current property of the enumerator type /// 5) MoveNext method of the enumerator type /// /// The caller will have to do some extra conversion checks before creating a ForEachEnumeratorInfo for the BoundForEachStatement. /// </summary> /// <param name="builder">Builder to fill in (partially, all but conversions).</param> /// <param name="collectionExpr">The expression over which to iterate.</param> /// <param name="diagnostics">Populated with binding diagnostics.</param> /// <returns>Partially populated (all but conversions) or null if there was an error.</returns> private bool GetEnumeratorInfo(ref ForEachEnumeratorInfo.Builder builder, BoundExpression collectionExpr, DiagnosticBag diagnostics) { TypeSymbol collectionExprType = collectionExpr.Type; if (collectionExpr.ConstantValue != null && collectionExpr.ConstantValue.IsNull) { // Spec seems to refer to null literals, but Dev10 reports anything known to be null. Debug.Assert(collectionExpr.ConstantValue.IsNull); // only constant value with no type diagnostics.Add(ErrorCode.ERR_NullNotValid, syntax.Expression.Location); return(false); } if ((object)collectionExprType == null) // There's no way to enumerate something without a type. { // The null literal was caught above, so anything else with a null type is a method group or anonymous function diagnostics.Add(ErrorCode.ERR_AnonMethGrpInForEach, syntax.Expression.Location, collectionExpr.Display); // CONSIDER: dev10 also reports ERR_ForEachMissingMember (i.e. failed pattern match). return(false); } if (collectionExpr.ResultKind == LookupResultKind.NotAValue) { // Short-circuiting to prevent strange behavior in the case where the collection // expression is a type expression and the type is enumerable. Debug.Assert(collectionExpr.HasAnyErrors); // should already have been reported return(false); } // The spec specifically lists the collection, enumerator, and element types for arrays and dynamic. if (collectionExprType.Kind == SymbolKind.ArrayType || collectionExprType.Kind == SymbolKind.DynamicType) { // NOTE: for arrays, we won't actually use any of these members - they're just for the API. builder.CollectionType = GetSpecialType(SpecialType.System_Collections_IEnumerable, diagnostics, this.syntax); builder.ElementType = collectionExprType.IsDynamic() ? (this.syntax.Type.IsVar ? (TypeSymbol)DynamicTypeSymbol.Instance : GetSpecialType(SpecialType.System_Object, diagnostics, this.syntax)) : ((ArrayTypeSymbol)collectionExprType).ElementType; // CONSIDER: // For arrays none of these members will actually be emitted, so it seems strange to prevent compilation if they can't be found. // skip this work in the batch case? (If so, also special case string, which won't use the pattern methods.) builder.GetEnumeratorMethod = (MethodSymbol)GetSpecialTypeMember(SpecialMember.System_Collections_IEnumerable__GetEnumerator, diagnostics, this.syntax); builder.CurrentPropertyGetter = (MethodSymbol)GetSpecialTypeMember(SpecialMember.System_Collections_IEnumerator__get_Current, diagnostics, this.syntax); builder.MoveNextMethod = (MethodSymbol)GetSpecialTypeMember(SpecialMember.System_Collections_IEnumerator__MoveNext, diagnostics, this.syntax); Debug.Assert((object)builder.GetEnumeratorMethod == null || builder.GetEnumeratorMethod.ReturnType == this.Compilation.GetSpecialType(SpecialType.System_Collections_IEnumerator)); // We don't know the runtime type, so we will have to insert a runtime check for IDisposable (with a conditional call to IDisposable.Dispose). builder.NeedsDisposeMethod = true; return(true); } bool foundMultipleGenericIEnumerableInterfaces; if (SatisfiesGetEnumeratorPattern(ref builder, collectionExprType, diagnostics)) { Debug.Assert((object)builder.GetEnumeratorMethod != null); builder.CollectionType = collectionExprType; if (SatisfiesForEachPattern(ref builder, diagnostics)) { builder.ElementType = ((PropertySymbol)builder.CurrentPropertyGetter.AssociatedSymbol).Type; // NOTE: if IDisposable is not available at all, no diagnostics will be reported - we will just assume that // the enumerator is not disposable. If it has IDisposable in its interface list, there will be a diagnostic there. // If IDisposable is available but its Dispose method is not, then diagnostics will be reported only if the enumerator // is potentially disposable. var useSiteDiagnosticBag = DiagnosticBag.GetInstance(); TypeSymbol enumeratorType = builder.GetEnumeratorMethod.ReturnType; HashSet <DiagnosticInfo> useSiteDiagnostics = null; if (!enumeratorType.IsSealed || this.Conversions.ClassifyImplicitConversion(enumeratorType, this.Compilation.GetSpecialType(SpecialType.System_IDisposable), ref useSiteDiagnostics).IsImplicit) { builder.NeedsDisposeMethod = true; diagnostics.AddRange(useSiteDiagnosticBag); } useSiteDiagnosticBag.Free(); diagnostics.Add(this.syntax, useSiteDiagnostics); return(true); } MethodSymbol getEnumeratorMethod = builder.GetEnumeratorMethod; diagnostics.Add(ErrorCode.ERR_BadGetEnumerator, this.syntax.Expression.Location, getEnumeratorMethod.ReturnType, getEnumeratorMethod); return(false); } if (IsIEnumerable(collectionExprType)) { // This indicates a problem with the special IEnumerable type - it should have satisfied the GetEnumerator pattern. diagnostics.Add(ErrorCode.ERR_ForEachMissingMember, syntax.Expression.Location, collectionExprType, GetEnumeratorMethodName); return(false); } if (AllInterfacesContainsIEnumerable(ref builder, collectionExprType, diagnostics, out foundMultipleGenericIEnumerableInterfaces)) { CSharpSyntaxNode errorLocationSyntax = this.syntax.Expression; if (foundMultipleGenericIEnumerableInterfaces) { diagnostics.Add(ErrorCode.ERR_MultipleIEnumOfT, errorLocationSyntax.Location, collectionExprType, this.Compilation.GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T)); return(false); } Debug.Assert((object)builder.CollectionType != null); NamedTypeSymbol collectionType = (NamedTypeSymbol)builder.CollectionType; if (collectionType.IsGenericType) { // If the type is generic, we have to search for the methods Debug.Assert(collectionType.OriginalDefinition.SpecialType == SpecialType.System_Collections_Generic_IEnumerable_T); builder.ElementType = collectionType.TypeArgumentsNoUseSiteDiagnostics.Single(); MethodSymbol getEnumeratorMethod = (MethodSymbol)GetSpecialTypeMember(SpecialMember.System_Collections_Generic_IEnumerable_T__GetEnumerator, diagnostics, errorLocationSyntax); if ((object)getEnumeratorMethod != null) { builder.GetEnumeratorMethod = getEnumeratorMethod.AsMember(collectionType); TypeSymbol enumeratorType = builder.GetEnumeratorMethod.ReturnType; Debug.Assert(enumeratorType.OriginalDefinition.SpecialType == SpecialType.System_Collections_Generic_IEnumerator_T); MethodSymbol currentPropertyGetter = (MethodSymbol)GetSpecialTypeMember(SpecialMember.System_Collections_Generic_IEnumerator_T__get_Current, diagnostics, errorLocationSyntax); if ((object)currentPropertyGetter != null) { builder.CurrentPropertyGetter = currentPropertyGetter.AsMember((NamedTypeSymbol)enumeratorType); } } builder.MoveNextMethod = (MethodSymbol)GetSpecialTypeMember(SpecialMember.System_Collections_IEnumerator__MoveNext, diagnostics, errorLocationSyntax); // NOTE: MoveNext is actually inherited from System.Collections.IEnumerator } else { // Non-generic - use special members to avoid re-computing Debug.Assert(collectionType.SpecialType == SpecialType.System_Collections_IEnumerable); builder.ElementType = GetSpecialType(SpecialType.System_Object, diagnostics, errorLocationSyntax); builder.GetEnumeratorMethod = (MethodSymbol)GetSpecialTypeMember(SpecialMember.System_Collections_IEnumerable__GetEnumerator, diagnostics, errorLocationSyntax); builder.CurrentPropertyGetter = (MethodSymbol)GetSpecialTypeMember(SpecialMember.System_Collections_IEnumerator__get_Current, diagnostics, errorLocationSyntax); builder.MoveNextMethod = (MethodSymbol)GetSpecialTypeMember(SpecialMember.System_Collections_IEnumerator__MoveNext, diagnostics, errorLocationSyntax); Debug.Assert((object)builder.GetEnumeratorMethod == null || builder.GetEnumeratorMethod.ReturnType == GetSpecialType(SpecialType.System_Collections_IEnumerator, diagnostics, errorLocationSyntax)); } // We don't know the runtime type, so we will have to insert a runtime check for IDisposable (with a conditional call to IDisposable.Dispose). builder.NeedsDisposeMethod = true; return(true); } // This is a type that we don't know how to enumerate. // Skip the diagnostic if the type has no name - it makes the message unhelpful. if (!string.IsNullOrEmpty(collectionExprType.Name)) { diagnostics.Add(ErrorCode.ERR_ForEachMissingMember, syntax.Expression.Location, collectionExprType, GetEnumeratorMethodName); } return(false); }
private BoundExpression MakeEventAccess( SyntaxNode syntax, BoundExpression rewrittenReceiver, EventSymbol eventSymbol, ConstantValue constantValueOpt, LookupResultKind resultKind, TypeSymbol type) { Debug.Assert(eventSymbol.HasAssociatedField); FieldSymbol fieldSymbol = eventSymbol.AssociatedField; Debug.Assert((object)fieldSymbol != null); if (!eventSymbol.IsWindowsRuntimeEvent) { return(MakeFieldAccess(syntax, rewrittenReceiver, fieldSymbol, constantValueOpt, resultKind, type)); } NamedTypeSymbol fieldType = (NamedTypeSymbol)fieldSymbol.Type; Debug.Assert(fieldType.Name == "EventRegistrationTokenTable"); // _tokenTable BoundFieldAccess fieldAccess = new BoundFieldAccess( syntax, fieldSymbol.IsStatic ? null : rewrittenReceiver, fieldSymbol, constantValueOpt: null) { WasCompilerGenerated = true }; BoundExpression getOrCreateCall; MethodSymbol getOrCreateMethod; if (TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__GetOrCreateEventRegistrationTokenTable, out getOrCreateMethod)) { getOrCreateMethod = getOrCreateMethod.AsMember(fieldType); // EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable) getOrCreateCall = BoundCall.Synthesized( syntax, receiverOpt: null, method: getOrCreateMethod, arg0: fieldAccess); } else { getOrCreateCall = new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray.Create <BoundExpression>(fieldAccess), ErrorTypeSymbol.UnknownResultType); } PropertySymbol invocationListProperty; if (TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__InvocationList, out invocationListProperty)) { MethodSymbol invocationListAccessor = invocationListProperty.GetMethod; if ((object)invocationListAccessor == null) { string accessorName = SourcePropertyAccessorSymbol.GetAccessorName(invocationListProperty.Name, getNotSet: true, isWinMdOutput: invocationListProperty.IsCompilationOutputWinMdObj()); _diagnostics.Add(new CSDiagnosticInfo(ErrorCode.ERR_MissingPredefinedMember, invocationListProperty.ContainingType, accessorName), syntax.Location); } else { invocationListAccessor = invocationListAccessor.AsMember(fieldType); return(_factory.Call(getOrCreateCall, invocationListAccessor)); } } return(new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray.Create(getOrCreateCall), ErrorTypeSymbol.UnknownResultType)); }