Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/Compilers/CSharp/Portable/Binder/BinderFlags.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ internal enum BinderFlags : uint
ParameterDefaultValue = 1 << 23,

/// <summary>
/// In the debugger, one can take the address of a managed object.
/// In the debugger, one can take the address of a moveable variable.
/// </summary>
AllowManagedAddressOf = 1 << 24,
AllowMoveableAddressOf = 1 << 24,

/// <summary>
/// In the debugger, the context is always unsafe, but one can still await.
Expand Down Expand Up @@ -112,6 +112,12 @@ internal enum BinderFlags : uint
/// </summary>
InExpressionTree = 1 << 30,

/// <summary>
/// Indicates whether the current context allows pointer types to managed types,
/// assuming we're already in an unsafe context (otherwise all pointer types are errors anyways).
/// </summary>
AllowManagedPointer = 1u << 31,

// Groups

AllClearedAtExecutableCodeBoundary = InLockBody | InCatchBlock | InCatchFilter | InFinallyBlock | InTryBlockOfTryCatch | InNestedFinallyBlock,
Expand Down
26 changes: 17 additions & 9 deletions src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1387,7 +1387,7 @@ private BoundExpression BindSizeOf(SizeOfExpressionSyntax node, BindingDiagnosti
TypeWithAnnotations typeWithAnnotations = this.BindType(typeSyntax, diagnostics, out alias);
TypeSymbol type = typeWithAnnotations.Type;

bool typeHasErrors = type.IsErrorType() || CheckManagedAddr(Compilation, type, node.Location, diagnostics);
bool typeHasErrors = type.IsErrorType() || CheckManagedAddr(Compilation, type, warnForManaged: false, node.Location, diagnostics);

BoundTypeExpression boundType = new BoundTypeExpression(typeSyntax, alias, typeWithAnnotations, typeHasErrors);
ConstantValue constantValue = GetConstantSizeOf(type);
Expand All @@ -1397,23 +1397,31 @@ private BoundExpression BindSizeOf(SizeOfExpressionSyntax node, BindingDiagnosti
}

/// <returns>true if managed type-related errors were found, otherwise false.</returns>
internal static bool CheckManagedAddr(CSharpCompilation compilation, TypeSymbol type, Location location, BindingDiagnosticBag diagnostics)
internal static bool CheckManagedAddr(CSharpCompilation compilation, TypeSymbol type, bool warnForManaged, Location location, BindingDiagnosticBag diagnostics)
{
var useSiteInfo = new CompoundUseSiteInfo<AssemblySymbol>(diagnostics, compilation.Assembly);
var managedKind = type.GetManagedKind(ref useSiteInfo);
diagnostics.Add(location, useSiteInfo);

return CheckManagedAddr(compilation, type, managedKind, location, diagnostics);
return CheckManagedAddr(compilation, type, managedKind, warnForManaged, location, diagnostics);
}

/// <returns>true if managed type-related errors were found, otherwise false.</returns>
internal static bool CheckManagedAddr(CSharpCompilation compilation, TypeSymbol type, ManagedKind managedKind, Location location, BindingDiagnosticBag diagnostics)
internal static bool CheckManagedAddr(CSharpCompilation compilation, TypeSymbol type, ManagedKind managedKind, bool warnForManaged, Location location, BindingDiagnosticBag diagnostics)
{
switch (managedKind)
{
case ManagedKind.Managed:
diagnostics.Add(ErrorCode.ERR_ManagedAddr, location, type);
return true;
if (warnForManaged)
{
diagnostics.Add(ErrorCode.WRN_ManagedAddr, location, type);
return false;
}
else
{
diagnostics.Add(ErrorCode.ERR_ManagedAddr, location, type);
return true;
}
case ManagedKind.UnmanagedWithGenerics when MessageID.IDS_FeatureUnmanagedConstructedTypes.GetFeatureAvailabilityDiagnosticInfo(compilation) is CSDiagnosticInfo diagnosticInfo:
diagnostics.Add(diagnosticInfo, location);
return true;
Expand Down Expand Up @@ -2219,7 +2227,7 @@ private BoundBaseReference BindBase(BaseExpressionSyntax node, BindingDiagnostic
private BoundExpression BindCast(CastExpressionSyntax node, BindingDiagnosticBag diagnostics)
{
BoundExpression operand = this.BindValue(node.Expression, diagnostics, BindValueKind.RValue);
TypeWithAnnotations targetTypeWithAnnotations = this.BindType(node.Type, diagnostics);
TypeWithAnnotations targetTypeWithAnnotations = this.WithAdditionalFlags(BinderFlags.AllowManagedPointer).BindType(node.Type, diagnostics);
TypeSymbol targetType = targetTypeWithAnnotations.Type;

if (targetType.IsNullableType() &&
Expand Down Expand Up @@ -3299,7 +3307,7 @@ private BoundExpression BindImplicitStackAllocArrayCreationExpression(ImplicitSt

if (!bestType.IsErrorType())
{
CheckManagedAddr(Compilation, bestType, node.Location, diagnostics);
CheckManagedAddr(Compilation, bestType, warnForManaged: false, node.Location, diagnostics);
}

return BindStackAllocWithInitializer(
Expand Down Expand Up @@ -3656,7 +3664,7 @@ private BoundExpression BindStackAllocArrayCreationExpression(
TypeSymbol type = GetStackAllocType(node, elementType, diagnostics, out bool hasErrors);
if (!elementType.Type.IsErrorType())
{
hasErrors = hasErrors || CheckManagedAddr(Compilation, elementType.Type, elementTypeSyntax.Location, diagnostics);
hasErrors = hasErrors || CheckManagedAddr(Compilation, elementType.Type, warnForManaged: false, elementTypeSyntax.Location, diagnostics);
}

SyntaxList<ArrayRankSpecifierSyntax> rankSpecifiers = arrayTypeSyntax.RankSpecifiers;
Expand Down
28 changes: 10 additions & 18 deletions src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2502,30 +2502,22 @@ private BoundExpression BindAddressOfExpression(PrefixUnaryExpressionSyntax node
ManagedKind managedKind = operandType.GetManagedKind(ref useSiteInfo);
diagnostics.Add(node.Location, useSiteInfo);

bool allowManagedAddressOf = Flags.Includes(BinderFlags.AllowManagedAddressOf);
if (!allowManagedAddressOf)
if (!hasErrors)
{
if (!hasErrors)
{
hasErrors = CheckManagedAddr(Compilation, operandType, managedKind, node.Location, diagnostics);
}
hasErrors = CheckManagedAddr(Compilation, operandType, managedKind, warnForManaged: true, node.Location, diagnostics);
}

if (!hasErrors)
bool allowManagedAddressOf = Flags.Includes(BinderFlags.AllowMoveableAddressOf);
if (!hasErrors && !allowManagedAddressOf)
{
if (IsMoveableVariable(operand, accessedLocalOrParameterOpt: out _) != isFixedStatementAddressOfExpression)
{
Symbol accessedLocalOrParameterOpt;
if (IsMoveableVariable(operand, out accessedLocalOrParameterOpt) != isFixedStatementAddressOfExpression)
{
Error(diagnostics, isFixedStatementAddressOfExpression ? ErrorCode.ERR_FixedNotNeeded : ErrorCode.ERR_FixedNeeded, node);
hasErrors = true;
}
Error(diagnostics, isFixedStatementAddressOfExpression ? ErrorCode.ERR_FixedNotNeeded : ErrorCode.ERR_FixedNeeded, node);
hasErrors = true;
}
}

TypeSymbol pointedAtType = managedKind == ManagedKind.Managed && allowManagedAddressOf
? GetSpecialType(SpecialType.System_IntPtr, diagnostics, node)
: operandType ?? CreateErrorType();
TypeSymbol pointerType = new PointerTypeSymbol(TypeWithAnnotations.Create(pointedAtType));

TypeSymbol pointerType = new PointerTypeSymbol(TypeWithAnnotations.Create(operandType));
return new BoundAddressOfOperator(node, operand, pointerType, hasErrors);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1334,7 +1334,7 @@ private bool IsValidFixedVariableInitializer(TypeSymbol declType, SourceLocalSym
}
}

if (CheckManagedAddr(Compilation, elementType, initializerSyntax.Location, diagnostics))
if (CheckManagedAddr(Compilation, elementType, warnForManaged: false, initializerSyntax.Location, diagnostics))
{
hasErrors = true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ NamespaceOrTypeOrAliasSymbolWithAnnotations bindPointer()

if (!Flags.HasFlag(BinderFlags.SuppressConstraintChecks))
{
CheckManagedAddr(Compilation, elementType.Type, node.Location, diagnostics);
CheckManagedAddr(Compilation, elementType.Type, warnForManaged: Flags.HasFlag(BinderFlags.AllowManagedPointer), node.Location, diagnostics);
}

return TypeWithAnnotations.Create(new PointerTypeSymbol(elementType));
Expand Down
6 changes: 6 additions & 0 deletions src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,12 @@
<data name="ERR_ManagedAddr" xml:space="preserve">
<value>Cannot take the address of, get the size of, or declare a pointer to a managed type ('{0}')</value>
</data>
<data name="WRN_ManagedAddr" xml:space="preserve">
<value>This takes the address of, gets the size of, or declares a pointer to a managed type ('{0}')</value>
</data>
<data name="WRN_ManagedAddr_Title" xml:space="preserve">
<value>This takes the address of, gets the size of, or declares a pointer to a managed type</value>
</data>
<data name="ERR_BadFixedInitType" xml:space="preserve">
<value>The type of a local declared in a fixed statement must be a pointer type</value>
</data>
Expand Down
3 changes: 3 additions & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1612,6 +1612,9 @@ internal enum ErrorCode
ERR_ImplicitRangeIndexerWithName = 8429,
// available range

WRN_ManagedAddr = 8500,
// available range

#region diagnostics introduced for recursive patterns
ERR_WrongNumberOfSubpatterns = 8502,
ERR_PropertyPatternNameMissing = 8503,
Expand Down
2 changes: 2 additions & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,7 @@ internal static int GetWarningLevel(ErrorCode code)
case ErrorCode.WRN_DuplicateAnalyzerReference:
case ErrorCode.WRN_ScopedMismatchInParameterOfTarget:
case ErrorCode.WRN_ScopedMismatchInParameterOfOverrideOrImplementation:
case ErrorCode.WRN_ManagedAddr:
return 1;
default:
return 0;
Expand Down Expand Up @@ -2229,6 +2230,7 @@ internal static bool IsBuildOnlyDiagnostic(ErrorCode code)
case ErrorCode.ERR_RefReturnOnlyParameter:
case ErrorCode.ERR_RefReturnOnlyParameter2:
case ErrorCode.ERR_RefAssignReturnOnly:
case ErrorCode.WRN_ManagedAddr:
return false;
default:
// NOTE: All error codes must be explicitly handled in this switch statement
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading