Skip to content

Commit 7fa23f4

Browse files
authored
Track used assemblies of data section string literals (#78552)
* Track used assemblies of data section string literals * Move reporting to module * Fix a failing test * Improve test * Add a comment
1 parent 0d6bd9d commit 7fa23f4

File tree

3 files changed

+102
-62
lines changed

3 files changed

+102
-62
lines changed

src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3487,13 +3487,6 @@ private void EmitConstantExpression(TypeSymbol type, ConstantValue constantValue
34873487
}
34883488
else
34893489
{
3490-
// TODO: use-site dependencies are not reported to UsedAssemblyReferences https://github.com/dotnet/roslyn/issues/78172
3491-
if (constantValue.IsString && constantValue.StringValue.Length > _module.Compilation.DataSectionStringLiteralThreshold)
3492-
{
3493-
_ = Binder.GetWellKnownTypeMember(_module.Compilation, WellKnownMember.System_Text_Encoding__get_UTF8, _diagnostics, syntax: syntaxNode);
3494-
_ = Binder.GetWellKnownTypeMember(_module.Compilation, WellKnownMember.System_Text_Encoding__GetString, _diagnostics, syntax: syntaxNode);
3495-
}
3496-
34973490
_builder.EmitConstantValue(constantValue, syntaxNode);
34983491
}
34993492
}

src/Compilers/CSharp/Portable/Symbols/Source/SourceModuleSymbol.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,14 @@ internal override void ForceComplete(SourceLocation? locationOpt, Predicate<Symb
244244
ValidateLinkedAssemblies(diagnostics, cancellationToken);
245245
}
246246

247+
// If "data section string literals" are enabled, check the necessary APIs are available so used assemblies are tracked correctly.
248+
if (this.DeclaringCompilation.DataSectionStringLiteralThreshold != null)
249+
{
250+
diagnostics ??= BindingDiagnosticBag.GetInstance();
251+
_ = Binder.GetWellKnownTypeMember(this.DeclaringCompilation, WellKnownMember.System_Text_Encoding__get_UTF8, diagnostics, NoLocation.Singleton);
252+
_ = Binder.GetWellKnownTypeMember(this.DeclaringCompilation, WellKnownMember.System_Text_Encoding__GetString, diagnostics, NoLocation.Singleton);
253+
}
254+
247255
if (_state.NotePartComplete(CompletionPart.StartValidatingReferencedAssemblies))
248256
{
249257
if (diagnostics != null)

src/Compilers/CSharp/Test/Emit/Emit/EmitMetadataTests.cs

Lines changed: 94 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2949,74 +2949,42 @@ public void DataSectionStringLiterals_MissingMembers()
29492949

29502950
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithFeature("experimental-data-section-string-literals", "0"));
29512951
comp.MakeMemberMissing(WellKnownMember.System_Text_Encoding__get_UTF8);
2952-
comp.VerifyEmitDiagnostics(
2953-
// (1,22): error CS0656: Missing compiler required member 'System.Text.Encoding.get_UTF8'
2954-
// System.Console.Write("a");
2955-
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"""a""").WithArguments("System.Text.Encoding", "get_UTF8").WithLocation(1, 22),
2956-
// (2,22): error CS0656: Missing compiler required member 'System.Text.Encoding.get_UTF8'
2957-
// System.Console.Write("bb");
2958-
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"""bb""").WithArguments("System.Text.Encoding", "get_UTF8").WithLocation(2, 22),
2959-
// (3,22): error CS0656: Missing compiler required member 'System.Text.Encoding.get_UTF8'
2960-
// System.Console.Write("ccc");
2961-
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"""ccc""").WithArguments("System.Text.Encoding", "get_UTF8").WithLocation(3, 22));
2952+
comp.VerifyDiagnostics(
2953+
// error CS0656: Missing compiler required member 'System.Text.Encoding.get_UTF8'
2954+
Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.Text.Encoding", "get_UTF8").WithLocation(1, 1));
29622955

29632956
comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithFeature("experimental-data-section-string-literals", "0"));
29642957
comp.MakeMemberMissing(WellKnownMember.System_Text_Encoding__GetString);
2965-
comp.VerifyEmitDiagnostics(
2966-
// (1,22): error CS0656: Missing compiler required member 'System.Text.Encoding.GetString'
2967-
// System.Console.Write("a");
2968-
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"""a""").WithArguments("System.Text.Encoding", "GetString").WithLocation(1, 22),
2969-
// (2,22): error CS0656: Missing compiler required member 'System.Text.Encoding.GetString'
2970-
// System.Console.Write("bb");
2971-
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"""bb""").WithArguments("System.Text.Encoding", "GetString").WithLocation(2, 22),
2972-
// (3,22): error CS0656: Missing compiler required member 'System.Text.Encoding.GetString'
2973-
// System.Console.Write("ccc");
2974-
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"""ccc""").WithArguments("System.Text.Encoding", "GetString").WithLocation(3, 22));
2958+
comp.VerifyDiagnostics(
2959+
// error CS0656: Missing compiler required member 'System.Text.Encoding.GetString'
2960+
Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.Text.Encoding", "GetString").WithLocation(1, 1));
29752961

29762962
comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithFeature("experimental-data-section-string-literals", "0"));
29772963
comp.MakeMemberMissing(WellKnownMember.System_Text_Encoding__get_UTF8);
29782964
comp.MakeMemberMissing(WellKnownMember.System_Text_Encoding__GetString);
2979-
comp.VerifyEmitDiagnostics(
2980-
// (1,22): error CS0656: Missing compiler required member 'System.Text.Encoding.get_UTF8'
2981-
// System.Console.Write("a");
2982-
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"""a""").WithArguments("System.Text.Encoding", "get_UTF8").WithLocation(1, 22),
2983-
// (1,22): error CS0656: Missing compiler required member 'System.Text.Encoding.GetString'
2984-
// System.Console.Write("a");
2985-
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"""a""").WithArguments("System.Text.Encoding", "GetString").WithLocation(1, 22),
2986-
// (2,22): error CS0656: Missing compiler required member 'System.Text.Encoding.get_UTF8'
2987-
// System.Console.Write("bb");
2988-
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"""bb""").WithArguments("System.Text.Encoding", "get_UTF8").WithLocation(2, 22),
2989-
// (2,22): error CS0656: Missing compiler required member 'System.Text.Encoding.GetString'
2990-
// System.Console.Write("bb");
2991-
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"""bb""").WithArguments("System.Text.Encoding", "GetString").WithLocation(2, 22),
2992-
// (3,22): error CS0656: Missing compiler required member 'System.Text.Encoding.get_UTF8'
2993-
// System.Console.Write("ccc");
2994-
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"""ccc""").WithArguments("System.Text.Encoding", "get_UTF8").WithLocation(3, 22),
2995-
// (3,22): error CS0656: Missing compiler required member 'System.Text.Encoding.GetString'
2996-
// System.Console.Write("ccc");
2997-
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"""ccc""").WithArguments("System.Text.Encoding", "GetString").WithLocation(3, 22));
2965+
comp.VerifyDiagnostics(
2966+
// error CS0656: Missing compiler required member 'System.Text.Encoding.get_UTF8'
2967+
Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.Text.Encoding", "get_UTF8").WithLocation(1, 1),
2968+
// error CS0656: Missing compiler required member 'System.Text.Encoding.GetString'
2969+
Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.Text.Encoding", "GetString").WithLocation(1, 1));
29982970

29992971
comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithFeature("experimental-data-section-string-literals", "1"));
30002972
comp.MakeMemberMissing(WellKnownMember.System_Text_Encoding__get_UTF8);
30012973
comp.MakeMemberMissing(WellKnownMember.System_Text_Encoding__GetString);
3002-
comp.VerifyEmitDiagnostics(
3003-
// (2,26): error CS0656: Missing compiler required member 'System.Text.Encoding.get_UTF8'
3004-
// System.Console.Write("bb");
3005-
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"""bb""").WithArguments("System.Text.Encoding", "get_UTF8").WithLocation(2, 22),
3006-
// (2,26): error CS0656: Missing compiler required member 'System.Text.Encoding.GetString'
3007-
// System.Console.Write("bb");
3008-
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"""bb""").WithArguments("System.Text.Encoding", "GetString").WithLocation(2, 22),
3009-
// (3,22): error CS0656: Missing compiler required member 'System.Text.Encoding.get_UTF8'
3010-
// System.Console.Write("ccc");
3011-
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"""ccc""").WithArguments("System.Text.Encoding", "get_UTF8").WithLocation(3, 22),
3012-
// (3,22): error CS0656: Missing compiler required member 'System.Text.Encoding.GetString'
3013-
// System.Console.Write("ccc");
3014-
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"""ccc""").WithArguments("System.Text.Encoding", "GetString").WithLocation(3, 22));
2974+
comp.VerifyDiagnostics(
2975+
// error CS0656: Missing compiler required member 'System.Text.Encoding.get_UTF8'
2976+
Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.Text.Encoding", "get_UTF8").WithLocation(1, 1),
2977+
// error CS0656: Missing compiler required member 'System.Text.Encoding.GetString'
2978+
Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.Text.Encoding", "GetString").WithLocation(1, 1));
30152979

30162980
comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithFeature("experimental-data-section-string-literals", "3"));
30172981
comp.MakeMemberMissing(WellKnownMember.System_Text_Encoding__get_UTF8);
30182982
comp.MakeMemberMissing(WellKnownMember.System_Text_Encoding__GetString);
3019-
CompileAndVerify(comp, expectedOutput: "abbccc").VerifyDiagnostics();
2983+
comp.VerifyDiagnostics(
2984+
// error CS0656: Missing compiler required member 'System.Text.Encoding.get_UTF8'
2985+
Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.Text.Encoding", "get_UTF8").WithLocation(1, 1),
2986+
// error CS0656: Missing compiler required member 'System.Text.Encoding.GetString'
2987+
Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.Text.Encoding", "GetString").WithLocation(1, 1));
30202988
}
30212989

30222990
[Fact]
@@ -3204,6 +3172,68 @@ .locals init (int V_0,
32043172
""");
32053173
}
32063174

3175+
[Theory]
3176+
[InlineData("""public static string M() => "abc";""")]
3177+
[InlineData("""public static void M(string s) { switch (s) { case "abc": break; } }""")]
3178+
public void DataSectionStringLiterals_UsedAssemblyReferences(string code)
3179+
{
3180+
var source1 = """
3181+
namespace System
3182+
{
3183+
public class Object;
3184+
public class String
3185+
{
3186+
public static bool op_Equality(string a, string b) => false;
3187+
}
3188+
public class ValueType;
3189+
public struct Void;
3190+
public struct Byte;
3191+
public struct Int16;
3192+
public struct Int32;
3193+
public struct Int64;
3194+
public struct Boolean;
3195+
public class Attribute;
3196+
public class Enum;
3197+
public enum AttributeTargets;
3198+
public class AttributeUsageAttribute
3199+
{
3200+
public AttributeUsageAttribute(AttributeTargets validOn) { }
3201+
public bool AllowMultiple { get; set; }
3202+
public bool Inherited { get; set; }
3203+
}
3204+
}
3205+
""";
3206+
var ref1 = CreateEmptyCompilation(source1, assemblyName: "MinimalCoreLib").VerifyDiagnostics().EmitToImageReference();
3207+
3208+
var source2 = """
3209+
namespace System.Text
3210+
{
3211+
public class Encoding
3212+
{
3213+
public static Encoding UTF8 => null;
3214+
public unsafe string GetString(byte* bytes, int byteCount) => null;
3215+
}
3216+
}
3217+
""";
3218+
var ref2 = CreateEmptyCompilation(source2, [ref1], options: TestOptions.UnsafeDebugDll, assemblyName: "Encoding")
3219+
.VerifyDiagnostics().EmitToImageReference();
3220+
3221+
var source3 = $$"""
3222+
public static class C
3223+
{
3224+
{{code}}
3225+
}
3226+
""";
3227+
var comp = CreateEmptyCompilation(source3, [ref1, ref2], assemblyName: "Lib1");
3228+
AssertEx.SetEqual([ref1], comp.GetUsedAssemblyReferences());
3229+
comp.VerifyEmitDiagnostics();
3230+
3231+
comp = CreateEmptyCompilation(source3, [ref1, ref2], assemblyName: "Lib2",
3232+
parseOptions: TestOptions.Regular.WithFeature("experimental-data-section-string-literals", "0"));
3233+
AssertEx.SetEqual([ref1, ref2], comp.GetUsedAssemblyReferences());
3234+
comp.VerifyEmitDiagnostics();
3235+
}
3236+
32073237
[Fact]
32083238
public void DataSectionStringLiterals_InvalidUtf8()
32093239
{
@@ -3561,8 +3591,7 @@ public class InvalidOperationException();
35613591
""";
35623592

35633593
var parseOptions = TestOptions.RegularPreview
3564-
.WithNoRefSafetyRulesAttribute()
3565-
.WithFeature("experimental-data-section-string-literals", "0");
3594+
.WithNoRefSafetyRulesAttribute();
35663595

35673596
CompileAndVerify(CreateEmptyCompilation(source, parseOptions: parseOptions),
35683597
verify: Verification.Skipped,
@@ -3587,6 +3616,16 @@ public class InvalidOperationException();
35873616
.VerifyDiagnostics(
35883617
// warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
35893618
Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion).WithLocation(1, 1));
3619+
3620+
// NOTE: If the feature is enabled by default in the future, it should not fail in case of missing Encoding members
3621+
// (it should be automatically disabled instead and could warn) to avoid regressing the scenario above.
3622+
CreateEmptyCompilation(source,
3623+
parseOptions: parseOptions.WithFeature("experimental-data-section-string-literals", "0"))
3624+
.VerifyDiagnostics(
3625+
// error CS0656: Missing compiler required member 'System.Text.Encoding.get_UTF8'
3626+
Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.Text.Encoding", "get_UTF8").WithLocation(1, 1),
3627+
// error CS0656: Missing compiler required member 'System.Text.Encoding.GetString'
3628+
Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.Text.Encoding", "GetString").WithLocation(1, 1));
35903629
}
35913630

35923631
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/76707")]

0 commit comments

Comments
 (0)