提交 605886a5 编写于 作者: O Omar Tawfik

Merge branch 'master' of https://github.com/dotnet/roslyn into remove-ref-readonly-parameters

......@@ -21,7 +21,7 @@ class Awaiter<T> : INotifyCompletion
{
public bool IsCompleted { get; }
public T GetResult();
public void OnCompletion(Action completion);
public void OnCompleted(Action completion);
}
```
## Builder Type
......
......@@ -99,27 +99,27 @@ internal enum BindValueKind : byte
ReadonlyRef = RefersToLocation | RValue,
/// <summary>
/// Expression is passed as a ref or out parameter or assigned to a byref variable.
/// Expression can be the operand of an address-of operation (&amp;).
/// Same as ReadonlyRef. The difference is just for error reporting.
/// </summary>
RefOrOut = RefersToLocation | RValue | Assignable,
AddressOf = ReadonlyRef + 1,
/// <summary>
/// Expression can be the operand of an address-of operation (&amp;).
/// Same as RefOrOut. The difference is just for error reporting.
/// Expression is the receiver of a fixed buffer field access
/// Same as ReadonlyRef. The difference is just for error reporting.
/// </summary>
AddressOf = RefOrOut + 1,
FixedReceiver = ReadonlyRef + 2,
/// <summary>
/// Expression is the receiver of a fixed buffer field access
/// Same as RefOrOut. The difference is just for error reporting.
/// Expression is passed as a ref or out parameter or assigned to a byref variable.
/// </summary>
FixedReceiver = RefOrOut + 2,
RefOrOut = RefersToLocation | RValue | Assignable,
/// <summary>
/// Expression is returned by an ordinary r/w reference.
/// Same as RefOrOut. The difference is just for error reporting.
/// </summary>
RefReturn = RefOrOut + 3,
RefReturn = RefOrOut + 1,
}
private static bool RequiresRValueOnly(BindValueKind kind)
......@@ -395,7 +395,9 @@ internal bool CheckValueKind(SyntaxNode node, BoundExpression expr, BindValueKin
// Note: RValueOnly is checked at the beginning of this method. Since we are here we need more than readable.
//"this" is readonly in members of readonly structs, unless we are in a constructor.
if (!thisref.Type.IsValueType ||
(thisref.Type.IsReadOnly && (this.ContainingMemberOrLambda as MethodSymbol)?.MethodKind != MethodKind.Constructor))
(RequiresAssignableVariable(valueKind) &&
thisref.Type.IsReadOnly &&
(this.ContainingMemberOrLambda as MethodSymbol)?.MethodKind != MethodKind.Constructor))
{
// CONSIDER: the Dev10 name has angle brackets (i.e. "<this>")
Error(diagnostics, GetThisLvalueError(valueKind), node, ThisParameterSymbol.SymbolName);
......@@ -1369,12 +1371,6 @@ private static void ReportReadonlyLocalError(SyntaxNode node, LocalSymbol local,
return;
}
if (kind == BindValueKind.AddressOf)
{
Error(diagnostics, ErrorCode.ERR_AddrOnReadOnlyLocal, node);
return;
}
ErrorCode[] ReadOnlyLocalErrors =
{
ErrorCode.ERR_RefReadonlyLocalCause,
......@@ -1401,7 +1397,7 @@ static private ErrorCode GetThisLvalueError(BindValueKind kind)
return ErrorCode.ERR_RefReadonlyLocal;
case BindValueKind.AddressOf:
return ErrorCode.ERR_AddrOnReadOnlyLocal;
return ErrorCode.ERR_InvalidAddrOp;
case BindValueKind.IncrementDecrement:
return ErrorCode.ERR_IncrementLvalueExpected;
......
......@@ -578,8 +578,12 @@ private TypeSymbol BindNamedAttributeArgumentType(AttributeArgumentSyntax namedA
if (parameter.IsParams && parameter.Type.IsSZArray() && i + 1 == parameterCount)
{
reorderedArgument = GetParamArrayArgument(parameter, constructorArgsArray, argumentsCount, argsConsumedCount, this.Conversions);
sourceIndices = sourceIndices ?? CreateSourceIndicesArray(i, parameterCount);
reorderedArgument = GetParamArrayArgument(parameter, constructorArgsArray, constructorArgumentNamesOpt, argumentsCount,
argsConsumedCount, this.Conversions, out bool foundNamed);
if (!foundNamed)
{
sourceIndices = sourceIndices ?? CreateSourceIndicesArray(i, parameterCount);
}
}
else if (argsConsumedCount < argumentsCount)
{
......@@ -820,41 +824,48 @@ private TypedConstant GetDefaultValueArgument(ParameterSymbol parameter, Attribu
}
}
private static TypedConstant GetParamArrayArgument(ParameterSymbol parameter, ImmutableArray<TypedConstant> constructorArgsArray, int argumentsCount, int argsConsumedCount, Conversions conversions)
private static TypedConstant GetParamArrayArgument(ParameterSymbol parameter, ImmutableArray<TypedConstant> constructorArgsArray,
ImmutableArray<string> constructorArgumentNamesOpt, int argumentsCount, int argsConsumedCount, Conversions conversions, out bool foundNamed)
{
Debug.Assert(argsConsumedCount <= argumentsCount);
// If there's a named argument, we'll use that
if (!constructorArgumentNamesOpt.IsDefault)
{
int argIndex = constructorArgumentNamesOpt.IndexOf(parameter.Name);
if (argIndex >= 0)
{
foundNamed = true;
if (TryGetNormalParamValue(parameter, constructorArgsArray, argIndex, conversions, out var namedValue))
{
return namedValue;
}
// A named argument for a params parameter is necessarily the only one for that parameter
return new TypedConstant(parameter.Type, ImmutableArray.Create(constructorArgsArray[argIndex]));
}
}
int paramArrayArgCount = argumentsCount - argsConsumedCount;
foundNamed = false;
// If there are zero arguments left
if (paramArrayArgCount == 0)
{
return new TypedConstant(parameter.Type, ImmutableArray<TypedConstant>.Empty);
}
// If there's exactly one argument and it's an array of an appropriate type, then just return it.
if (paramArrayArgCount == 1 && constructorArgsArray[argsConsumedCount].Kind == TypedConstantKind.Array)
// If there's exactly one argument left, we'll try to use it in normal form
if (paramArrayArgCount == 1 &&
TryGetNormalParamValue(parameter, constructorArgsArray, argsConsumedCount, conversions, out var lastValue))
{
TypeSymbol argumentType = (TypeSymbol)constructorArgsArray[argsConsumedCount].Type;
// Easy out (i.e. don't both classifying conversion).
if (argumentType == parameter.Type)
{
return constructorArgsArray[argsConsumedCount];
}
HashSet<DiagnosticInfo> useSiteDiagnostics = null; // ignoring, since already bound argument and parameter
Conversion conversion = conversions.ClassifyBuiltInConversion(argumentType, parameter.Type, ref useSiteDiagnostics);
// NOTE: Won't always succeed, even though we've performed overload resolution.
// For example, passing int[] to params object[] actually treats the int[] as an element of the object[].
if (conversion.IsValid && conversion.Kind == ConversionKind.ImplicitReference)
{
return constructorArgsArray[argsConsumedCount];
}
return lastValue;
}
Debug.Assert(!constructorArgsArray.IsDefault);
Debug.Assert(argsConsumedCount <= constructorArgsArray.Length);
// Take the trailing arguments as an array for expanded form
var values = new TypedConstant[paramArrayArgCount];
for (int i = 0; i < paramArrayArgCount; i++)
......@@ -865,6 +876,39 @@ private static TypedConstant GetParamArrayArgument(ParameterSymbol parameter, Im
return new TypedConstant(parameter.Type, values.AsImmutableOrNull());
}
private static bool TryGetNormalParamValue(ParameterSymbol parameter, ImmutableArray<TypedConstant> constructorArgsArray,
int argIndex, Conversions conversions, out TypedConstant result)
{
TypedConstant argument = constructorArgsArray[argIndex];
if (argument.Kind != TypedConstantKind.Array)
{
result = default;
return false;
}
TypeSymbol argumentType = (TypeSymbol)argument.Type;
// Easy out (i.e. don't bother classifying conversion).
if (argumentType == parameter.Type)
{
result = argument;
return true;
}
HashSet<DiagnosticInfo> useSiteDiagnostics = null; // ignoring, since already bound argument and parameter
Conversion conversion = conversions.ClassifyBuiltInConversion(argumentType, parameter.Type, ref useSiteDiagnostics);
// NOTE: Won't always succeed, even though we've performed overload resolution.
// For example, passing int[] to params object[] actually treats the int[] as an element of the object[].
if (conversion.IsValid && conversion.Kind == ConversionKind.ImplicitReference)
{
result = argument;
return true;
}
result = default;
return false;
}
#endregion
#region AttributeExpressionVisitor
......
......@@ -241,15 +241,6 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to Cannot take the address of a read-only local variable.
/// </summary>
internal static string ERR_AddrOnReadOnlyLocal {
get {
return ResourceManager.GetString("ERR_AddrOnReadOnlyLocal", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Agnostic assembly cannot have a processor specific module &apos;{0}&apos;..
/// </summary>
......@@ -8493,18 +8484,16 @@ internal class CSharpResources {
return ResourceManager.GetString("ERR_RefReturnNonreturnableLocal2", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cannot return a parameter by reference &apos;{0}&apos; because it is not a ref or out parameter.
/// </summary>
internal static string ERR_RefReturnParameter
{
get
{
internal static string ERR_RefReturnParameter {
get {
return ResourceManager.GetString("ERR_RefReturnParameter", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cannot return by reference a member of parameter &apos;{0}&apos; because it is not a ref or out parameter.
/// </summary>
......
......@@ -1356,9 +1356,6 @@
<data name="WRN_AlwaysNull_Title" xml:space="preserve">
<value>The result of the expression is always 'null'</value>
</data>
<data name="ERR_AddrOnReadOnlyLocal" xml:space="preserve">
<value>Cannot take the address of a read-only local variable</value>
</data>
<data name="ERR_RefReturnThis" xml:space="preserve">
<value>Cannot return 'this' by reference.</value>
</data>
......
......@@ -2336,7 +2336,9 @@ private void EmitAssignmentValue(BoundAssignmentOperator assignmentOperator)
{
int exprTempsBefore = _expressionTemps?.Count ?? 0;
LocalDefinition temp = EmitAddress(assignmentOperator.Right, AddressKind.Writeable);
// NOTE: passing "ReadOnly" here. Assuming we do not have compile errors,
// We should not get an address of a copy, even if the RHS is readonly
LocalDefinition temp = EmitAddress(assignmentOperator.Right, AddressKind.ReadOnly);
// Generally taking a ref for the purpose of ref assignment should not be done on homeless values
// however, there are very rare cases when we need to get a ref off a temp in synthetic code.
......
......@@ -311,7 +311,7 @@ internal enum ErrorCode
ERR_ConWithValCon = 456,
ERR_AmbigUDConv = 457,
WRN_AlwaysNull = 458,
ERR_AddrOnReadOnlyLocal = 459,
// ERR_AddrOnReadOnlyLocal = 459, // no longer an error
ERR_OverrideWithConstraints = 460,
ERR_AmbigOverride = 462,
ERR_DecConstError = 463,
......
......@@ -6,7 +6,6 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
using Microsoft.CodeAnalysis.CSharp.Syntax;
......@@ -62,6 +61,286 @@ class C
CompileAndVerify(source, sourceSymbolValidator: attributeValidator, symbolValidator: null);
}
[Fact]
[WorkItem(20741, "https://github.com/dotnet/roslyn/issues/20741")]
public void TestNamedArgumentOnStringParamsArgument()
{
var comp = CreateCompilationWithMscorlib46(@"
using System;
class MarkAttribute : Attribute
{
public MarkAttribute(bool a, params object[] b)
{
}
}
[Mark(b: new string[] { ""Hello"", ""World"" }, a: true)]
[Mark(b: ""Hello"", true)]
static class Program
{
}", parseOptions: TestOptions.Regular7_2);
comp.VerifyDiagnostics(
// (11,2): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
// [Mark(b: new string[] { "Hello", "World" }, a: true)]
Diagnostic(ErrorCode.ERR_BadAttributeArgument, @"Mark(b: new string[] { ""Hello"", ""World"" }, a: true)").WithLocation(11, 2),
// (12,7): error CS8323: Named argument 'b' is used out-of-position but is followed by an unnamed argument
// [Mark(b: "Hello", true)]
Diagnostic(ErrorCode.ERR_BadNonTrailingNamedArgument, "b").WithArguments("b").WithLocation(12, 7)
);
}
[Fact]
[WorkItem(20741, "https://github.com/dotnet/roslyn/issues/20741")]
public void TestNamedArgumentOnOrderedObjectParamsArgument()
{
var comp = CreateCompilationWithMscorlib46(@"
using System;
using System.Reflection;
sealed class MarkAttribute : Attribute
{
public MarkAttribute(bool a, params object[] b)
{
B = b;
}
public object[] B { get; }
}
[Mark(a: true, b: new object[] { ""Hello"", ""World"" })]
static class Program
{
public static void Main()
{
var attr = typeof(Program).GetCustomAttribute<MarkAttribute>();
Console.Write($""B.Length={attr.B.Length}, B[0]={attr.B[0]}, B[1]={attr.B[1]}"");
}
}", options: TestOptions.DebugExe);
comp.VerifyDiagnostics();
CompileAndVerify(comp, expectedOutput: @"B.Length=2, B[0]=Hello, B[1]=World");
var program = (NamedTypeSymbol)comp.GetMember("Program");
var attributeData = (SourceAttributeData)program.GetAttributes()[0];
Assert.Equal(new[] { 0, -1 }, attributeData.ConstructorArgumentsSourceIndices);
}
[Fact]
[WorkItem(20741, "https://github.com/dotnet/roslyn/issues/20741")]
public void TestNamedArgumentOnObjectParamsArgument()
{
var comp = CreateCompilationWithMscorlib46(@"
using System;
using System.Reflection;
sealed class MarkAttribute : Attribute
{
public MarkAttribute(bool a, params object[] b)
{
B = b;
}
public object[] B { get; }
}
[Mark(b: new object[] { ""Hello"", ""World"" }, a: true)]
static class Program
{
public static void Main()
{
var attr = typeof(Program).GetCustomAttribute<MarkAttribute>();
Console.Write($""B.Length={attr.B.Length}, B[0]={attr.B[0]}, B[1]={attr.B[1]}"");
}
}", options: TestOptions.DebugExe);
comp.VerifyDiagnostics();
CompileAndVerify(comp, expectedOutput: @"B.Length=2, B[0]=Hello, B[1]=World");
var program = (NamedTypeSymbol)comp.GetMember("Program");
var attributeData = (SourceAttributeData)program.GetAttributes()[0];
Assert.Equal(new[] { 1, -1 }, attributeData.ConstructorArgumentsSourceIndices);
}
[Fact]
[WorkItem(20741, "https://github.com/dotnet/roslyn/issues/20741")]
public void TestNamedArgumentOnObjectParamsArgument2()
{
var comp = CreateCompilationWithMscorlib46(@"
using System;
using System.Reflection;
sealed class MarkAttribute : Attribute
{
public MarkAttribute(bool a, params object[] b)
{
A = a;
B = b;
}
public bool A { get; }
public object[] B { get; }
}
[Mark(b: ""Hello"", a: true)]
static class Program
{
public static void Main()
{
var attr = typeof(Program).GetCustomAttribute<MarkAttribute>();
Console.Write($""A={attr.A}, B.Length={attr.B.Length}, B[0]={attr.B[0]}"");
}
}", options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_2);
comp.VerifyDiagnostics();
CompileAndVerify(comp, expectedOutput: @"A=True, B.Length=1, B[0]=Hello");
var program = (NamedTypeSymbol)comp.GetMember("Program");
var attributeData = (SourceAttributeData)program.GetAttributes()[0];
Assert.Equal(new[] { 1, -1 }, attributeData.ConstructorArgumentsSourceIndices);
}
[Fact]
[WorkItem(20741, "https://github.com/dotnet/roslyn/issues/20741")]
public void TestNamedArgumentOnObjectParamsArgument3()
{
var comp = CreateCompilationWithMscorlib46(@"
using System;
using System.Reflection;
sealed class MarkAttribute : Attribute
{
public MarkAttribute(bool a, params object[] b)
{
B = b;
}
public object[] B { get; }
}
[Mark(true, new object[] { ""Hello"" }, new object[] { ""World"" })]
static class Program
{
public static void Main()
{
var attr = typeof(Program).GetCustomAttribute<MarkAttribute>();
var worldArray = (object[])attr.B[1];
Console.Write(worldArray[0]);
}
}", options: TestOptions.DebugExe);
comp.VerifyDiagnostics();
CompileAndVerify(comp, expectedOutput: @"World");
var program = (NamedTypeSymbol)comp.GetMember("Program");
var attributeData = (SourceAttributeData)program.GetAttributes()[0];
Assert.Equal(new[] { 0, -1 }, attributeData.ConstructorArgumentsSourceIndices);
}
[Fact]
[WorkItem(20741, "https://github.com/dotnet/roslyn/issues/20741")]
public void TestNamedArgumentOnObjectParamsArgument4()
{
var comp = CreateCompilationWithMscorlib46(@"
using System;
using System.Reflection;
sealed class MarkAttribute : Attribute
{
public MarkAttribute(bool a, params object[] b)
{
B = b;
}
public object[] B { get; }
}
[Mark(a: true, new object[] { ""Hello"" }, new object[] { ""World"" })]
static class Program
{
public static void Main()
{
var attr = typeof(Program).GetCustomAttribute<MarkAttribute>();
var worldArray = (object[])attr.B[1];
Console.Write(worldArray[0]);
}
}", options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_2);
comp.VerifyDiagnostics();
CompileAndVerify(comp, expectedOutput: @"World");
var program = (NamedTypeSymbol)comp.GetMember("Program");
var attributeData = (SourceAttributeData)program.GetAttributes()[0];
Assert.Equal(new[] { 0, -1 }, attributeData.ConstructorArgumentsSourceIndices);
}
[Fact]
[WorkItem(20741, "https://github.com/dotnet/roslyn/issues/20741")]
public void TestNamedArgumentOnObjectParamsArgument5()
{
var comp = CreateCompilationWithMscorlib46(@"
using System;
using System.Reflection;
sealed class MarkAttribute : Attribute
{
public MarkAttribute(bool a, params object[] b)
{
B = b;
}
public object[] B { get; }
}
[Mark(b: null, a: true)]
static class Program
{
public static void Main()
{
var attr = typeof(Program).GetCustomAttribute<MarkAttribute>();
Console.Write(attr.B == null);
}
}", options: TestOptions.DebugExe);
comp.VerifyDiagnostics();
CompileAndVerify(comp, expectedOutput: @"True");
var program = (NamedTypeSymbol)comp.GetMember("Program");
var attributeData = (SourceAttributeData)program.GetAttributes()[0];
Assert.Equal(new[] { 1, -1 }, attributeData.ConstructorArgumentsSourceIndices);
}
[Fact]
[WorkItem(20741, "https://github.com/dotnet/roslyn/issues/20741")]
public void TestNamedArgumentOnNonParamsArgument()
{
var comp = CreateCompilationWithMscorlib46(@"
using System;
using System.Reflection;
sealed class MarkAttribute : Attribute
{
public MarkAttribute(int a, int b)
{
A = a;
B = b;
}
public int A { get; }
public int B { get; }
}
[Mark(b: 42, a: 1)]
static class Program
{
public static void Main()
{
var attr = typeof(Program).GetCustomAttribute<MarkAttribute>();
Console.Write($""A={attr.A}, B={attr.B}"");
}
}", options: TestOptions.DebugExe);
comp.VerifyDiagnostics();
CompileAndVerify(comp, expectedOutput: "A=1, B=42");
var program = (NamedTypeSymbol)comp.GetMember("Program");
var attributeData = (SourceAttributeData)program.GetAttributes()[0];
Assert.Equal(new[] { 1, 0 }, attributeData.ConstructorArgumentsSourceIndices);
}
[WorkItem(984896, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/984896")]
[Fact]
public void TestAssemblyAttributesErr()
......
......@@ -464,6 +464,7 @@ static void M(in int arg1, in (int Alice, int Bob) arg2)
Diagnostic(ErrorCode.ERR_RefReadonlyNotField2, "arg2.Alice").WithArguments("variable", "in (int Alice, int Bob)"));
}
[WorkItem(22306, "https://github.com/dotnet/roslyn/issues/22306")]
[Fact]
public void InParamCannotTakePtr()
{
......@@ -488,18 +489,12 @@ unsafe static void M(in int arg1, in (int Alice, int Bob) arg2)
var comp = CreateCompilationWithMscorlib45(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.UnsafeReleaseDll);
comp.VerifyDiagnostics(
// (6,20): error CS0211: Cannot take the address of the given expression
// (6,18): error CS0212: You can only take the address of an unfixed expression inside of a fixed statement initializer
// int* a = & arg1;
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "arg1").WithLocation(6, 20),
// (7,20): error CS0211: Cannot take the address of the given expression
Diagnostic(ErrorCode.ERR_FixedNeeded, "& arg1").WithLocation(6, 18),
// (7,18): error CS0212: You can only take the address of an unfixed expression inside of a fixed statement initializer
// int* b = & arg2.Alice;
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "arg2.Alice").WithLocation(7, 20),
// (9,26): error CS0211: Cannot take the address of the given expression
// fixed(int* c = & arg1)
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "arg1").WithLocation(9, 26),
// (13,26): error CS0211: Cannot take the address of the given expression
// fixed(int* d = & arg2.Alice)
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "arg2.Alice").WithLocation(13, 26)
Diagnostic(ErrorCode.ERR_FixedNeeded, "& arg2.Alice").WithLocation(7, 18)
);
}
......
......@@ -13,7 +13,7 @@ public class CodeGenRefReadOnlyReturnTests : CompilingTestBase
[Fact]
public void RefReadonlyLocalToField()
{
var comp = CompileAndVerify(@"
var source = @"
struct S
{
public int X;
......@@ -52,7 +52,9 @@ class C
return ref rs1;
}
}");
}";
var comp = CompileAndVerify(source, parseOptions: TestOptions.Regular.WithPEVerifyCompatFeature());
comp.VerifyIL("C.M", @"
{
// Code size 65 (0x41)
......@@ -82,6 +84,31 @@ .maxstack 2
IL_003b: call ""void S2.AddOne()""
IL_0040: ret
}");
comp = CompileAndVerify(source, verify: false);
comp.VerifyIL("C.M", @"
{
// Code size 59 (0x3b)
.maxstack 2
.locals init (S V_0)
IL_0000: ldsflda ""S C.s1""
IL_0005: dup
IL_0006: ldobj ""S""
IL_000b: stloc.0
IL_000c: ldloca.s V_0
IL_000e: call ""void S.AddOne()""
IL_0013: ldsflda ""S C.s2""
IL_0018: ldobj ""S""
IL_001d: stloc.0
IL_001e: ldloca.s V_0
IL_0020: call ""void S.AddOne()""
IL_0025: ldsflda ""S2 C.s3""
IL_002a: call ""void S2.AddOne()""
IL_002f: ldarg.0
IL_0030: ldflda ""S2 C.s4""
IL_0035: call ""void S2.AddOne()""
IL_003a: ret
}");
}
[Fact]
......@@ -343,15 +370,11 @@ static void M()
}");
verifier.VerifyIL("C.M()", @"
{
// Code size 11 (0xb)
// Code size 7 (0x7)
.maxstack 1
.locals init (int V_0)
IL_0000: call ""ref readonly int C.Helper()""
IL_0005: ldind.i4
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0009: pop
IL_000a: ret
IL_0005: pop
IL_0006: ret
}");
}
......@@ -618,30 +641,18 @@ unsafe static void Test()
var comp = CreateCompilationWithMscorlib45(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.UnsafeReleaseDll);
comp.VerifyDiagnostics(
// (6,20): error CS0211: Cannot take the address of the given expression
// (6,18): error CS0212: You can only take the address of an unfixed expression inside of a fixed statement initializer
// int* a = & M();
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "M()").WithLocation(6, 20),
// (7,20): error CS0211: Cannot take the address of the given expression
Diagnostic(ErrorCode.ERR_FixedNeeded, "& M()").WithLocation(6, 18),
// (7,18): error CS0212: You can only take the address of an unfixed expression inside of a fixed statement initializer
// int* b = & M1().Alice;
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "M1().Alice").WithLocation(7, 20),
// (9,21): error CS0211: Cannot take the address of the given expression
Diagnostic(ErrorCode.ERR_FixedNeeded, "& M1().Alice").WithLocation(7, 18),
// (9,19): error CS0212: You can only take the address of an unfixed expression inside of a fixed statement initializer
// int* a1 = & P;
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "P").WithLocation(9, 21),
// (10,21): error CS0211: Cannot take the address of the given expression
Diagnostic(ErrorCode.ERR_FixedNeeded, "& P").WithLocation(9, 19),
// (10,19): error CS0212: You can only take the address of an unfixed expression inside of a fixed statement initializer
// int* b2 = & P1.Alice;
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "P1.Alice").WithLocation(10, 21),
// (12,26): error CS0211: Cannot take the address of the given expression
// fixed(int* c = & M())
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "M()").WithLocation(12, 26),
// (16,26): error CS0211: Cannot take the address of the given expression
// fixed(int* d = & M1().Alice)
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "M1().Alice").WithLocation(16, 26),
// (20,26): error CS0211: Cannot take the address of the given expression
// fixed(int* c = & P)
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "P").WithLocation(20, 26),
// (24,26): error CS0211: Cannot take the address of the given expression
// fixed(int* d = & P1.Alice)
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "P1.Alice").WithLocation(24, 26)
Diagnostic(ErrorCode.ERR_FixedNeeded, "& P1.Alice").WithLocation(10, 19)
);
}
......
......@@ -1226,6 +1226,73 @@ .locals init (pinned int& V_0)
");
}
[Fact]
public void FixedStatementThis()
{
var text = @"
public class Program
{
public static void Main()
{
S1 s = default;
s.Test();
}
unsafe readonly struct S1
{
readonly int x;
public void Test()
{
fixed(void* p = &this)
{
*(int*)p = 123;
}
ref readonly S1 r = ref this;
fixed (S1* p = &r)
{
System.Console.WriteLine(p->x);
}
}
}
}
";
var compVerifier = CompileAndVerify(text, options: TestOptions.UnsafeReleaseExe, expectedOutput: @"123");
compVerifier.VerifyIL("Program.S1.Test()", @"
{
// Code size 30 (0x1e)
.maxstack 2
.locals init (void* V_0, //p
pinned Program.S1& V_1)
IL_0000: ldarg.0
IL_0001: stloc.1
IL_0002: ldloc.1
IL_0003: conv.u
IL_0004: stloc.0
IL_0005: ldloc.0
IL_0006: ldc.i4.s 123
IL_0008: stind.i4
IL_0009: ldc.i4.0
IL_000a: conv.u
IL_000b: stloc.1
IL_000c: ldarg.0
IL_000d: stloc.1
IL_000e: ldloc.1
IL_000f: conv.u
IL_0010: ldfld ""int Program.S1.x""
IL_0015: call ""void System.Console.WriteLine(int)""
IL_001a: ldc.i4.0
IL_001b: conv.u
IL_001c: stloc.1
IL_001d: ret
}
");
}
[WorkItem(22306, "https://github.com/dotnet/roslyn/issues/22306")]
[Fact]
public void FixedStatementMultipleFields()
{
......@@ -1235,7 +1302,7 @@ public void FixedStatementMultipleFields()
unsafe class C
{
int x;
int y;
readonly int y;
static void Main()
{
......@@ -1292,6 +1359,77 @@ .maxstack 4
");
}
[WorkItem(22306, "https://github.com/dotnet/roslyn/issues/22306")]
[Fact]
public void FixedStatementMultipleMethods()
{
var text = @"
using System;
unsafe class C
{
int x;
readonly int y;
ref int X()=>ref x;
ref readonly int this[int i]=>ref y;
static void Main()
{
C c = new C();
fixed (int* p = &c.X(), q = &c[3])
{
*p = 1;
*q = 2;
}
Console.Write(c.x);
Console.Write(c.y);
}
}
";
var compVerifier = CompileAndVerify(text, options: TestOptions.UnsafeReleaseExe, expectedOutput: @"12");
compVerifier.VerifyIL("C.Main", @"
{
// Code size 58 (0x3a)
.maxstack 4
.locals init (int* V_0, //p
pinned int& V_1,
pinned int& V_2)
IL_0000: newobj ""C..ctor()""
IL_0005: dup
IL_0006: callvirt ""ref int C.X()""
IL_000b: stloc.1
IL_000c: ldloc.1
IL_000d: conv.u
IL_000e: stloc.0
IL_000f: dup
IL_0010: ldc.i4.3
IL_0011: callvirt ""ref readonly int C.this[int].get""
IL_0016: stloc.2
IL_0017: ldloc.2
IL_0018: conv.u
IL_0019: ldloc.0
IL_001a: ldc.i4.1
IL_001b: stind.i4
IL_001c: ldc.i4.2
IL_001d: stind.i4
IL_001e: ldc.i4.0
IL_001f: conv.u
IL_0020: stloc.1
IL_0021: ldc.i4.0
IL_0022: conv.u
IL_0023: stloc.2
IL_0024: dup
IL_0025: ldfld ""int C.x""
IL_002a: call ""void System.Console.Write(int)""
IL_002f: ldfld ""int C.y""
IL_0034: call ""void System.Console.Write(int)""
IL_0039: ret
}
");
}
[WorkItem(546866, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546866")]
[Fact]
public void FixedStatementProperty()
......
......@@ -1371,33 +1371,29 @@ public unsafe void M1()
int[] ints = new int[] { 1, 2, 3 };
foreach (int i in ints)
{
int *j = &i; // CS0459
int *j = &i;
}
fixed (int *i = &_i)
{
int **j = &i; // CS0459
int **j = &i;
}
}
private int _i = 0;
}";
CreateCompilationWithMscorlib45(source, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.RegularWithIOperationFeature)
.VerifyDiagnostics(Diagnostic(ErrorCode.ERR_InvalidAddrOp, "a + b").WithLocation(7, 18),
Diagnostic(ErrorCode.ERR_AddrOnReadOnlyLocal, "i").WithLocation(28, 23),
Diagnostic(ErrorCode.ERR_AddrOnReadOnlyLocal, "i").WithLocation(33, 24))
.VerifyDiagnostics(Diagnostic(ErrorCode.ERR_InvalidAddrOp, "a + b").WithLocation(7, 18))
.VerifyAnalyzerDiagnostics(new DiagnosticAnalyzer[] { new AddressOfTestAnalyzer() }, null, null, false,
Diagnostic(AddressOfTestAnalyzer.AddressOfDescriptor.Id, "&(a + b)").WithLocation(7, 16),
Diagnostic(AddressOfTestAnalyzer.InvalidAddressOfReferenceDescriptor.Id, "a + b").WithLocation(7, 18),
Diagnostic(AddressOfTestAnalyzer.AddressOfDescriptor.Id, "&a").WithLocation(9, 16),
Diagnostic(AddressOfTestAnalyzer.AddressOfDescriptor.Id, "&x").WithLocation(15, 17),
Diagnostic(AddressOfTestAnalyzer.AddressOfDescriptor.Id, "&(*p)").WithLocation(16, 12),
Diagnostic(AddressOfTestAnalyzer.AddressOfDescriptor.Id, "&p[0]").WithLocation(17, 12),
Diagnostic(AddressOfTestAnalyzer.AddressOfDescriptor.Id, "&i").WithLocation(28, 22),
Diagnostic(AddressOfTestAnalyzer.InvalidAddressOfReferenceDescriptor.Id, "i").WithLocation(28, 23),
Diagnostic(AddressOfTestAnalyzer.AddressOfDescriptor.Id, "&_i").WithLocation(31, 25),
Diagnostic(AddressOfTestAnalyzer.AddressOfDescriptor.Id, "&i").WithLocation(33, 23),
Diagnostic(AddressOfTestAnalyzer.InvalidAddressOfReferenceDescriptor.Id, "i").WithLocation(33, 24));
Diagnostic("AddressOfOperation", "&(a + b)").WithLocation(7, 16),
Diagnostic("InvalidAddressOfReference", "a + b").WithLocation(7, 18),
Diagnostic("AddressOfOperation", "&a").WithLocation(9, 16),
Diagnostic("AddressOfOperation", "&i").WithLocation(28, 22),
Diagnostic("AddressOfOperation", "&_i").WithLocation(31, 25),
Diagnostic("AddressOfOperation", "&i").WithLocation(33, 23),
Diagnostic("AddressOfOperation", "&x").WithLocation(15, 17),
Diagnostic("AddressOfOperation", "&(*p)").WithLocation(16, 12),
Diagnostic("AddressOfOperation", "&p[0]").WithLocation(17, 12));
}
[Fact]
......
......@@ -287,14 +287,12 @@ void M1()
Right: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Int32, IsInvalid) (Syntax: '&p1')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand: IAddressOfExpression (OperationKind.AddressOfExpression, Type: System.Int32**, IsInvalid) (Syntax: '&p1')
Reference: IInvalidExpression (OperationKind.InvalidExpression, Type: System.Int32*, IsInvalid) (Syntax: 'p1')
Children(1):
ILocalReferenceExpression: p1 (OperationKind.LocalReferenceExpression, Type: System.Int32*, IsInvalid) (Syntax: 'p1')
Reference: ILocalReferenceExpression: p1 (OperationKind.LocalReferenceExpression, Type: System.Int32*, IsInvalid) (Syntax: 'p1')
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0459: Cannot take the address of a read-only local variable
// file.cs(15,22): error CS0266: Cannot implicitly convert type 'int**' to 'int'. An explicit conversion exists (are you missing a cast?)
// i3 = &p1;
Diagnostic(ErrorCode.ERR_AddrOnReadOnlyLocal, "p1").WithLocation(15, 23)
Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "&p1").WithArguments("int**", "int").WithLocation(15, 22)
};
VerifyOperationTreeAndDiagnosticsForTest<FixedStatementSyntax>(source, expectedOperationTree, expectedDiagnostics,
......
......@@ -10260,8 +10260,9 @@ public static void Main()
Diagnostic(ErrorCode.ERR_AmbigUDConv, "h1a").WithArguments("H1<A>.implicit operator G1<A>(H1<A>)", "H0.implicit operator G0(H0)", "H1<A>", "G0"));
}
[WorkItem(22306, "https://github.com/dotnet/roslyn/issues/22306")]
[Fact]
public void CS0459ERR_AddrOnReadOnlyLocal()
public void AddrOnReadOnlyLocal()
{
var text = @"
class A
......@@ -10271,25 +10272,19 @@ public unsafe void M1()
int[] ints = new int[] { 1, 2, 3 };
foreach (int i in ints)
{
int *j = &i; // CS0459
int *j = &i;
}
fixed (int *i = &_i)
{
int **j = &i; // CS0459
int **j = &i;
}
}
private int _i = 0;
}
";
CreateStandardCompilation(text, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (9,23): error CS0459: Cannot take the address of a read-only local variable
// int *j = &i; // CS0459
Diagnostic(ErrorCode.ERR_AddrOnReadOnlyLocal, "i"),
// (14,24): error CS0459: Cannot take the address of a read-only local variable
// int **j = &i; // CS0459
Diagnostic(ErrorCode.ERR_AddrOnReadOnlyLocal, "i"));
CreateStandardCompilation(text, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics();
}
[Fact]
......
......@@ -3123,6 +3123,7 @@ int M(int param)
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "x").WithArguments("x"));
}
[WorkItem(22306, "https://github.com/dotnet/roslyn/issues/22306")]
[Fact]
public void AddressOfExpressionKinds_ReadOnlyLocal()
{
......@@ -3142,17 +3143,17 @@ void M()
foreach (int y in new int[1])
{
p = &y; //CS0459
p = &y;
}
using (S s = new S())
{
S* sp = &s; //CS0459
S* sp = &s;
}
fixed (int* a = &array[0])
{
int** pp = &a; //CS0459
int** pp = &a;
}
}
}
......@@ -3165,19 +3166,11 @@ struct S : System.IDisposable
CreateCompilationWithMscorlibAndSystemCore(text, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (13,14): error CS0211: Cannot take the address of the given expression
// p = &x; //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "x"),
// (17,18): error CS0459: Cannot take the address of a read-only local variable
// p = &y; //CS0459
Diagnostic(ErrorCode.ERR_AddrOnReadOnlyLocal, "y"),
// (22,22): error CS0459: Cannot take the address of a read-only local variable
// S* sp = &s; //CS0459
Diagnostic(ErrorCode.ERR_AddrOnReadOnlyLocal, "s"),
// (27,25): error CS0459: Cannot take the address of a read-only local variable
// int** pp = &a; //CS0459
Diagnostic(ErrorCode.ERR_AddrOnReadOnlyLocal, "a"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "x").WithLocation(13, 14),
// (6,11): warning CS0649: Field 'C.array' is never assigned to, and will always have its default value null
// int[] array;
Diagnostic(ErrorCode.WRN_UnassignedInternalField, "array").WithArguments("C.array", "null"));
Diagnostic(ErrorCode.WRN_UnassignedInternalField, "array").WithArguments("C.array", "null").WithLocation(6, 11)
);
}
[Fact]
......@@ -3242,7 +3235,7 @@ int M(int param)
var w = &(F += null); //CS0211
var x = &(array is object); //CS0211
var y = &(array ?? array); //CS0208, CS0211 (managed)
var aa = &this; //CS0208, CS0459 (readonly)
var aa = &this; //CS0208
var bb = &typeof(int); //CS0208, CS0211 (managed)
var cc = &Color.Red; //CS0211
......@@ -3268,120 +3261,121 @@ enum Color
}
";
CreateStandardCompilation(text, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (76,18): error CS0212: You can only take the address of an unfixed expression inside of a fixed statement initializer
// var aa = &this; //CS0212 (need fixed)
Diagnostic(ErrorCode.ERR_FixedNeeded, "&this").WithLocation(76, 18),
// (23,14): error CS0211: Cannot take the address of the given expression
// p = &1; //CS0211 (can't addr)
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "1"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "1").WithLocation(23, 14),
// (24,13): error CS0212: You can only take the address of an unfixed expression inside of a fixed statement initializer
// p = &array[0]; //CS0212 (need fixed)
Diagnostic(ErrorCode.ERR_FixedNeeded, "&array[0]"),
Diagnostic(ErrorCode.ERR_FixedNeeded, "&array[0]").WithLocation(24, 13),
// (25,15): error CS0211: Cannot take the address of the given expression
// p = &(local = 1); //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "local = 1"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "local = 1").WithLocation(25, 15),
// (26,14): error CS0103: The name 'goo' does not exist in the current context
// p = &goo; //CS0103 (no goo)
Diagnostic(ErrorCode.ERR_NameNotInContext, "goo").WithArguments("goo"),
Diagnostic(ErrorCode.ERR_NameNotInContext, "goo").WithArguments("goo").WithLocation(26, 14),
// (27,13): error CS0212: You can only take the address of an unfixed expression inside of a fixed statement initializer
// p = &base.f; //CS0212
Diagnostic(ErrorCode.ERR_FixedNeeded, "&base.f"),
Diagnostic(ErrorCode.ERR_FixedNeeded, "&base.f").WithLocation(27, 13),
// (28,15): error CS0211: Cannot take the address of the given expression
// p = &(local + local); //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "local + local"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "local + local").WithLocation(28, 15),
// (29,14): error CS0211: Cannot take the address of the given expression
// p = &M(local); //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "M(local)"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "M(local)").WithLocation(29, 14),
// (30,14): error CS0211: Cannot take the address of the given expression
// p = &func(); //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "func()"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "func()").WithLocation(30, 14),
// (31,15): error CS0211: Cannot take the address of the given expression
// p = &(local += local); //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "local += local"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "local += local").WithLocation(31, 15),
// (32,15): error CS0211: Cannot take the address of the given expression
// p = &(local == 0 ? local : param); //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "local == 0 ? local : param"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "local == 0 ? local : param").WithLocation(32, 15),
// (33,15): error CS0211: Cannot take the address of the given expression
// p = &((int)param); //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "(int)param"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "(int)param").WithLocation(33, 15),
// (34,14): error CS0211: Cannot take the address of the given expression
// p = &default(int); //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "default(int)"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "default(int)").WithLocation(34, 14),
// (35,14): error CS0211: Cannot take the address of the given expression
// p = &delegate { return 1; }; //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "delegate { return 1; }"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "delegate { return 1; }").WithLocation(35, 14),
// (36,13): error CS0212: You can only take the address of an unfixed expression inside of a fixed statement initializer
// p = &instanceField; //CS0212
Diagnostic(ErrorCode.ERR_FixedNeeded, "&instanceField"),
Diagnostic(ErrorCode.ERR_FixedNeeded, "&instanceField").WithLocation(36, 13),
// (37,13): error CS0212: You can only take the address of an unfixed expression inside of a fixed statement initializer
// p = &staticField; //CS0212
Diagnostic(ErrorCode.ERR_FixedNeeded, "&staticField"),
Diagnostic(ErrorCode.ERR_FixedNeeded, "&staticField").WithLocation(37, 13),
// (38,15): error CS0211: Cannot take the address of the given expression
// p = &(local++); //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "local++"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "local++").WithLocation(38, 15),
// (39,14): error CS0211: Cannot take the address of the given expression
// p = &this[0]; //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "this[0]").WithArguments("C.this[int]"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "this[0]").WithArguments("C.this[int]").WithLocation(39, 14),
// (40,15): error CS0211: Cannot take the address of the given expression
// p = &(() => 1); //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "() => 1"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "() => 1").WithLocation(40, 15),
// (41,14): error CS0211: Cannot take the address of the given expression
// p = &M; //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "M").WithArguments("M", "method group"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "M").WithArguments("M", "method group").WithLocation(41, 14),
// (42,15): error CS0211: Cannot take the address of the given expression
// p = &(new System.Int32()); //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "new System.Int32()"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "new System.Int32()").WithLocation(42, 15),
// (43,14): error CS0211: Cannot take the address of the given expression
// p = &P; //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "P").WithArguments("C.P"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "P").WithArguments("C.P").WithLocation(43, 14),
// (44,14): error CS0211: Cannot take the address of the given expression
// p = &sizeof(int); //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "sizeof(int)"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "sizeof(int)").WithLocation(44, 14),
// (45,13): error CS0212: You can only take the address of an unfixed expression inside of a fixed statement initializer
// p = &this.instanceField; //CS0212
Diagnostic(ErrorCode.ERR_FixedNeeded, "&this.instanceField"),
Diagnostic(ErrorCode.ERR_FixedNeeded, "&this.instanceField").WithLocation(45, 13),
// (46,15): error CS0211: Cannot take the address of the given expression
// p = &(+local); //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "+local"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "+local").WithLocation(46, 15),
// (49,16): error CS0211: Cannot take the address of the given expression
// pp = &(&local); //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "&local"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "&local").WithLocation(49, 16),
// (51,19): error CS0211: Cannot take the address of the given expression
// var q = &(new { }); //CS0208, CS0211 (managed)
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "new { }"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "new { }").WithLocation(51, 19),
// (52,19): error CS0211: Cannot take the address of the given expression
// var r = &(new int[1]); //CS0208, CS0211 (managed)
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "new int[1]"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "new int[1]").WithLocation(52, 19),
// (53,19): error CS0211: Cannot take the address of the given expression
// var s = &(array as object); //CS0208, CS0211 (managed)
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "array as object"),
// (54,17): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('System.Action')
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "array as object").WithLocation(53, 19),
// (54,17): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('Action')
// var t = &E; //CS0208
Diagnostic(ErrorCode.ERR_ManagedAddr, "&E").WithArguments("System.Action"),
Diagnostic(ErrorCode.ERR_ManagedAddr, "&E").WithArguments("System.Action").WithLocation(54, 17),
// (55,18): error CS0079: The event 'C.F' can only appear on the left hand side of += or -=
// var u = &F; //CS0079 (can't use event like that)
Diagnostic(ErrorCode.ERR_BadEventUsageNoField, "F").WithArguments("C.F"),
Diagnostic(ErrorCode.ERR_BadEventUsageNoField, "F").WithArguments("C.F").WithLocation(55, 18),
// (56,19): error CS0211: Cannot take the address of the given expression
// var v = &(E += null); //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "E += null"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "E += null").WithLocation(56, 19),
// (57,19): error CS0211: Cannot take the address of the given expression
// var w = &(F += null); //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "F += null"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "F += null").WithLocation(57, 19),
// (58,19): error CS0211: Cannot take the address of the given expression
// var x = &(array is object); //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "array is object"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "array is object").WithLocation(58, 19),
// (59,19): error CS0211: Cannot take the address of the given expression
// var y = &(array ?? array); //CS0208, CS0211 (managed)
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "array ?? array"),
// (60,19): error CS0459: Cannot take the address of a read-only local variable
// var aa = &this; //CS0208, CS0459 (readonly)
Diagnostic(ErrorCode.ERR_AddrOnReadOnlyLocal, "this").WithArguments("this"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "array ?? array").WithLocation(59, 19),
// (60,19): error CS0211: Cannot take the address of the given expression
// var aa = &this; //CS0208
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "this").WithArguments("this").WithLocation(60, 19),
// (61,19): error CS0211: Cannot take the address of the given expression
// var bb = &typeof(int); //CS0208, CS0211 (managed)
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "typeof(int)"),
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "typeof(int)").WithLocation(61, 19),
// (62,19): error CS0211: Cannot take the address of the given expression
// var cc = &Color.Red; //CS0211
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "Color.Red"),
// (76,18): error CS0212: You can only take the address of an unfixed expression inside of a fixed statement initializer
// var aa = &this; //CS0212 (need fixed)
Diagnostic(ErrorCode.ERR_FixedNeeded, "&this"));
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "Color.Red").WithLocation(62, 19)
);
}
#endregion AddressOf operand kinds
......@@ -3839,6 +3833,7 @@ public static void Main()
Diagnostic(ErrorCode.ERR_AnonymousTypePropertyAssignedBadValue, "p1 = &x").WithArguments("int*"));
}
[WorkItem(22306, "https://github.com/dotnet/roslyn/issues/22306")]
[WorkItem(544537, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544537")]
[Fact]
public void AddressOfStaticReadonlyFieldInsideFixed()
......@@ -3855,10 +3850,7 @@ unsafe public static void Main()
}
";
CreateCompilationWithMscorlibAndSystemCore(text, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (8,27): error CS0211: Cannot take the address of the given expression
// fixed (int* v1 = &R1) { }
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "R1"));
CreateCompilationWithMscorlibAndSystemCore(text, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics();
}
#endregion AddressOf diagnostics
......@@ -8572,9 +8564,10 @@ unsafe void M(in int p)
int* pointer = &p;
}
}", options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (6,25): error CS0211: Cannot take the address of the given expression
// (6,24): error CS0212: You can only take the address of an unfixed expression inside of a fixed statement initializer
// int* pointer = &p;
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "p").WithLocation(6, 25));
Diagnostic(ErrorCode.ERR_FixedNeeded, "&p").WithLocation(6, 24)
);
}
#endregion
......
......@@ -63,6 +63,54 @@ End Class
CompilationUtils.AssertNoDiagnostics(comp)
End Sub
<Fact>
<WorkItem(20741, "https://github.com/dotnet/roslyn/issues/20741")>
Public Sub TestNamedArgumentOnStringParamsArgument()
Dim source =
<compilation>
<file name="a.vb">
<![CDATA[
Imports System
Class MarkAttribute
Inherits Attribute
Public Sub New(ByVal otherArg As Boolean, ParamArray args As Object())
End Sub
End Class
<Mark(args:=New String() {"Hello", "World"}, otherArg:=True)>
Module Program
Private Sub Test(ByVal otherArg As Boolean, ParamArray args As Object())
End Sub
Sub Main()
Console.WriteLine("Method call")
Test(args:=New String() {"Hello", "World"}, otherArg:=True)
End Sub
End Module
]]>
</file>
</compilation>
Dim comp = CreateCompilationWithMscorlibAndVBRuntime(source)
comp.AssertTheseDiagnostics(<errors><![CDATA[
BC30455: Argument not specified for parameter 'otherArg' of 'Public Sub New(otherArg As Boolean, ParamArray args As Object())'.
<Mark(args:=New String() {"Hello", "World"}, otherArg:=True)>
~~~~
BC30661: Field or property 'args' is not found.
<Mark(args:=New String() {"Hello", "World"}, otherArg:=True)>
~~~~
BC30661: Field or property 'otherArg' is not found.
<Mark(args:=New String() {"Hello", "World"}, otherArg:=True)>
~~~~~~~~
BC30587: Named argument cannot match a ParamArray parameter.
Test(args:=New String() {"Hello", "World"}, otherArg:=True)
~~~~
]]></errors>)
End Sub
''' <summary>
''' This function is the same as PEParameterSymbolParamArray
''' except that we check attributes first (to check for race
......
......@@ -111,7 +111,10 @@ public void AddAnalyzerProvider(IIncrementalAnalyzerProvider provider, Increment
}
var analyzer = lazyProvider.Value.CreateIncrementalAnalyzer(workspace);
coordinator.AddAnalyzer(analyzer, metadata.HighPriorityForActiveFile);
if (analyzer != null)
{
coordinator.AddAnalyzer(analyzer, metadata.HighPriorityForActiveFile);
}
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册