From 644742da100d090c8c71cc722fb791714846899f Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Fri, 7 Jul 2023 12:01:23 +0200 Subject: [PATCH] Disallow applying `RequiresLocationAttribute` to parameters in source (#68871) --- .../CSharp/Portable/CSharpResources.resx | 3 + .../CSharp/Portable/Errors/ErrorCode.cs | 1 + .../CSharp/Portable/Errors/ErrorFacts.cs | 1 + .../Source/SourceComplexParameterSymbol.cs | 9 +- .../CSharp/Portable/Symbols/Symbol.cs | 5 + .../Portable/xlf/CSharpResources.cs.xlf | 5 + .../Portable/xlf/CSharpResources.de.xlf | 5 + .../Portable/xlf/CSharpResources.es.xlf | 5 + .../Portable/xlf/CSharpResources.fr.xlf | 5 + .../Portable/xlf/CSharpResources.it.xlf | 5 + .../Portable/xlf/CSharpResources.ja.xlf | 5 + .../Portable/xlf/CSharpResources.ko.xlf | 5 + .../Portable/xlf/CSharpResources.pl.xlf | 5 + .../Portable/xlf/CSharpResources.pt-BR.xlf | 5 + .../Portable/xlf/CSharpResources.ru.xlf | 5 + .../Portable/xlf/CSharpResources.tr.xlf | 5 + .../Portable/xlf/CSharpResources.zh-Hans.xlf | 5 + .../Portable/xlf/CSharpResources.zh-Hant.xlf | 5 + .../Semantics/RefReadonlyParameterTests.cs | 209 +++++++++++++++++- 19 files changed, 284 insertions(+), 9 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 6cdf980bcf2b5..258f1bfd72b96 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -5878,6 +5878,9 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ An in parameter cannot have the Out attribute. + + A ref readonly parameter cannot have the Out attribute. + {0} is not a valid C# compound assignment operation diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 01ddb4f35baea..cde7acbdec205 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2193,6 +2193,7 @@ internal enum ErrorCode ERR_UnsupportedPrimaryConstructorParameterCapturingRefAny = 9136, ERR_RefReadOnlyWrongOrdering = 9501, // PROTOTYPE: Pack numbers + ERR_OutAttrOnRefReadonlyParam = 9520, #endregion diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index 8876e2f8a8c57..e82b5f91694f2 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -2311,6 +2311,7 @@ internal static bool IsBuildOnlyDiagnostic(ErrorCode code) case ErrorCode.ERR_ConstantValueOfTypeExpected: case ErrorCode.ERR_UnsupportedPrimaryConstructorParameterCapturingRefAny: case ErrorCode.ERR_RefReadOnlyWrongOrdering: + case ErrorCode.ERR_OutAttrOnRefReadonlyParam: return false; default: // NOTE: All error codes must be explicitly handled in this switch statement diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs index 703fd450ca369..463f2457767be 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs @@ -802,7 +802,7 @@ protected override void DecodeWellKnownAttributeImpl(ref DecodeWellKnownAttribut else if (ReportExplicitUseOfReservedAttributes(in arguments, ReservedAttributes.DynamicAttribute | ReservedAttributes.IsReadOnlyAttribute | - // PROTOTYPE: RequiresLocationAttribute + ReservedAttributes.RequiresLocationAttribute | ReservedAttributes.IsUnmanagedAttribute | ReservedAttributes.IsByRefLikeAttribute | ReservedAttributes.TupleElementNamesAttribute | @@ -1412,6 +1412,13 @@ internal override void PostDecodeWellKnownAttributes(ImmutableArray arguments, ReservedAttributes reserved) @@ -1449,6 +1450,10 @@ internal bool ReportExplicitUseOfReservedAttributes(in DecodeWellKnownAttributeA reportExplicitUseOfReservedAttribute(attribute, arguments, AttributeDescription.IsReadOnlyAttribute)) { } + else if ((reserved & ReservedAttributes.RequiresLocationAttribute) != 0 && + reportExplicitUseOfReservedAttribute(attribute, arguments, AttributeDescription.RequiresLocationAttribute)) + { + } else if ((reserved & ReservedAttributes.IsUnmanagedAttribute) != 0 && reportExplicitUseOfReservedAttribute(attribute, arguments, AttributeDescription.IsUnmanagedAttribute)) { diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 8619d4cc3c4b8..890d6c0174fe9 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -1217,6 +1217,11 @@ Uživatelsky definovaný operátor {0} nejde deklarovat zaškrtnutý. + + A ref readonly parameter cannot have the Out attribute. + A ref readonly parameter cannot have the Out attribute. + + An out variable cannot be declared as a ref local Výstupní proměnná nemůže být deklarovaná jako lokální proměnná podle odkazu. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index c49e9051183d4..c69f4a1a911ff 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -1217,6 +1217,11 @@ Der benutzerdefinierte Operator "{0}" kann nicht als überprüft deklariert werden. + + A ref readonly parameter cannot have the Out attribute. + A ref readonly parameter cannot have the Out attribute. + + An out variable cannot be declared as a ref local Eine out-Variable kann nicht als lokales ref-Element deklariert werden. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index c693350fdac91..e831d06618215 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -1217,6 +1217,11 @@ El operador definido por el usuario '{0}' no se puede declarar como comprobado + + A ref readonly parameter cannot have the Out attribute. + A ref readonly parameter cannot have the Out attribute. + + An out variable cannot be declared as a ref local Una variable out no se puede declarar como ref local diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index dff17352fd1bd..4b3f0e4392e52 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -1217,6 +1217,11 @@ Impossible de vérifier l’opérateur défini par l’utilisateur '{0}' + + A ref readonly parameter cannot have the Out attribute. + A ref readonly parameter cannot have the Out attribute. + + An out variable cannot be declared as a ref local Impossible de déclarer une variable out en tant que variable locale ref diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 313a1abea70a4..b3049a4c2e392 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -1217,6 +1217,11 @@ Impossibile dichiarare controllato l'operatore '{0}' definito dall'utente + + A ref readonly parameter cannot have the Out attribute. + A ref readonly parameter cannot have the Out attribute. + + An out variable cannot be declared as a ref local Non è possibile dichiarare una variabile out come variabile locale ref diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 5dca7c5a0cfc0..a1f8c26099092 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -1217,6 +1217,11 @@ ユーザー定義演算子 '{0}' はチェック済みと宣言できません。 + + A ref readonly parameter cannot have the Out attribute. + A ref readonly parameter cannot have the Out attribute. + + An out variable cannot be declared as a ref local out 変数を ref ローカルと宣言することはできません diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index e8392a281e964..91af8c6f488ec 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -1217,6 +1217,11 @@ 사용자 정의 연산자 '{0}'은(는) 선언할 수 없습니다. + + A ref readonly parameter cannot have the Out attribute. + A ref readonly parameter cannot have the Out attribute. + + An out variable cannot be declared as a ref local 출력 변수는 참조 로컬로 선언할 수 없습니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 7519dd0fc60eb..b055daec385de 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -1217,6 +1217,11 @@ Nie można zadeklarować operatora „{0}” zdefiniowanego przez użytkownika + + A ref readonly parameter cannot have the Out attribute. + A ref readonly parameter cannot have the Out attribute. + + An out variable cannot be declared as a ref local Zmiennej out nie można zadeklarować jako lokalnej zmiennej ref diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 424d77f1f6979..a98185fd6fbb8 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -1217,6 +1217,11 @@ O operador definido pelo usuário '{0}' não pode ser declarado verificado + + A ref readonly parameter cannot have the Out attribute. + A ref readonly parameter cannot have the Out attribute. + + An out variable cannot be declared as a ref local Uma variável out não pode ser declarada como uma referência local diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 84867bb74ae4e..229d6372c8616 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -1217,6 +1217,11 @@ Невозможно объявить определяемый пользователем оператор "{0}" как проверенный + + A ref readonly parameter cannot have the Out attribute. + A ref readonly parameter cannot have the Out attribute. + + An out variable cannot be declared as a ref local Выходная переменная не может быть объявлена как локальная переменная ref diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 5d4459a4e665b..ad6249a2d1bab 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -1217,6 +1217,11 @@ Kullanıcı tanımlı '{0}' işleci işaretlenmiş olarak bildirilemiyor + + A ref readonly parameter cannot have the Out attribute. + A ref readonly parameter cannot have the Out attribute. + + An out variable cannot be declared as a ref local Bir out değişkeni ref yerel değeri olarak bildirilemez diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 229b08e63dbee..0c2e0857e1c24 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -1217,6 +1217,11 @@ 用户定义的运算符 '{0}' 无法声明为已验证 + + A ref readonly parameter cannot have the Out attribute. + A ref readonly parameter cannot have the Out attribute. + + An out variable cannot be declared as a ref local out 变量无法声明为 ref 局部变量 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 3c49c50692dd7..3634aab3de5ca 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -1217,6 +1217,11 @@ 使用者定義的運算子 '{0}' 無法宣告為已檢查 + + A ref readonly parameter cannot have the Out attribute. + A ref readonly parameter cannot have the Out attribute. + + An out variable cannot be declared as a ref local out 變數不可宣告為 ref local diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/RefReadonlyParameterTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/RefReadonlyParameterTests.cs index 7c874f65443c7..078f9565c47ee 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/RefReadonlyParameterTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/RefReadonlyParameterTests.cs @@ -18,6 +18,15 @@ public partial class RefReadonlyParameterTests : CSharpTestBase private const string RequiresLocationAttributeNamespace = "System.Runtime.CompilerServices"; private const string RequiresLocationAttributeQualifiedName = $"{RequiresLocationAttributeNamespace}.{RequiresLocationAttributeName}"; + private const string RequiresLocationAttributeDefinition = $$""" + namespace {{RequiresLocationAttributeNamespace}} + { + class {{RequiresLocationAttributeName}} : System.Attribute + { + } + } + """; + private static void VerifyRequiresLocationAttributeSynthesized(ModuleSymbol module) { var attributeType = module.GlobalNamespace.GetMember(RequiresLocationAttributeQualifiedName); @@ -96,17 +105,142 @@ static void verify(ModuleSymbol m) [Fact] public void ManuallyDefinedAttribute() { - var source = $$""" + var source = """ class C { public void M(ref readonly int p) { } } + """; + var verifier = CompileAndVerify(new[] { source, RequiresLocationAttributeDefinition }, + sourceSymbolValidator: verify, symbolValidator: verify); + verifier.VerifyDiagnostics(); + + static void verify(ModuleSymbol m) + { + var attribute = m.GlobalNamespace.GetMember(RequiresLocationAttributeQualifiedName); + Assert.NotNull(attribute); - namespace {{RequiresLocationAttributeNamespace}} + var p = m.GlobalNamespace.GetMember("C.M").Parameters.Single(); + VerifyRefReadonlyParameter(p); + } + } + + [Fact] + public void ManuallyAppliedAttribute() + { + var source = """ + using System.Runtime.CompilerServices; + [RequiresLocation] class C { - class {{RequiresLocationAttributeName}} : System.Attribute - { - } + void M1([RequiresLocation] ref readonly int p) { } + void M2([RequiresLocation] in int p) { } + void M3([RequiresLocation] ref int p) { } + void M4([RequiresLocation] int p) { } + [return: RequiresLocation] int M5() => 5; + [return: RequiresLocation] ref int M6() => throw null; + [return: RequiresLocation] ref readonly int M7() => throw null; + [RequiresLocation] void M8() { } + } + """; + + CreateCompilation(new[] { source, RequiresLocationAttributeDefinition }, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // 0.cs(4,14): error CS8335: Do not use 'System.Runtime.CompilerServices.RequiresLocationAttribute'. This is reserved for compiler usage. + // void M1([RequiresLocation] ref readonly int p) { } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "RequiresLocation").WithArguments("System.Runtime.CompilerServices.RequiresLocationAttribute").WithLocation(4, 14), + // 0.cs(4,36): error CS8652: The feature 'ref readonly parameters' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // void M1([RequiresLocation] ref readonly int p) { } + Diagnostic(ErrorCode.ERR_FeatureInPreview, "readonly").WithArguments("ref readonly parameters").WithLocation(4, 36), + // 0.cs(5,14): error CS8335: Do not use 'System.Runtime.CompilerServices.RequiresLocationAttribute'. This is reserved for compiler usage. + // void M2([RequiresLocation] in int p) { } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "RequiresLocation").WithArguments("System.Runtime.CompilerServices.RequiresLocationAttribute").WithLocation(5, 14), + // 0.cs(6,14): error CS8335: Do not use 'System.Runtime.CompilerServices.RequiresLocationAttribute'. This is reserved for compiler usage. + // void M3([RequiresLocation] ref int p) { } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "RequiresLocation").WithArguments("System.Runtime.CompilerServices.RequiresLocationAttribute").WithLocation(6, 14), + // 0.cs(7,14): error CS8335: Do not use 'System.Runtime.CompilerServices.RequiresLocationAttribute'. This is reserved for compiler usage. + // void M4([RequiresLocation] int p) { } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "RequiresLocation").WithArguments("System.Runtime.CompilerServices.RequiresLocationAttribute").WithLocation(7, 14)); + + var expectedDiagnostics = new[] + { + // 0.cs(4,14): error CS8335: Do not use 'System.Runtime.CompilerServices.RequiresLocationAttribute'. This is reserved for compiler usage. + // void M1([RequiresLocation] ref readonly int p) { } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "RequiresLocation").WithArguments("System.Runtime.CompilerServices.RequiresLocationAttribute").WithLocation(4, 14), + // 0.cs(5,14): error CS8335: Do not use 'System.Runtime.CompilerServices.RequiresLocationAttribute'. This is reserved for compiler usage. + // void M2([RequiresLocation] in int p) { } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "RequiresLocation").WithArguments("System.Runtime.CompilerServices.RequiresLocationAttribute").WithLocation(5, 14), + // 0.cs(6,14): error CS8335: Do not use 'System.Runtime.CompilerServices.RequiresLocationAttribute'. This is reserved for compiler usage. + // void M3([RequiresLocation] ref int p) { } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "RequiresLocation").WithArguments("System.Runtime.CompilerServices.RequiresLocationAttribute").WithLocation(6, 14), + // 0.cs(7,14): error CS8335: Do not use 'System.Runtime.CompilerServices.RequiresLocationAttribute'. This is reserved for compiler usage. + // void M4([RequiresLocation] int p) { } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "RequiresLocation").WithArguments("System.Runtime.CompilerServices.RequiresLocationAttribute").WithLocation(7, 14) + }; + + CreateCompilation(new[] { source, RequiresLocationAttributeDefinition }, parseOptions: TestOptions.RegularNext).VerifyDiagnostics(expectedDiagnostics); + CreateCompilation(new[] { source, RequiresLocationAttributeDefinition }).VerifyDiagnostics(expectedDiagnostics); + } + + [Fact] + public void ManuallyAppliedAttribute_NotDefined() + { + var source = """ + using System.Runtime.CompilerServices; + class C + { + void M([RequiresLocation] ref int p) { } + } + """; + + CreateCompilation(source).VerifyDiagnostics( + // (1,1): hidden CS8019: Unnecessary using directive. + // using System.Runtime.CompilerServices; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using System.Runtime.CompilerServices;").WithLocation(1, 1), + // (4,13): error CS0246: The type or namespace name 'RequiresLocationAttribute' could not be found (are you missing a using directive or an assembly reference?) + // void M([RequiresLocation] ref int p) { } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "RequiresLocation").WithArguments("RequiresLocationAttribute").WithLocation(4, 13), + // (4,13): error CS0246: The type or namespace name 'RequiresLocation' could not be found (are you missing a using directive or an assembly reference?) + // void M([RequiresLocation] ref int p) { } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "RequiresLocation").WithArguments("RequiresLocation").WithLocation(4, 13)); + + CreateCompilation(new[] { source, RequiresLocationAttributeDefinition }).VerifyDiagnostics( + // 0.cs(4,13): error CS8335: Do not use 'System.Runtime.CompilerServices.RequiresLocationAttribute'. This is reserved for compiler usage. + // void M([RequiresLocation] ref int p) { } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "RequiresLocation").WithArguments("System.Runtime.CompilerServices.RequiresLocationAttribute").WithLocation(4, 13)); + } + + [Fact] + public void ManuallyAppliedAttributes_RequiresLocationIn() + { + var source = """ + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + class C + { + void M1([RequiresLocation, In] ref int p) { } + void M2([RequiresLocation, In] in int p) { } + void M3([RequiresLocation, In] int p) { } + } + """; + CreateCompilation(new[] { source, RequiresLocationAttributeDefinition }).VerifyDiagnostics( + // 0.cs(5,14): error CS8335: Do not use 'System.Runtime.CompilerServices.RequiresLocationAttribute'. This is reserved for compiler usage. + // void M1([RequiresLocation, In] ref int p) { } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "RequiresLocation").WithArguments("System.Runtime.CompilerServices.RequiresLocationAttribute").WithLocation(5, 14), + // 0.cs(6,14): error CS8335: Do not use 'System.Runtime.CompilerServices.RequiresLocationAttribute'. This is reserved for compiler usage. + // void M2([RequiresLocation, In] in int p) { } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "RequiresLocation").WithArguments("System.Runtime.CompilerServices.RequiresLocationAttribute").WithLocation(6, 14), + // 0.cs(7,14): error CS8335: Do not use 'System.Runtime.CompilerServices.RequiresLocationAttribute'. This is reserved for compiler usage. + // void M3([RequiresLocation, In] int p) { } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "RequiresLocation").WithArguments("System.Runtime.CompilerServices.RequiresLocationAttribute").WithLocation(7, 14)); + } + + [Fact] + public void ManuallyAppliedAttributes_In() + { + var source = """ + using System.Runtime.InteropServices; + class C + { + public void M([In] ref readonly int p) { } } """; var verifier = CompileAndVerify(source, sourceSymbolValidator: verify, symbolValidator: verify); @@ -114,14 +248,73 @@ class {{RequiresLocationAttributeName}} : System.Attribute static void verify(ModuleSymbol m) { - var attribute = m.GlobalNamespace.GetMember(RequiresLocationAttributeQualifiedName); - Assert.NotNull(attribute); + VerifyRequiresLocationAttributeSynthesized(m); var p = m.GlobalNamespace.GetMember("C.M").Parameters.Single(); - VerifyRefReadonlyParameter(p); + VerifyRefReadonlyParameter(p, attributes: m is not SourceModuleSymbol); + if (m is SourceModuleSymbol) + { + var attribute = Assert.Single(p.GetAttributes()); + Assert.Equal("System.Runtime.InteropServices.InAttribute", attribute.AttributeClass.ToTestDisplayString()); + Assert.Empty(attribute.ConstructorArguments); + Assert.Empty(attribute.NamedArguments); + } } } + [Fact] + public void ManuallyAppliedAttributes_InOut() + { + var source = """ + using System.Runtime.InteropServices; + class C + { + void M1([Out] ref readonly int p) { } + void M2([In, Out] ref readonly int p) { } + } + """; + CreateCompilation(source).VerifyDiagnostics( + // (4,36): error CS9520: A ref readonly parameter cannot have the Out attribute. + // void M1([Out] ref readonly int p) { } + Diagnostic(ErrorCode.ERR_OutAttrOnRefReadonlyParam, "p").WithLocation(4, 36), + // (5,40): error CS9520: A ref readonly parameter cannot have the Out attribute. + // void M2([In, Out] ref readonly int p) { } + Diagnostic(ErrorCode.ERR_OutAttrOnRefReadonlyParam, "p").WithLocation(5, 40)); + } + + [Fact] + public void ManuallyAppliedAttributes_IsReadOnly() + { + var source = """ + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + class C + { + void M1([IsReadOnly] ref readonly int p) { } + void M2([In, IsReadOnly] ref readonly int p) { } + void M3([In, RequiresLocation, IsReadOnly] ref int p) { } + } + + namespace System.Runtime.CompilerServices + { + public class IsReadOnlyAttribute : System.Attribute { } + } + """; + CreateCompilation(new[] { source, RequiresLocationAttributeDefinition }).VerifyDiagnostics( + // 0.cs(5,14): error CS8335: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage. + // void M1([IsReadOnly] ref readonly int p) { } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsReadOnly").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(5, 14), + // 0.cs(6,18): error CS8335: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage. + // void M2([In, IsReadOnly] ref readonly int p) { } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsReadOnly").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(6, 18), + // 0.cs(7,18): error CS8335: Do not use 'System.Runtime.CompilerServices.RequiresLocationAttribute'. This is reserved for compiler usage. + // void M3([In, RequiresLocation, IsReadOnly] ref int p) { } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "RequiresLocation").WithArguments("System.Runtime.CompilerServices.RequiresLocationAttribute").WithLocation(7, 18), + // 0.cs(7,36): error CS8335: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage. + // void M3([In, RequiresLocation, IsReadOnly] ref int p) { } + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsReadOnly").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(7, 36)); + } + [Fact] public void BothAttributes() {