private ImmutableArray <TypeParameterSymbol> LoadTypeParameters(ref DiagnosticInfo diagnosticInfo) { try { var moduleSymbol = _containingType.ContainingPEModule; var gpHandles = moduleSymbol.Module.GetGenericParametersForMethodOrThrow(_handle); if (gpHandles.Count == 0) { return(ImmutableArray <TypeParameterSymbol> .Empty); } else { var ownedParams = ImmutableArray.CreateBuilder <TypeParameterSymbol>(gpHandles.Count); for (int i = 0; i < gpHandles.Count; i++) { ownedParams.Add(new PETypeParameterSymbol(moduleSymbol, this, (ushort)i, gpHandles[i])); } return(ownedParams.ToImmutable()); } } catch (BadImageFormatException) { diagnosticInfo = new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this); return(ImmutableArray <TypeParameterSymbol> .Empty); } }
internal static CSDiagnosticInfo ReportDiagnostic(this ErrorCode code, ref DiagnosticBag diagnostics, Location location, params object[] args) { var info = new CSDiagnosticInfo(code, args); var diag = new Diagnostic(info, location); if (diagnostics == null) diagnostics = new DiagnosticBag(); diagnostics.Add(diag); return info; }
private DiagnosticInfo InitializeUseSiteDiagnostic(DiagnosticInfo diagnostic) { Debug.Assert(!CSDiagnosticInfo.IsEmpty(diagnostic)); if (diagnostic != null) { diagnostic = InterlockedOperations.Initialize(ref AccessUncommonFields()._lazyUseSiteDiagnostic, diagnostic, CSDiagnosticInfo.EmptyErrorInfo); } _packedFlags.SetIsUseSiteDiagnosticPopulated(); return(diagnostic); }
internal static CSDiagnosticInfo ReportDiagnostic(this ErrorCode code, ref DiagnosticBag diagnostics, Location location, params object[] args) { var info = new CSDiagnosticInfo(code, args); var diag = new Diagnostic(info, location); if (diagnostics == null) { diagnostics = new DiagnosticBag(); } diagnostics.Add(diag); return(info); }
private static ExtendedErrorTypeSymbol CyclicInheritanceError( RetargetingNamedTypeSymbol type, TypeSymbol declaredBase ) { var info = new CSDiagnosticInfo(ErrorCode.ERR_ImportedCircularBase, declaredBase, type); return(new ExtendedErrorTypeSymbol( declaredBase, LookupResultKind.NotReferencable, info, true )); }
internal ErrorTypeSymbol CreateCycleInTypeForwarderErrorTypeSymbol( ref MetadataTypeName emittedName ) { DiagnosticInfo diagnosticInfo = new CSDiagnosticInfo( ErrorCode.ERR_CycleInTypeForwarder, emittedName.FullName, this.Name ); return(new MissingMetadataTypeSymbol.TopLevel( this.Modules[0], ref emittedName, diagnosticInfo )); }
internal ErrorTypeSymbol CreateMultipleForwardingErrorTypeSymbol( ref MetadataTypeName emittedName, ModuleSymbol forwardingModule, AssemblySymbol destination1, AssemblySymbol destination2 ) { var diagnosticInfo = new CSDiagnosticInfo( ErrorCode.ERR_TypeForwardedToMultipleAssemblies, forwardingModule, this, emittedName.FullName, destination1, destination2 ); return(new MissingMetadataTypeSymbol.TopLevel( forwardingModule, ref emittedName, diagnosticInfo )); }
// Check if the given symbol can be accessed with the given arity. If OK, return false. // If not OK, return true and return a diagnosticinfo. Note that methods with type arguments // can be accesses with arity zero due to type inference (but non types). private bool WrongArity(Symbol symbol, int arity, out DiagnosticInfo diagInfo) { switch (symbol.Kind) { case SymbolKind.NamedType: NamedTypeSymbol namedType = (NamedTypeSymbol)symbol; if (namedType.Arity != arity) { diagInfo = new CSDiagnosticInfo(ErrorCode.ERR_BadArity, namedType.GetFullName(), namedType.Arity); return(true); } break; case SymbolKind.Method: if (arity != 0) { MethodSymbol method = (MethodSymbol)symbol; if (method.Arity != arity) { diagInfo = new CSDiagnosticInfo(ErrorCode.ERR_HasNoTypeVars, method.GetFullName()); return(true); } } break; default: if (arity != 0) { diagInfo = new CSDiagnosticInfo(ErrorCode.ERR_TypeArgsNotAllowed, symbol.GetFullName()); return(true); } break; } diagInfo = null; return(false); }
internal override DiagnosticInfo GetUseSiteDiagnostic() { if (!_packedFlags.IsUseSiteDiagnosticPopulated) { DiagnosticInfo result = null; CalculateUseSiteDiagnostic(ref result); EnsureTypeParametersAreLoaded(ref result); return(InitializeUseSiteDiagnostic(result)); } var uncommonFields = _uncommonFields; if (uncommonFields == null) { return(null); } else { var result = uncommonFields._lazyUseSiteDiagnostic; return(CSDiagnosticInfo.IsEmpty(result) ? InterlockedOperations.Initialize(ref uncommonFields._lazyUseSiteDiagnostic, null, CSDiagnosticInfo.EmptyErrorInfo) : result); } }
internal override bool GetUnificationUseSiteDiagnostic(ref DiagnosticInfo result, TypeSymbol dependentType) { AssertReferencesInitialized(); var ownerModule = this; var ownerAssembly = ownerModule.ContainingAssembly; var dependentAssembly = dependentType.ContainingAssembly; if (ownerAssembly == dependentAssembly) { return(false); } // TODO (tomat): we should report an error/warning for all unified references, not just the first one. foreach (var unifiedAssembly in GetUnifiedAssemblies()) { if (!ReferenceEquals(unifiedAssembly.TargetAssembly, dependentAssembly)) { continue; } var referenceId = unifiedAssembly.OriginalReference; var definitionId = dependentAssembly.Identity; var involvedAssemblies = ImmutableArray.Create <Symbol>(ownerAssembly, dependentAssembly); DiagnosticInfo info; if (definitionId.Version > referenceId.Version) { // unified with a definition whose version is higher than the reference ErrorCode warning = (definitionId.Version.Major == referenceId.Version.Major && definitionId.Version.Minor == referenceId.Version.Minor) ? ErrorCode.WRN_UnifyReferenceBldRev : ErrorCode.WRN_UnifyReferenceMajMin; // warning: Assuming assembly reference '{0}' used by '{1}' matches identity '{2}' of '{3}', you may need to supply runtime policy. info = new CSDiagnosticInfo( warning, new object[] { referenceId.GetDisplayName(), ownerAssembly.Name, // TODO (tomat): should rather be MetadataReference.Display for the corresponding reference definitionId.GetDisplayName(), dependentAssembly.Name }, involvedAssemblies, ImmutableArray <Location> .Empty); } else { // unified with a definition whose version is lower than the reference // error: Assembly '{0}' with identity '{1}' uses '{2}' which has a higher version than referenced assembly '{3}' with identity '{4}' info = new CSDiagnosticInfo( ErrorCode.ERR_AssemblyMatchBadVersion, new object[] { ownerAssembly.Name, // TODO (tomat): should rather be MetadataReference.Display for the corresponding reference ownerAssembly.Identity.GetDisplayName(), referenceId.GetDisplayName(), dependentAssembly.Name, // TODO (tomat): should rather be MetadataReference.Display for the corresponding reference definitionId.GetDisplayName() }, involvedAssemblies, ImmutableArray <Location> .Empty); } if (MergeUseSiteDiagnostics(ref result, info)) { return(true); } } return(false); }
private ImmutableArray<TypeParameterSymbol> LoadTypeParameters(ref DiagnosticInfo diagnosticInfo) { try { var moduleSymbol = _containingType.ContainingPEModule; var gpHandles = moduleSymbol.Module.GetGenericParametersForMethodOrThrow(_handle); if (gpHandles.Count == 0) { return ImmutableArray<TypeParameterSymbol>.Empty; } else { var ownedParams = ImmutableArray.CreateBuilder<TypeParameterSymbol>(gpHandles.Count); for (int i = 0; i < gpHandles.Count; i++) { ownedParams.Add(new PETypeParameterSymbol(moduleSymbol, this, (ushort)i, gpHandles[i])); } return ownedParams.ToImmutable(); } } catch (BadImageFormatException) { diagnosticInfo = new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this); return ImmutableArray<TypeParameterSymbol>.Empty; } }
private ImmutableArray<SynthesizedExplicitImplementationForwardingMethod> ComputeInterfaceImplementations( DiagnosticBag diagnostics, CancellationToken cancellationToken) { if (this.IsInterface) { return ImmutableArray<SynthesizedExplicitImplementationForwardingMethod>.Empty; } var synthesizedImplementations = ArrayBuilder<SynthesizedExplicitImplementationForwardingMethod>.GetInstance(); // NOTE: We can't iterator over this collection directly, since it is not ordered. Instead we // iterate over AllInterfaces and filter out the interfaces that are not in this set. This is // preferable to doing the DFS ourselves because both AllInterfaces and // InterfacesAndTheirBaseInterfaces are cached and used in multiple places. ImmutableHashSet<NamedTypeSymbol> interfacesAndTheirBases = this.InterfacesAndTheirBaseInterfacesNoUseSiteDiagnostics; foreach (var @interface in this.AllInterfacesNoUseSiteDiagnostics) { cancellationToken.ThrowIfCancellationRequested(); if (!interfacesAndTheirBases.Contains(@interface)) { continue; } bool? hasImportedBaseTypeDeclaringInterface = null; foreach (var interfaceMember in @interface.GetMembersUnordered()) { cancellationToken.ThrowIfCancellationRequested(); // Only require implementations for members that can be implemented in C#. SymbolKind interfaceMemberKind = interfaceMember.Kind; switch (interfaceMemberKind) { case SymbolKind.Method: case SymbolKind.Property: case SymbolKind.Event: if (interfaceMember.IsStatic) { continue; } break; default: continue; } var implementingMemberAndDiagnostics = this.FindImplementationForInterfaceMemberWithDiagnostics(interfaceMember); var implementingMember = implementingMemberAndDiagnostics.Symbol; var synthesizedImplementation = this.SynthesizeInterfaceMemberImplementation(implementingMemberAndDiagnostics, interfaceMember); bool wasImplementingMemberFound = (object)implementingMember != null; if ((object)synthesizedImplementation != null) { synthesizedImplementations.Add(synthesizedImplementation); } if (wasImplementingMemberFound && interfaceMemberKind == SymbolKind.Event) { // NOTE: unlike dev11, we're including a related location for the implementing type, because // otherwise the only error location will be in the containing type of the implementing event // (i.e. no indication of which type's interface list is actually problematic). EventSymbol interfaceEvent = (EventSymbol)interfaceMember; EventSymbol implementingEvent = (EventSymbol)implementingMember; EventSymbol maybeWinRTEvent; EventSymbol maybeRegularEvent; if (interfaceEvent.IsWindowsRuntimeEvent) { maybeWinRTEvent = interfaceEvent; // Definitely WinRT. maybeRegularEvent = implementingEvent; // Maybe regular. } else { maybeWinRTEvent = implementingEvent; // Maybe WinRT. maybeRegularEvent = interfaceEvent; // Definitely regular. } if (interfaceEvent.IsWindowsRuntimeEvent != implementingEvent.IsWindowsRuntimeEvent) { // At this point (and not before), we know that maybeWinRTEvent is definitely a WinRT event and maybeRegularEvent is definitely a regular event. var args = new object[] { implementingEvent, interfaceEvent, maybeWinRTEvent, maybeRegularEvent }; var info = new CSDiagnosticInfo(ErrorCode.ERR_MixingWinRTEventWithRegular, args, ImmutableArray<Symbol>.Empty, ImmutableArray.Create<Location>(this.Locations[0])); diagnostics.Add(info, implementingEvent.Locations[0]); } } // Dev10: If a whole property is missing, report the property. If the property is present, but an accessor // is missing, report just the accessor. var associatedPropertyOrEvent = interfaceMemberKind == SymbolKind.Method ? ((MethodSymbol)interfaceMember).AssociatedSymbol : null; if ((object)associatedPropertyOrEvent == null || ReportAccessorOfInterfacePropertyOrEvent(associatedPropertyOrEvent) || (wasImplementingMemberFound && !implementingMember.IsAccessor())) { //we're here because //(a) the interface member is not an accessor, or //(b) the interface member is an accessor of an interesting (see ReportAccessorOfInterfacePropertyOrEvent) property or event, or //(c) the implementing member exists and is not an accessor. if (implementingMemberAndDiagnostics.Diagnostics.Any()) { diagnostics.AddRange(implementingMemberAndDiagnostics.Diagnostics); } else if (!wasImplementingMemberFound) { // NOTE: An alternative approach would be to keep track of this while searching for the implementing member. // In some cases, we might even be able to stop looking and just accept that a base type has things covered // (though we'd have to be careful about losing diagnostics and we might produce fewer bridge methods). // However, this approach has the advantage that there is no cost unless we encounter a base type that // claims to implement an interface, but we can't figure out how (i.e. free in nearly all cases). hasImportedBaseTypeDeclaringInterface = hasImportedBaseTypeDeclaringInterface ?? HasImportedBaseTypeDeclaringInterface(@interface); // If a base type from metadata declares that it implements the interface, we'll just trust it. // (See fFoundImport in SymbolPreparer::CheckInterfaceMethodImplementation.) if (!hasImportedBaseTypeDeclaringInterface.GetValueOrDefault()) { // CONSIDER: Dev10 does not emit this diagnostic for interface properties if the // derived type attempts to implement an accessor directly as a method. // Suppress for bogus properties and events and for indexed properties. if (!interfaceMember.MustCallMethodsDirectly() && !interfaceMember.IsIndexedProperty()) { DiagnosticInfo useSiteDiagnostic = interfaceMember.GetUseSiteDiagnostic(); if (useSiteDiagnostic != null && useSiteDiagnostic.DefaultSeverity == DiagnosticSeverity.Error) { diagnostics.Add(useSiteDiagnostic, GetImplementsLocation(@interface)); } else { diagnostics.Add(ErrorCode.ERR_UnimplementedInterfaceMember, GetImplementsLocation(@interface) ?? this.Locations[0], this, interfaceMember); } } } } else if (interfaceMemberKind == SymbolKind.Method) { // Don't report use site errors on properties - we'll report them on each of their accessors. // Don't report use site errors for implementations in other types unless // a synthesized implementation is needed that invokes the base method. // We can do so only if there are no use-site errors. if ((object)synthesizedImplementation != null || implementingMember.ContainingType == this) { DiagnosticInfo useSiteDiagnostic = interfaceMember.GetUseSiteDiagnostic(); // CAVEAT: don't report ERR_ByRefReturnUnsupported since by-ref return types are // specifically allowed for the purposes of interface implementation (for C++ interop). // However, if there's a reference to the interface member in source, then we do want // to produce a use site error. if (useSiteDiagnostic != null && (ErrorCode)useSiteDiagnostic.Code != ErrorCode.ERR_ByRefReturnUnsupported) { // Don't report a use site error with a location in another compilation. For example, // if the error is that a base type in another assembly implemented an interface member // on our behalf and the use site error is that the current assembly does not reference // some required assembly, then we want to report the error in the current assembly - // not in the implementing assembly. Location location = implementingMember.IsFromCompilation(this.DeclaringCompilation) ? implementingMember.Locations[0] : this.Locations[0]; Symbol.ReportUseSiteDiagnostic(useSiteDiagnostic, diagnostics, location); } } } } } } return synthesizedImplementations.ToImmutableAndFree(); }
internal override bool GetUnificationUseSiteDiagnostic(ref DiagnosticInfo result, TypeSymbol dependentType) { AssertReferencesInitialized(); var ownerModule = this; var ownerAssembly = ownerModule.ContainingAssembly; var dependentAssembly = dependentType.ContainingAssembly; if (ownerAssembly == dependentAssembly) { return false; } // TODO (tomat): we should report an error/warning for all unified references, not just the first one. foreach (var unifiedAssembly in GetUnifiedAssemblies()) { if (!ReferenceEquals(unifiedAssembly.TargetAssembly, dependentAssembly)) { continue; } var referenceId = unifiedAssembly.OriginalReference; var definitionId = dependentAssembly.Identity; var involvedAssemblies = ImmutableArray.Create<Symbol>(ownerAssembly, dependentAssembly); DiagnosticInfo info; if (definitionId.Version > referenceId.Version) { // unified with a definition whose version is higher than the reference ErrorCode warning = (definitionId.Version.Major == referenceId.Version.Major && definitionId.Version.Minor == referenceId.Version.Minor) ? ErrorCode.WRN_UnifyReferenceBldRev : ErrorCode.WRN_UnifyReferenceMajMin; // warning: Assuming assembly reference '{0}' used by '{1}' matches identity '{2}' of '{3}', you may need to supply runtime policy. info = new CSDiagnosticInfo( warning, new object[] { referenceId.GetDisplayName(), ownerAssembly.Name, // TODO (tomat): should rather be MetadataReference.Display for the corresponding reference definitionId.GetDisplayName(), dependentAssembly.Name }, involvedAssemblies, ImmutableArray<Location>.Empty); } else { // unified with a definition whose version is lower than the reference // error: Assembly '{0}' with identity '{1}' uses '{2}' which has a higher version than referenced assembly '{3}' with identity '{4}' info = new CSDiagnosticInfo( ErrorCode.ERR_AssemblyMatchBadVersion, new object[] { ownerAssembly.Name, // TODO (tomat): should rather be MetadataReference.Display for the corresponding reference ownerAssembly.Identity.GetDisplayName(), referenceId.GetDisplayName(), dependentAssembly.Name, // TODO (tomat): should rather be MetadataReference.Display for the corresponding reference definitionId.GetDisplayName() }, involvedAssemblies, ImmutableArray<Location>.Empty); } if (MergeUseSiteDiagnostics(ref result, info)) { return true; } } return false; }
private static ExtendedErrorTypeSymbol CyclicInheritanceError(RetargetingNamedTypeSymbol type, TypeSymbol declaredBase) { var info = new CSDiagnosticInfo(ErrorCode.ERR_ImportedCircularBase, declaredBase, type); return new ExtendedErrorTypeSymbol(declaredBase, LookupResultKind.NotReferencable, info, true); }
public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node) { BoundExpression originalLeft = node.Left; if (originalLeft.Kind != BoundKind.Local) { return(base.VisitAssignmentOperator(node)); } var leftLocal = (BoundLocal)originalLeft; BoundExpression originalRight = node.Right; #if XSHARP if (leftLocal.LocalSymbol.RefKind != RefKind.None && node.IsRef && NeedsProxy(leftLocal.LocalSymbol)) { var info = new CSDiagnosticInfo(ErrorCode.ERR_StaticLocalInCodeBlock, leftLocal.LocalSymbol.Name); this.Diagnostics.Add(info, node.Syntax.Location); return(node); } #endif if (leftLocal.LocalSymbol.RefKind != RefKind.None && node.IsRef && NeedsProxy(leftLocal.LocalSymbol)) { Debug.Assert(!proxies.ContainsKey(leftLocal.LocalSymbol)); Debug.Assert(originalRight.Kind != BoundKind.ConvertedStackAllocExpression); //spilling ref local variables throw ExceptionUtilities.Unreachable; } if (NeedsProxy(leftLocal.LocalSymbol) && !proxies.ContainsKey(leftLocal.LocalSymbol)) { Debug.Assert(leftLocal.LocalSymbol.DeclarationKind == LocalDeclarationKind.None); // spilling temp variables throw ExceptionUtilities.Unreachable; } BoundExpression rewrittenLeft = (BoundExpression)this.Visit(leftLocal); BoundExpression rewrittenRight = (BoundExpression)this.Visit(originalRight); TypeSymbol rewrittenType = VisitType(node.Type); // Check if we're assigning the result of stackalloc to a hoisted local. // If we are, we need to store the result in a temp local and then assign // the value of the local to the field corresponding to the hoisted local. // If the receiver of the field is on the stack when the stackalloc happens, // popping it will free the memory (?) or otherwise cause verification issues. // DevDiv Bugs 59454 if (rewrittenLeft.Kind != BoundKind.Local && originalRight.Kind == BoundKind.ConvertedStackAllocExpression) { // From ILGENREC::genAssign: // DevDiv Bugs 59454: Handle hoisted local initialized with a stackalloc // NOTE: Need to check for cast of stackalloc on RHS. // If LHS isLocal, then genAddr is a noop so regular case works fine. SyntheticBoundNodeFactory factory = new SyntheticBoundNodeFactory(this.CurrentMethod, rewrittenLeft.Syntax, this.CompilationState, this.Diagnostics); BoundAssignmentOperator tempAssignment; BoundLocal tempLocal = factory.StoreToTemp(rewrittenRight, out tempAssignment); Debug.Assert(!node.IsRef); BoundAssignmentOperator rewrittenAssignment = node.Update(rewrittenLeft, tempLocal, node.IsRef, rewrittenType); return(new BoundSequence( node.Syntax, ImmutableArray.Create <LocalSymbol>(tempLocal.LocalSymbol), ImmutableArray.Create <BoundExpression>(tempAssignment), rewrittenAssignment, rewrittenType)); } return(node.Update(rewrittenLeft, rewrittenRight, node.IsRef, rewrittenType)); }
// Check if the given symbol can be accessed with the given arity. If OK, return false. // If not OK, return true and return a diagnosticinfo. Note that methods with type arguments // can be accesses with arity zero due to type inference (but non types). private bool WrongArity(Symbol symbol, int arity, out DiagnosticInfo diagInfo) { switch (symbol.Kind) { case SymbolKind.NamedType: NamedTypeSymbol namedType = (NamedTypeSymbol)symbol; if (namedType.Arity != arity) { diagInfo = new CSDiagnosticInfo(ErrorCode.ERR_BadArity, namedType.GetFullName(), namedType.Arity); return true; } break; case SymbolKind.Method: if (arity != 0) { MethodSymbol method = (MethodSymbol)symbol; if (method.Arity != arity) { diagInfo = new CSDiagnosticInfo(ErrorCode.ERR_HasNoTypeVars, method.GetFullName()); return true; } } break; default: if (arity != 0) { diagInfo = new CSDiagnosticInfo(ErrorCode.ERR_TypeArgsNotAllowed, symbol.GetFullName()); return true; } break; } diagInfo = null; return false; }