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
6 changes: 0 additions & 6 deletions src/Compilers/CSharp/Portable/Binder/BinderFlags.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,6 @@ 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
24 changes: 11 additions & 13 deletions src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1393,7 +1393,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, warnForManaged: false, node.Location, diagnostics);
bool typeHasErrors = type.IsErrorType() || CheckManagedAddr(Compilation, type, node.Location, diagnostics);

BoundTypeExpression boundType = new BoundTypeExpression(typeSyntax, alias, typeWithAnnotations, typeHasErrors);
ConstantValue constantValue = GetConstantSizeOf(type);
Expand All @@ -1403,31 +1403,29 @@ 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, bool warnForManaged, Location location, BindingDiagnosticBag diagnostics)
internal static bool CheckManagedAddr(CSharpCompilation compilation, TypeSymbol type, Location location, BindingDiagnosticBag diagnostics, bool errorForManaged = false)
{
var useSiteInfo = new CompoundUseSiteInfo<AssemblySymbol>(diagnostics, compilation.Assembly);
var managedKind = type.GetManagedKind(ref useSiteInfo);
diagnostics.Add(location, useSiteInfo);

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

/// <returns>true if managed type-related errors were found, otherwise false.</returns>
internal static bool CheckManagedAddr(CSharpCompilation compilation, TypeSymbol type, ManagedKind managedKind, bool warnForManaged, Location location, BindingDiagnosticBag diagnostics)
internal static bool CheckManagedAddr(CSharpCompilation compilation, TypeSymbol type, ManagedKind managedKind, Location location, BindingDiagnosticBag diagnostics, bool errorForManaged = false)
{
switch (managedKind)
{
case ManagedKind.Managed:
if (warnForManaged)
{
diagnostics.Add(ErrorCode.WRN_ManagedAddr, location, type);
return false;
}
else
if (errorForManaged)
{
diagnostics.Add(ErrorCode.ERR_ManagedAddr, location, type);
return true;
}

diagnostics.Add(ErrorCode.WRN_ManagedAddr, location, type);
Copy link
Member

@RikkiGibson RikkiGibson Sep 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also do a LangVersion check so that people on old language versions can't suppress these #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's a good idea. I'll do a runtime rebuild tonight to verify they don't have a project with managed pointers and LangVer<11.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following conversation with Jared, I added a LangVer check. Thanks

return false;
Copy link
Contributor

@cston cston Sep 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return false

Should this return true if the language version check fails? #Resolved

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If not, the method comment should be updated to reflect the new behavior.

case ManagedKind.UnmanagedWithGenerics when MessageID.IDS_FeatureUnmanagedConstructedTypes.GetFeatureAvailabilityDiagnosticInfo(compilation) is CSDiagnosticInfo diagnosticInfo:
diagnostics.Add(diagnosticInfo, location);
return true;
Expand Down Expand Up @@ -2233,7 +2231,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.WithAdditionalFlags(BinderFlags.AllowManagedPointer).BindType(node.Type, diagnostics);
TypeWithAnnotations targetTypeWithAnnotations = this.BindType(node.Type, diagnostics);
TypeSymbol targetType = targetTypeWithAnnotations.Type;

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

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

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

SyntaxList<ArrayRankSpecifierSyntax> rankSpecifiers = arrayTypeSyntax.RankSpecifiers;
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2504,7 +2504,7 @@ private BoundExpression BindAddressOfExpression(PrefixUnaryExpressionSyntax node

if (!hasErrors)
{
hasErrors = CheckManagedAddr(Compilation, operandType, managedKind, warnForManaged: true, node.Location, diagnostics);
hasErrors = CheckManagedAddr(Compilation, operandType, managedKind, node.Location, diagnostics);
}

bool allowManagedAddressOf = Flags.Includes(BinderFlags.AllowMoveableAddressOf);
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, warnForManaged: false, initializerSyntax.Location, diagnostics))
if (CheckManagedAddr(Compilation, elementType, 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, warnForManaged: Flags.HasFlag(BinderFlags.AllowManagedPointer), node.Location, diagnostics);
CheckManagedAddr(Compilation, elementType.Type, node.Location, diagnostics);
}

return TypeWithAnnotations.Create(new PointerTypeSymbol(elementType));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ public override BoundNode VisitFixedStatement(BoundFixedStatement node)
}
else
{
Debug.Assert(!pinnedTemp.Type.IsManagedTypeNoUseSiteDiagnostics);

// temp = ref *default(T*);
cleanup[i] = _factory.Assignment(_factory.Local(pinnedTemp), _factory.NullRef(pinnedTemp.TypeWithAnnotations), isRef: true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ private static bool CheckConstraintsSingleType(TypeSymbol type, in CheckConstrai
}
else if (type.Kind == SymbolKind.PointerType)
{
Binder.CheckManagedAddr(args.CurrentCompilation, ((PointerTypeSymbol)type).PointedAtType, warnForManaged: false, args.Location, args.Diagnostics);
Binder.CheckManagedAddr(args.CurrentCompilation, ((PointerTypeSymbol)type).PointedAtType, args.Location, args.Diagnostics);
}
return false; // continue walking types
}
Expand Down
10 changes: 5 additions & 5 deletions src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14341,15 +14341,15 @@ interface ITest2<T> : ValueTuple<int, int, int, int, int, int, int, T> where T :
options: TestOptions.ReleaseExe.WithAllowUnsafe(true));

comp.VerifyDiagnostics(
// (31,18): error CS0509: 'Test1<T>': cannot derive from sealed type 'ValueTuple<int, int, int, int, int, int, int, T>'
// class Test1<T> : ValueTuple<int, int, int, int, int, int, int, T> where T : struct
Diagnostic(ErrorCode.ERR_CantDeriveFromSealedType, "ValueTuple<int, int, int, int, int, int, int, T>").WithArguments("Test1<T>", "System.ValueTuple<int, int, int, int, int, int, int, T>").WithLocation(31, 18),
// (35,23): error CS0527: Type 'ValueTuple<int, int, int, int, int, int, int, T>' in interface list is not an interface
// interface ITest2<T> : ValueTuple<int, int, int, int, int, int, int, T> where T : struct
Diagnostic(ErrorCode.ERR_NonInterfaceInInterfaceList, "ValueTuple<int, int, int, int, int, int, int, T>").WithArguments("System.ValueTuple<int, int, int, int, int, int, int, T>").WithLocation(35, 23),
// (25,69): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('ValueTuple<int, int, int, int, int, int, int, T>')
// (31,18): error CS0509: 'Test1<T>': cannot derive from sealed type 'ValueTuple<int, int, int, int, int, int, int, T>'
// class Test1<T> : ValueTuple<int, int, int, int, int, int, int, T> where T : struct
Diagnostic(ErrorCode.ERR_CantDeriveFromSealedType, "ValueTuple<int, int, int, int, int, int, int, T>").WithArguments("Test1<T>", "System.ValueTuple<int, int, int, int, int, int, int, T>").WithLocation(31, 18),
// (25,69): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('ValueTuple<int, int, int, int, int, int, int, T>')
// public static ValueTuple<int, int, int, int, int, int, int, T>* M5()
Diagnostic(ErrorCode.ERR_ManagedAddr, "M5").WithArguments("System.ValueTuple<int, int, int, int, int, int, int, T>").WithLocation(25, 69),
Diagnostic(ErrorCode.WRN_ManagedAddr, "M5").WithArguments("System.ValueTuple<int, int, int, int, int, int, int, T>").WithLocation(25, 69),
// (23,74): error CS0066: 'Test<T>.E1': event must be of a delegate type
// public static event ValueTuple<int, int, int, int, int, int, int, T> E1;
Diagnostic(ErrorCode.ERR_EventNotDelegate, "E1").WithArguments("Test<T>.E1").WithLocation(23, 74),
Expand Down
4 changes: 2 additions & 2 deletions src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1407,9 +1407,9 @@ void M()
}
}",
comp => comp.VerifyDiagnostics(
// (7,45): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('S')
// (7,45): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('S')
// System.Console.WriteLine(sizeof(S*));
Diagnostic(ErrorCode.ERR_ManagedAddr, "S*").WithArguments("S").WithLocation(7, 45)
Diagnostic(ErrorCode.WRN_ManagedAddr, "S*").WithArguments("S").WithLocation(7, 45)
));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4471,12 +4471,12 @@ public static void Main(int* a, var* c, Typ* e)
// (13,31): error CS1525: Invalid expression term 'int'
// switch (a) { case int* b: break; }
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int").WithLocation(13, 31),
// (5,42): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('var')
// (5,42): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('var')
// public static void Main(int* a, var* c, Typ* e)
Diagnostic(ErrorCode.ERR_ManagedAddr, "c").WithArguments("var").WithLocation(5, 42),
// (5,50): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('Typ')
Diagnostic(ErrorCode.WRN_ManagedAddr, "c").WithArguments("var").WithLocation(5, 42),
// (5,50): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('Typ')
// public static void Main(int* a, var* c, Typ* e)
Diagnostic(ErrorCode.ERR_ManagedAddr, "e").WithArguments("Typ").WithLocation(5, 50),
Diagnostic(ErrorCode.WRN_ManagedAddr, "e").WithArguments("Typ").WithLocation(5, 50),
// (8,27): error CS0103: The name 'b' does not exist in the current context
// if (a is int* b) {}
Diagnostic(ErrorCode.ERR_NameNotInContext, "b").WithArguments("b").WithLocation(8, 27),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ void M(int i)
TypeOperand: C
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('C')
// (8,23): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('C')
// i = /*<bind>*/sizeof(C)/*</bind>*/;
Diagnostic(ErrorCode.ERR_ManagedAddr, "sizeof(C)").WithArguments("C").WithLocation(8, 23),
// CS0233: 'C' does not have a predefined size, therefore sizeof can only be used in an unsafe context (consider using System.Runtime.InteropServices.Marshal.SizeOf)
Diagnostic(ErrorCode.WRN_ManagedAddr, "sizeof(C)").WithArguments("C").WithLocation(8, 23),
// (8,23): error CS0233: 'C' does not have a predefined size, therefore sizeof can only be used in an unsafe context
// i = /*<bind>*/sizeof(C)/*</bind>*/;
Diagnostic(ErrorCode.ERR_SizeofUnsafe, "sizeof(C)").WithArguments("C").WithLocation(8, 23)
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4120,9 +4120,9 @@ public void Deconstruct(out dynamic x, out dynamic y)
// (9,10): error CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code
// (var*[] x4, int y4) = c;
Diagnostic(ErrorCode.ERR_TypeVarNotFound, "var").WithLocation(9, 10),
// (9,10): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('var')
// (9,10): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('var')
// (var*[] x4, int y4) = c;
Diagnostic(ErrorCode.ERR_ManagedAddr, "var*").WithArguments("var").WithLocation(9, 10),
Diagnostic(ErrorCode.WRN_ManagedAddr, "var*").WithArguments("var").WithLocation(9, 10),
// (9,10): error CS0266: Cannot implicitly convert type 'dynamic' to 'var*[]'. An explicit conversion exists (are you missing a cast?)
// (var*[] x4, int y4) = c;
Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "var*[] x4").WithArguments("dynamic", "var*[]").WithLocation(9, 10),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3564,9 +3564,9 @@ class E<T> where T : struct {}
// (6,27): error CS0722: 'S': static types cannot be used as return types
// void M1(delegate*<C*, S> ptr) {}
Diagnostic(ErrorCode.ERR_ReturnTypeIsStaticClass, "S").WithArguments("S").WithLocation(6, 27),
// (6,30): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('C')
// (6,30): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('C')
// void M1(delegate*<C*, S> ptr) {}
Diagnostic(ErrorCode.ERR_ManagedAddr, "ptr").WithArguments("C").WithLocation(6, 30),
Diagnostic(ErrorCode.WRN_ManagedAddr, "ptr").WithArguments("C").WithLocation(6, 30),
// (8,32): error CS8377: The type 'T' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D<T>'
// void M3<T>(delegate*<D<T>> ptr) {}
Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "ptr").WithArguments("D<T>", "T", "T").WithLocation(8, 32),
Expand Down
Loading