diff --git a/Directory.Build.props b/Directory.Build.props index 99eee260233d71..21c3a57182edbc 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -269,6 +269,10 @@ $(WarningsNotAsErrors);NU1901;NU1902;NU1903;NU1904 $(NoWarn);CS8500;CS8969 + + $(NoWarn);IDE0100 + + $(NoWarn);IDE0060 $(NoWarn);CS1591 diff --git a/eng/Versions.props b/eng/Versions.props index d61001668130e5..87c7a1db2d1179 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -56,7 +56,7 @@ Source-build builds the product with the most recent previously source-built release. Thankfully, these two requirements line up nicely such that any version that satisfies the VS version requirement will also satisfy the .NET SDK version requirement because of how we ship. --> - 4.8.0 + 4.14.0 3.3.5-beta1.23270.2 diff --git a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ResultChecker.cs b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ResultChecker.cs index 673df2e9a11500..ff012a7945fee0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ResultChecker.cs +++ b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ResultChecker.cs @@ -202,6 +202,20 @@ private void VerifyLoggedMessages(AssemblyDefinition original, TrimmingTestLogge List<(ICustomAttributeProvider, CustomAttribute)> expectedNoWarningsAttributes = new(); foreach (var attrProvider in GetAttributeProviders(original)) { + if (attrProvider is IMemberDefinition attrMember && + attrMember is not TypeDefinition && + attrMember.DeclaringType is TypeDefinition declaringType && + declaringType.Name.StartsWith("")) + { + // Workaround: C# 14 extension members result in a compiler-generated type + // that has a member for each extension member (this is in addition to the type + // which contains the actual extension member implementation). + // The generated members inherit attributes from the extension members, but + // have empty implementations. We don't want to check inherited ExpectedWarningAttributes + // for these members. + continue; + } + foreach (var attr in attrProvider.CustomAttributes) { if (!IsProducedByNativeAOT(attr)) diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/DataFlow/LocalDataFlowVisitor.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/DataFlow/LocalDataFlowVisitor.cs index db1ae85bf19385..f392a2113139f4 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/DataFlow/LocalDataFlowVisitor.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/DataFlow/LocalDataFlowVisitor.cs @@ -305,8 +305,16 @@ bool merge return value; } - // Property may be an indexer, in which case there will be one or more index arguments followed by a value argument ImmutableArray.Builder arguments = ImmutableArray.CreateBuilder(); + + // Handle C# 14 extension property access (see comment in ProcessMethodCall) + if (setMethod.HasExtensionParameterOnType()) + { + arguments.Add(instanceValue); + instanceValue = TopValue; + } + + // Property may be an indexer, in which case there will be one or more index arguments followed by a value argument foreach (var val in propertyRef.Arguments) arguments.Add(Visit(val, state)); arguments.Add(value); @@ -705,14 +713,20 @@ public override TValue VisitPropertyReference(IPropertyReferenceOperation operat // Accessing property for reading is really a call to the getter // The setter case is handled in assignment operation since here we don't have access to the value to pass to the setter TValue instanceValue = Visit(operation.Instance, state); - IMethodSymbol? getMethod = operation.Property.GetGetMethod(); + IMethodSymbol getMethod = operation.Property.GetGetMethod()!; + ImmutableArray.Builder arguments = ImmutableArray.CreateBuilder(); + // Handle C# 14 extension property access (see comment in ProcessMethodCall) + if (getMethod.HasExtensionParameterOnType()) + { + arguments.Add(instanceValue); + instanceValue = TopValue; + } // Property may be an indexer, in which case there will be one or more index arguments - ImmutableArray.Builder arguments = ImmutableArray.CreateBuilder(); foreach (var val in operation.Arguments) arguments.Add(Visit(val, state)); - return HandleMethodCallHelper(getMethod!, instanceValue, arguments.ToImmutableArray(), operation, state); + return HandleMethodCallHelper(getMethod, instanceValue, arguments.ToImmutableArray(), operation, state); } public override TValue VisitEventReference(IEventReferenceOperation operation, LocalDataFlowState state) @@ -890,7 +904,7 @@ private TValue HandleMethodCallHelper( TConditionValue conditionValue = GetConditionValue(argumentOperation, state); var current = state.Current; ApplyCondition( - doesNotReturnIfConditionValue == false + !doesNotReturnIfConditionValue ? conditionValue : conditionValue.Negate(), ref current); @@ -910,6 +924,16 @@ private TValue ProcessMethodCall( TValue instanceValue = Visit(instance, state); var argumentsBuilder = ImmutableArray.CreateBuilder(); + + // For calls to C# 14 extensions, treat the instance argument as a regular argument. + // The extension method doesn't have an implicit this, yet (unlike for existing extension methods) + // the IOperation represents it as having an Instance. + if (method.HasExtensionParameterOnType()) + { + argumentsBuilder.Add(instanceValue); + instanceValue = TopValue; + } + foreach (var argument in arguments) { // For __arglist argument there might not be any parameter diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs index 31284d48b17d10..6f327374ee2cef 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs @@ -322,6 +322,11 @@ private static void VerifyDamOnPropertyAndAccessorMatch(SymbolAnalysisContext co || propertySymbol.GetDynamicallyAccessedMemberTypes() == DynamicallyAccessedMemberTypes.None) return; + // For C# 14 extension properties, property-level DAM does not propagate to accessors + // and we do not consider property vs accessor conflicts meaningful. Skip conflict checks. + if (methodSymbol.HasExtensionParameterOnType()) + return; + // None on the return type of 'get' matches unannotated if (methodSymbol.MethodKind == MethodKind.PropertyGet && methodSymbol.GetDynamicallyAccessedMemberTypesOnReturnType() != DynamicallyAccessedMemberTypes.None diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/ILLink.RoslynAnalyzer.csproj b/src/tools/illink/src/ILLink.RoslynAnalyzer/ILLink.RoslynAnalyzer.csproj index 49b09a3c07510b..e1b726443cb646 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/ILLink.RoslynAnalyzer.csproj +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/ILLink.RoslynAnalyzer.csproj @@ -10,7 +10,7 @@ $(NoWarn);CS8524 - $(NoWarn);CS0436 + $(NoWarn);CS0436 cs