提交 a4d9f3c4 编写于 作者: O Omar Tawfik 提交者: GitHub

In parameters cannot have Out attributes (#22645)

* In parameters cannot have Out attributes

* PR feedback

* Follow up
上级 3d77c977
......@@ -7397,7 +7397,16 @@ internal class CSharpResources {
}
/// <summary>
/// Looks up a localized string similar to Cannot specify only Out attribute on a ref parameter. Use both In and Out attributes, or neither..
/// Looks up a localized string similar to An in parameter cannot have the Out attribute..
/// </summary>
internal static string ERR_OutAttrOnInParam {
get {
return ResourceManager.GetString("ERR_OutAttrOnInParam", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cannot specify the Out attribute on a ref parameter without also specifying the In attribute..
/// </summary>
internal static string ERR_OutAttrOnRefParam {
get {
......
......@@ -1833,7 +1833,7 @@ If such a class is used as a base class and if the deriving class defines a dest
<value>Type defines operator == or operator != but does not override Object.GetHashCode()</value>
</data>
<data name="ERR_OutAttrOnRefParam" xml:space="preserve">
<value>Cannot specify only Out attribute on a ref parameter. Use both In and Out attributes, or neither.</value>
<value>Cannot specify the Out attribute on a ref parameter without also specifying the In attribute.</value>
</data>
<data name="ERR_OverloadRefKind" xml:space="preserve">
<value>'{0}' cannot define an overloaded {1} that differs only on parameter modifiers '{2}' and '{3}'</value>
......@@ -5210,4 +5210,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_RefExtensionMustBeValueTypeOrConstrainedToOne" xml:space="preserve">
<value>The first parameter of a 'ref' extension method '{0}' must be a value type or a generic type constrained to struct.</value>
</data>
<data name="ERR_OutAttrOnInParam" xml:space="preserve">
<value>An in parameter cannot have the Out attribute.</value>
</data>
</root>
\ No newline at end of file
......@@ -1536,6 +1536,7 @@ internal enum ErrorCode
ERR_EscapeLocal = 8352,
ERR_EscapeStackAlloc = 8353,
ERR_RefReturnThis = 8354,
ERR_OutAttrOnInParam = 8355,
#endregion diagnostics introduced for `ref readonly`, `ref ternary` and `ref-like` features in C# 7.2
}
}
......@@ -521,15 +521,7 @@ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArgu
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.InAttribute))
{
if (this.RefKind == RefKind.Out)
{
// error CS0036: An out parameter cannot have the In attribute
arguments.Diagnostics.Add(ErrorCode.ERR_InAttrOnOutParam, arguments.AttributeSyntaxOpt.Name.Location);
}
else
{
arguments.GetOrCreateData<CommonParameterWellKnownAttributeData>().HasInAttribute = true;
}
arguments.GetOrCreateData<CommonParameterWellKnownAttributeData>().HasInAttribute = true;
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.OutAttribute))
{
......@@ -860,10 +852,29 @@ internal override void PostDecodeWellKnownAttributes(ImmutableArray<CSharpAttrib
var data = (CommonParameterWellKnownAttributeData)decodedData;
if (data != null)
{
if (this.RefKind == RefKind.Ref && data.HasOutAttribute && !data.HasInAttribute)
switch (RefKind)
{
// error CS0662: '...' cannot specify only Out attribute on a ref parameter. Use both In and Out attributes, or neither.
diagnostics.Add(ErrorCode.ERR_OutAttrOnRefParam, this.Locations[0]);
case RefKind.Ref:
if (data.HasOutAttribute && !data.HasInAttribute)
{
// error CS0662: Cannot specify the Out attribute on a ref parameter without also specifying the In attribute.
diagnostics.Add(ErrorCode.ERR_OutAttrOnRefParam, this.Locations[0]);
}
break;
case RefKind.Out:
if (data.HasInAttribute)
{
// error CS0036: An out parameter cannot have the In attribute.
diagnostics.Add(ErrorCode.ERR_InAttrOnOutParam, this.Locations[0]);
}
break;
case RefKind.In:
if (data.HasOutAttribute)
{
// error CS8355: An in parameter cannot have the Out attribute.
diagnostics.Add(ErrorCode.ERR_OutAttrOnInParam, this.Locations[0]);
}
break;
}
}
......
......@@ -2026,29 +2026,117 @@ class C
}
[Fact]
public void InOutAttributes_Errors()
public void InAttribute_RefParameter()
{
var source = @"
CreateStandardCompilation(@"
using System.Runtime.InteropServices;
class C
{
public static void M([In]ref int p) { }
}").VerifyDiagnostics();
}
[Fact]
public void OutAttribute_RefParameter()
{
CreateStandardCompilation(@"
using System.Runtime.InteropServices;
class C
{
public static void E1([In]out int b) { }
public static void E2([Out]ref int a) { }
public static void E3([In, Out]out int a) { }
}
";
CreateStandardCompilation(source).VerifyDiagnostics(
// (6,28): error CS0036: An out parameter cannot have the In attribute
Diagnostic(ErrorCode.ERR_InAttrOnOutParam, "In"),
// (7,27): error CS0662: Cannot specify only Out attribute on a ref parameter. Use both In and Out attributes, or neither.
Diagnostic(ErrorCode.ERR_OutAttrOnRefParam, "a"),
// (8,28): error CS0036: An out parameter cannot have the In attribute
Diagnostic(ErrorCode.ERR_InAttrOnOutParam, "In"),
// (6,24): error CS0177: The out parameter 'b' must be assigned to before control leaves the current method
Diagnostic(ErrorCode.ERR_ParamUnassigned, "E1").WithArguments("b"),
// (8,24): error CS0177: The out parameter 'a' must be assigned to before control leaves the current method
Diagnostic(ErrorCode.ERR_ParamUnassigned, "E3").WithArguments("a"));
public static void M([Out]ref int p) { }
}").VerifyDiagnostics(
// (5,39): error CS0662: Cannot specify the Out attribute on a ref parameter without also specifying the In attribute.
// public static void M([Out]ref int p) { }
Diagnostic(ErrorCode.ERR_OutAttrOnRefParam, "p").WithLocation(5, 39));
}
[Fact]
public void InAndOutAttributes_RefParameter()
{
CreateStandardCompilation(@"
using System.Runtime.InteropServices;
class C
{
public static void M([In, Out]ref int p) { }
}").VerifyDiagnostics();
}
[Fact]
public void InAttribute_OutParameter()
{
CreateStandardCompilation(@"
using System.Runtime.InteropServices;
class C
{
public static void M([In]out int p) { p = 0; }
}").VerifyDiagnostics(
// (5,38): error CS0036: An out parameter cannot have the In attribute
// public static void M([In]out int p) { p = 0; }
Diagnostic(ErrorCode.ERR_InAttrOnOutParam, "p").WithLocation(5, 38));
}
[Fact]
public void OutAttribute_OutParameter()
{
CreateStandardCompilation(@"
using System.Runtime.InteropServices;
class C
{
public static void M([Out]out int p) { p = 0; }
}").VerifyDiagnostics();
}
[Fact]
public void InAndOutAttributes_OutParameter()
{
CreateStandardCompilation(@"
using System.Runtime.InteropServices;
class C
{
public static void M([In, Out]out int p) { p = 0; }
}").VerifyDiagnostics(
// (5,43): error CS0036: An out parameter cannot have the In attribute
// public static void M([In, Out]out int p) { p = 0; }
Diagnostic(ErrorCode.ERR_InAttrOnOutParam, "p").WithLocation(5, 43));
}
[Fact]
public void InAttribute_InParameter()
{
CreateStandardCompilation(@"
using System.Runtime.InteropServices;
class C
{
public static void M([In]in int p) { }
}").VerifyDiagnostics();
}
[Fact]
public void OutAttribute_InParameter()
{
CreateStandardCompilation(@"
using System.Runtime.InteropServices;
class C
{
public static void M([Out]in int p) { }
}").VerifyDiagnostics(
// (5,38): error CS8355: An in parameter cannot have the Out attribute.
// public static void M([Out]in int p) { }
Diagnostic(ErrorCode.ERR_OutAttrOnInParam, "p").WithLocation(5, 38));
}
[Fact]
public void OutAndInAttributes_InParameter()
{
CreateStandardCompilation(@"
using System.Runtime.InteropServices;
class C
{
public static void M([Out, In]in int p) { }
}").VerifyDiagnostics(
// (5,42): error CS8355: An in parameter cannot have the Out attribute.
// public static void M([Out, In]in int p) { }
Diagnostic(ErrorCode.ERR_OutAttrOnInParam, "p").WithLocation(5, 42));
}
[Fact]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册