Skip to content

Commit 0deb0cb

Browse files
authored
2 parents 74d07c0 + 17148b5 commit 0deb0cb

File tree

133 files changed

+11816
-311
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

133 files changed

+11816
-311
lines changed

docs/compilers/CSharp/Warnversion Warning Waves.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ In a typical project, this setting is controlled by the `AnalysisLevel` property
1313
which determines the `WarningLevel` property (passed to the `Csc` task).
1414
For more information on `AnalysisLevel`, see https://devblogs.microsoft.com/dotnet/automatically-find-latent-bugs-in-your-code-with-net-5/
1515

16+
## Warning level 11
17+
18+
The compiler shipped with .NET 11 (the C# 15 compiler) contains the following warnings which are reported only under `/warn:11` or higher.
19+
20+
| Warning ID | Description |
21+
|------------|-------------|
22+
| CS9368 | [RequiresUnsafeAttribute is only valid under the updated memory safety rules](https://github.com/dotnet/csharplang/issues/9704) |
23+
1624
## Warning level 10
1725

1826
The compiler shipped with .NET 10 (the C# 14 compiler) contains the following warnings which are reported only under `/warn:10` or higher.

src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1866,6 +1866,9 @@ private bool CheckEventValueKind(BoundEventAccess boundEvent, BindValueKind valu
18661866
}
18671867
else
18681868
{
1869+
// Unsafe member access for compound assignment is checked against the accessors elsewhere.
1870+
ReportDiagnosticsIfUnsafeMemberAccess(diagnostics, eventSymbol, eventSyntax);
1871+
18691872
if (!boundEvent.IsUsableAsField)
18701873
{
18711874
// Dev10 reports this in addition to ERR_BadAccess, but we won't even reach this point if the event isn't accessible (caught by lookup).
@@ -2074,6 +2077,7 @@ private bool CheckPropertyValueKind(SyntaxNode node, BoundExpression expr, BindV
20742077
}
20752078

20762079
ReportDiagnosticsIfObsolete(diagnostics, setMethod, node, receiver?.Kind == BoundKind.BaseReference);
2080+
ReportDiagnosticsIfUnsafeMemberAccess(diagnostics, setMethod, node);
20772081

20782082
var setValueKind = setMethod.IsEffectivelyReadOnly ? BindValueKind.RValue : BindValueKind.Assignable;
20792083
if (RequiresVariableReceiver(receiver, setMethod) && !CheckIsValidReceiverForVariable(node, receiver, setValueKind, diagnostics))
@@ -2124,6 +2128,7 @@ private bool CheckPropertyValueKind(SyntaxNode node, BoundExpression expr, BindV
21242128

21252129
CheckImplicitThisCopyInReadOnlyMember(receiver, getMethod, diagnostics);
21262130
ReportDiagnosticsIfObsolete(diagnostics, getMethod, node, receiver?.Kind == BoundKind.BaseReference);
2131+
ReportDiagnosticsIfUnsafeMemberAccess(diagnostics, getMethod, node);
21272132

21282133
if (IsBadBaseAccess(node, receiver, getMethod, diagnostics, propertySymbol) ||
21292134
reportUseSite(getMethod))

src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,7 @@ private BoundAssignmentOperator BindNamedAttributeArgument(AttributeArgumentSynt
529529
LookupResultKind resultKind;
530530
Symbol namedArgumentNameSymbol = BindNamedAttributeArgumentName(namedArgument, attributeType, diagnostics, out wasError, out resultKind);
531531
ReportDiagnosticsIfObsolete(diagnostics, namedArgumentNameSymbol, namedArgument, hasBaseReceiver: false);
532+
// Unsafe property access is checked on the accessor only to avoid duplicate diagnostics.
532533

533534
if (namedArgumentNameSymbol.Kind == SymbolKind.Property)
534535
{
@@ -537,6 +538,7 @@ private BoundAssignmentOperator BindNamedAttributeArgument(AttributeArgumentSynt
537538
if (setMethod != null)
538539
{
539540
ReportDiagnosticsIfObsolete(diagnostics, setMethod, namedArgument, hasBaseReceiver: false);
541+
ReportDiagnosticsIfUnsafeMemberAccess(diagnostics, setMethod, namedArgument);
540542

541543
if (setMethod.IsInitOnly && setMethod.DeclaringCompilation != this.Compilation)
542544
{
@@ -545,6 +547,10 @@ private BoundAssignmentOperator BindNamedAttributeArgument(AttributeArgumentSynt
545547
}
546548
}
547549
}
550+
else
551+
{
552+
ReportDiagnosticsIfUnsafeMemberAccess(diagnostics, namedArgumentNameSymbol, namedArgument);
553+
}
548554

549555
Debug.Assert(resultKind == LookupResultKind.Viable || wasError);
550556

src/Compilers/CSharp/Portable/Binder/Binder_Await.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ bool tryGetRuntimeAwaitHelper(BoundExpression expression, out BoundAwaitableValu
403403
return false;
404404
}
405405

406-
reportObsoleteDiagnostics(this, diagnostics, runtimeAwaitCall.Method, expression.Syntax);
406+
reportObsoleteAndUnsafeDiagnostics(this, diagnostics, runtimeAwaitCall.Method, expression.Syntax);
407407
return true;
408408

409409
static bool isApplicableMethod(
@@ -515,7 +515,7 @@ bool getRuntimeAwaitAwaiter(TypeSymbol awaiterType, out BoundCall? runtimeAwaitA
515515
runtimeAwaitAwaiterMethod,
516516
new ConstraintsHelper.CheckConstraintsArgs(this.Compilation, this.Conversions, includeNullability: false, syntax.Location, diagnostics));
517517

518-
reportObsoleteDiagnostics(this, diagnostics, runtimeAwaitAwaiterMethod, syntax);
518+
reportObsoleteAndUnsafeDiagnostics(this, diagnostics, runtimeAwaitAwaiterMethod, syntax);
519519

520520
placeholder = new BoundAwaitableValuePlaceholder(syntax, awaiterType);
521521

@@ -541,10 +541,11 @@ bool getRuntimeAwaitAwaiter(TypeSymbol awaiterType, out BoundCall? runtimeAwaitA
541541
return true;
542542
}
543543

544-
static void reportObsoleteDiagnostics(Binder @this, BindingDiagnosticBag diagnostics, MethodSymbol method, SyntaxNode syntax)
544+
static void reportObsoleteAndUnsafeDiagnostics(Binder @this, BindingDiagnosticBag diagnostics, MethodSymbol method, SyntaxNode syntax)
545545
{
546546
@this.ReportDiagnosticsIfObsolete(diagnostics, method, syntax, hasBaseReceiver: false);
547547
@this.ReportDiagnosticsIfObsolete(diagnostics, method.ContainingType, syntax, hasBaseReceiver: false);
548+
@this.ReportDiagnosticsIfUnsafeMemberAccess(diagnostics, method, syntax);
548549
}
549550
}
550551

@@ -644,6 +645,13 @@ private bool GetIsCompletedProperty(TypeSymbol awaiterType, SyntaxNode node, Typ
644645
return false;
645646
}
646647

648+
qualified = CheckValue(qualified, BindValueKind.RValue, diagnostics);
649+
if (qualified.HasAnyErrors)
650+
{
651+
isCompletedProperty = null;
652+
return false;
653+
}
654+
647655
isCompletedProperty = propertySymbol;
648656
if (isCompletedProperty.IsWriteOnly)
649657
{

src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ void reportUseSiteDiagnostics(SyntaxNode syntax, Conversion conversion, BoundExp
319319
ReportDiagnosticsIfObsolete(diagnostics, conversion, syntax, hasBaseReceiver: false);
320320
if (conversion.Method is not null)
321321
{
322+
ReportDiagnosticsIfUnsafeMemberAccess(diagnostics, conversion.Method, syntax);
322323
ReportUseSite(conversion.Method, diagnostics, syntax.Location);
323324
}
324325

@@ -468,6 +469,7 @@ void checkConstraintLanguageVersionAndRuntimeSupportForConversion(SyntaxNode syn
468469
Debug.Assert(elementField is { });
469470

470471
diagnostics.ReportUseSite(elementField, syntax);
472+
AssertNotUnsafeMemberAccess(elementField); // https://github.com/dotnet/roslyn/issues/82546: Support unsafe fields?
471473

472474
if (destination.OriginalDefinition.Equals(Compilation.GetWellKnownType(WellKnownType.System_ReadOnlySpan_T), TypeCompareKind.AllIgnoreOptions))
473475
{
@@ -1569,6 +1571,7 @@ internal void CheckCollectionBuilderMethod(
15691571

15701572
ReportDiagnosticsIfObsolete(diagnostics, collectionBuilderMethod.ContainingType, syntax, hasBaseReceiver: false);
15711573
ReportDiagnosticsIfObsolete(diagnostics, collectionBuilderMethod, syntax, hasBaseReceiver: false);
1574+
ReportDiagnosticsIfUnsafeMemberAccess(diagnostics, collectionBuilderMethod, syntax);
15721575
ReportDiagnosticsIfUnmanagedCallersOnly(diagnostics, collectionBuilderMethod, syntax, isDelegateConversion: false);
15731576

15741577
Debug.Assert(!collectionBuilderMethod.IsExtensionBlockMember());
@@ -1701,6 +1704,7 @@ static void bindClassCreationExpressionContinued(
17011704
var method = memberResolutionResult.Member;
17021705

17031706
binder.ReportDiagnosticsIfObsolete(diagnostics, method, node, hasBaseReceiver: false);
1707+
binder.ReportDiagnosticsIfUnsafeMemberAccess(diagnostics, method, node);
17041708
// NOTE: Use-site diagnostics were reported during overload resolution.
17051709

17061710
ImmutableSegmentedDictionary<string, Symbol> requiredMembers = GetMembersRequiringInitialization(method);
@@ -1950,6 +1954,7 @@ static bool bindMethodGroupInvocation(
19501954
else if (addMethods.Length == 1)
19511955
{
19521956
addMethodBinder.ReportDiagnosticsIfObsolete(diagnostics, addMethods[0], syntax, hasBaseReceiver: false);
1957+
addMethodBinder.ReportDiagnosticsIfUnsafeMemberAccess(diagnostics, addMethods[0], syntax);
19531958
ReportDiagnosticsIfUnmanagedCallersOnly(diagnostics, addMethods[0], syntax, isDelegateConversion: false);
19541959
Debug.Assert(!IsDisallowedExtensionInOlderLangVer(addMethods[0]));
19551960
}
@@ -2893,10 +2898,19 @@ private BoundExpression CreateStackAllocConversion(
28932898
switch (conversion.Kind)
28942899
{
28952900
case ConversionKind.StackAllocToPointerType:
2896-
ReportUnsafeIfNotAllowed(syntax.Location, diagnostics);
2901+
ReportUnsafeIfNotAllowed(syntax.Location, diagnostics, disallowedUnder: MemorySafetyRules.Legacy);
28972902
stackAllocType = new PointerTypeSymbol(TypeWithAnnotations.Create(elementType));
28982903
break;
28992904
case ConversionKind.StackAllocToSpanType:
2905+
// Under the updated memory safety rules, a stackalloc_expression is unsafe if being converted to Span/ROS,
2906+
// does not have an initializer, and is used within a member with SkipLocalsInitAttribute.
2907+
// https://github.com/dotnet/roslyn/issues/82546: Confirm this rule with LDM.
2908+
if (boundStackAlloc.InitializerOpt is null &&
2909+
ContainingMemberOrLambda is MethodSymbol { AreLocalsZeroed: false })
2910+
{
2911+
ReportUnsafeIfNotAllowed(syntax, diagnostics, disallowedUnder: MemorySafetyRules.Updated, customErrorCode: ErrorCode.ERR_UnsafeUninitializedStackAlloc);
2912+
}
2913+
29002914
CheckFeatureAvailability(syntax, MessageID.IDS_FeatureRefStructs, diagnostics);
29012915
stackAllocType = Compilation.GetWellKnownType(WellKnownType.System_Span_T).Construct(elementType);
29022916
break;
@@ -3526,7 +3540,7 @@ private bool MethodGroupConversionHasErrors(
35263540
}
35273541

35283542
if ((selectedMethod.HasParameterContainingPointerType() || selectedMethod.ReturnType.ContainsPointerOrFunctionPointer())
3529-
&& ReportUnsafeIfNotAllowed(syntax, diagnostics))
3543+
&& ReportUnsafeIfNotAllowed(syntax, diagnostics, disallowedUnder: MemorySafetyRules.Legacy))
35303544
{
35313545
return true;
35323546
}
@@ -3537,6 +3551,7 @@ private bool MethodGroupConversionHasErrors(
35373551
ReportDiagnosticsIfUnmanagedCallersOnly(diagnostics, selectedMethod, syntax, isDelegateConversion: true);
35383552
}
35393553
ReportDiagnosticsIfObsolete(diagnostics, selectedMethod, syntax, hasBaseReceiver: false);
3554+
ReportDiagnosticsIfUnsafeMemberAccess(diagnostics, selectedMethod, syntax);
35403555
ReportDiagnosticsIfDisallowedExtension(diagnostics, selectedMethod, syntax);
35413556

35423557
// No use site errors, but there could be use site warnings.

0 commit comments

Comments
 (0)