File: Attributes\AttributeTests_CallerInfoAttributes.cs
Web Access
Project: src\src\Compilers\CSharp\Test\Emit3\Microsoft.CodeAnalysis.CSharp.Emit3.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Emit3.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
    public class AttributeTests_CallerInfoAttributes : WellKnownAttributesTestBase
    {
        public static IEnumerable<MetadataReference> GetReferencesWithoutInteropServices() =>
            TargetFrameworkUtil.GetReferencesWithout(TargetFramework.Net50, "System.Runtime.InteropServices.dll");
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestBeginInvoke()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
 
namespace System.Runtime.InteropServices
{
    [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
    public sealed class OptionalAttribute : Attribute
    {
        public OptionalAttribute()
        {
        }
    }
 
    [AttributeUsage(AttributeTargets.Parameter)]
    public sealed class DefaultParameterValueAttribute : Attribute
    {
        public DefaultParameterValueAttribute(object value)
        {
            Value = value;
        }
        public object Value { get; }
    }
}
 
class Program
{
    const string s1 = nameof(s1);
    delegate void D(string s1, [CallerArgumentExpression(s1)] [Optional] [DefaultParameterValue(""default"")] string s2);
 
    static void M(string s1, string s2)
    {
    }
 
    static string GetString() => null;
 
    public static void Main()
    {
        D d = M;
        d.BeginInvoke(GetString(), callback: null, @object: null);
    }
}
";
 
            var compilation = CreateEmptyCompilation(source, GetReferencesWithoutInteropServices(), options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            // Begin/EndInvoke are not currently supported.
            CompileAndVerify(compilation).VerifyDiagnostics().VerifyIL("Program.Main", @"
{
  // Code size       31 (0x1f)
  .maxstack  5
  IL_0000:  ldnull
  IL_0001:  ldftn      ""void Program.M(string, string)""
  IL_0007:  newobj     ""Program.D..ctor(object, System.IntPtr)""
  IL_000c:  call       ""string Program.GetString()""
  IL_0011:  ldstr      ""default""
  IL_0016:  ldnull
  IL_0017:  ldnull
  IL_0018:  callvirt   ""System.IAsyncResult Program.D.BeginInvoke(string, string, System.AsyncCallback, object)""
  IL_001d:  pop
  IL_001e:  ret
}
");
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestEndInvoke()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
 
namespace System.Runtime.InteropServices
{
    [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
    public sealed class OptionalAttribute : Attribute
    {
        public OptionalAttribute()
        {
        }
    }
 
    [AttributeUsage(AttributeTargets.Parameter)]
    public sealed class DefaultParameterValueAttribute : Attribute
    {
        public DefaultParameterValueAttribute(object value)
        {
            Value = value;
        }
        public object Value { get; }
    }
}
 
class Program
{
    const string s1 = nameof(s1);
    delegate void D(ref string s1, [CallerArgumentExpression(s1)] [Optional] [DefaultParameterValue(""default"")] string s2);
 
    static void M(ref string s1, string s2)
    {
    }
 
    public static void Main()
    {
        D d = M;
        string s = string.Empty;
        d.EndInvoke(ref s, null);
    }
}
";
 
            var compilation = CreateEmptyCompilation(source, GetReferencesWithoutInteropServices(), options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            // Begin/EndInvoke are not currently supported.
            CompileAndVerify(compilation).VerifyDiagnostics().VerifyIL("Program.Main", @"
{
  // Code size       27 (0x1b)
  .maxstack  3
  .locals init (string V_0) //s
  IL_0000:  ldnull
  IL_0001:  ldftn      ""void Program.M(ref string, string)""
  IL_0007:  newobj     ""Program.D..ctor(object, System.IntPtr)""
  IL_000c:  ldsfld     ""string string.Empty""
  IL_0011:  stloc.0
  IL_0012:  ldloca.s   V_0
  IL_0014:  ldnull
  IL_0015:  callvirt   ""void Program.D.EndInvoke(ref string, System.IAsyncResult)""
  IL_001a:  ret
}
");
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestEndInvoke2()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
 
namespace System.Runtime.InteropServices
{
    [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
    public sealed class OptionalAttribute : Attribute
    {
        public OptionalAttribute()
        {
        }
    }
 
    [AttributeUsage(AttributeTargets.Parameter)]
    public sealed class DefaultParameterValueAttribute : Attribute
    {
        public DefaultParameterValueAttribute(object value)
        {
            Value = value;
        }
        public object Value { get; }
    }
}
 
class Program
{
    const string s5 = nameof(s5);
    delegate void D([CallerArgumentExpression(s5)] [Optional] [DefaultParameterValue(""default"")] ref string s1, string s2, string s3, string s4, string s5);
 
    static void M(ref string s1, string s2, string s3, string s4, string s5)
    {
    }
 
    public static void Main()
    {
        D d = M;
        d.EndInvoke(result: null);
    }
}
";
 
            var compilation = CreateEmptyCompilation(source, GetReferencesWithoutInteropServices(), options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            compilation.VerifyDiagnostics(
                // (29,22): error CS8964: The CallerArgumentExpressionAttribute may only be applied to parameters with default values
                //     delegate void D([CallerArgumentExpression(s5)] [Optional] [DefaultParameterValue("default")] ref string s1, string s2, string s3, string s4, string s5);
                Diagnostic(ErrorCode.ERR_BadCallerArgumentExpressionParamWithoutDefaultValue, "CallerArgumentExpression").WithLocation(29, 22),
                // (38,11): error CS7036: There is no argument given that corresponds to the required parameter 's1' of 'Program.D.EndInvoke(ref string, IAsyncResult)'
                //         d.EndInvoke(result: null);
                Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "EndInvoke").WithArguments("s1", "Program.D.EndInvoke(ref string, System.IAsyncResult)").WithLocation(38, 11)
                );
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestEndInvoke3()
        {
            string source = @"
using System.Runtime.CompilerServices;
 
namespace System.Runtime.InteropServices
{
    [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
    public sealed class OptionalAttribute : Attribute
    {
        public OptionalAttribute()
        {
        }
    }
 
    [AttributeUsage(AttributeTargets.Parameter)]
    public sealed class DefaultParameterValueAttribute : Attribute
    {
        public DefaultParameterValueAttribute(object value)
        {
            Value = value;
        }
        public object Value { get; }
    }
}
 
class Program
{
    const string s1 = nameof(s1);
    delegate void D(string s1, [CallerArgumentExpression(s1)] ref string s2 = ""default"");
 
    static void M(string s1, ref string s2)
    {
    }
 
    public static void Main()
    {
        D d = M;
        string s = string.Empty;
        d.EndInvoke(result: null);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            compilation.VerifyDiagnostics(
                // (28,33): error CS8964: The CallerArgumentExpressionAttribute may only be applied to parameters with default values
                //     delegate void D(string s1, [CallerArgumentExpression(s1)] ref string s2 = "default");
                Diagnostic(ErrorCode.ERR_BadCallerArgumentExpressionParamWithoutDefaultValue, "CallerArgumentExpression").WithLocation(28, 33),
                // (28,63): error CS1741: A ref or out parameter cannot have a default value
                //     delegate void D(string s1, [CallerArgumentExpression(s1)] ref string s2 = "default");
                Diagnostic(ErrorCode.ERR_RefOutDefaultValue, "ref").WithLocation(28, 63),
                // (38,11): error CS7036: There is no argument given that corresponds to the required parameter 's2' of 'Program.D.EndInvoke(ref string, IAsyncResult)'
                //         d.EndInvoke(result: null);
                Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "EndInvoke").WithArguments("s2", "Program.D.EndInvoke(ref string, System.IAsyncResult)").WithLocation(38, 11));
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestEndInvoke4()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
 
namespace System.Runtime.InteropServices
{
    [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
    public sealed class OptionalAttribute : Attribute
    {
        public OptionalAttribute()
        {
        }
    }
 
    [AttributeUsage(AttributeTargets.Parameter)]
    public sealed class DefaultParameterValueAttribute : Attribute
    {
        public DefaultParameterValueAttribute(object value)
        {
            Value = value;
        }
        public object Value { get; }
    }
}
 
class Program
{
    const string s1 = nameof(s1);
    delegate void D(string s1, [CallerArgumentExpression(s1)] [Optional] [DefaultParameterValue(""default"")] ref string s2);
 
    static void M(string s1, ref string s2)
    {
    }
 
    public static void Main()
    {
        D d = M;
        string s = string.Empty;
        d.EndInvoke(result: null);
    }
}
";
 
            var compilation = CreateEmptyCompilation(source, GetReferencesWithoutInteropServices(), options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            compilation.VerifyDiagnostics(
                // (29,33): error CS8964: The CallerArgumentExpressionAttribute may only be applied to parameters with default values
                //     delegate void D(string s1, [CallerArgumentExpression(s1)] [Optional] [DefaultParameterValue("default")] ref string s2);
                Diagnostic(ErrorCode.ERR_BadCallerArgumentExpressionParamWithoutDefaultValue, "CallerArgumentExpression").WithLocation(29, 33),
                // (39,11): error CS7036: There is no argument given that corresponds to the required parameter 's2' of 'Program.D.EndInvoke(ref string, IAsyncResult)'
                //         d.EndInvoke(result: null);
                Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "EndInvoke").WithArguments("s2", "Program.D.EndInvoke(ref string, System.IAsyncResult)").WithLocation(39, 11));
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestBeginInvoke_ReferringToCallbackParameter()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
 
namespace System.Runtime.InteropServices
{
    [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
    public sealed class OptionalAttribute : Attribute
    {
        public OptionalAttribute()
        {
        }
    }
 
    [AttributeUsage(AttributeTargets.Parameter)]
    public sealed class DefaultParameterValueAttribute : Attribute
    {
        public DefaultParameterValueAttribute(object value)
        {
            Value = value;
        }
        public object Value { get; }
    }
}
 
class Program
{
    const string callback = nameof(callback);
    delegate void D(string s1, [CallerArgumentExpression(callback)] [Optional] [DefaultParameterValue(""default"")] string s2);
 
    static void M(string s1, string s2)
    {
    }
 
    static string GetString() => null;
 
    public static void Main()
    {
        D d = M;
        d.BeginInvoke(GetString(), callback: null, @object: null);
    }
}
";
 
            var compilation = CreateEmptyCompilation(source, GetReferencesWithoutInteropServices(), options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation).VerifyDiagnostics(
                // (29,33): warning CS8963: The CallerArgumentExpressionAttribute applied to parameter 's2' will have no effect. It is applied with an invalid parameter name.
                //     delegate void D(string s1, [CallerArgumentExpression(callback)] [Optional] [DefaultParameterValue("default")] string s2);
                Diagnostic(ErrorCode.WRN_CallerArgumentExpressionAttributeHasInvalidParameterName, "CallerArgumentExpression").WithArguments("s2").WithLocation(29, 33)
                ).VerifyIL("Program.Main", @"
{
  // Code size       31 (0x1f)
  .maxstack  5
  IL_0000:  ldnull
  IL_0001:  ldftn      ""void Program.M(string, string)""
  IL_0007:  newobj     ""Program.D..ctor(object, System.IntPtr)""
  IL_000c:  call       ""string Program.GetString()""
  IL_0011:  ldstr      ""default""
  IL_0016:  ldnull
  IL_0017:  ldnull
  IL_0018:  callvirt   ""System.IAsyncResult Program.D.BeginInvoke(string, string, System.AsyncCallback, object)""
  IL_001d:  pop
  IL_001e:  ret
}
");
        }
 
        #region CallerArgumentExpression - Invocations
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestGoodCallerArgumentExpressionAttribute()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    public static void Main()
    {
        Log(123);
    }
    const string p = nameof(p);
    static void Log(int p, [CallerArgumentExpression(p)] string arg = ""<default-arg>"")
    {
        Console.WriteLine(arg);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "123").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestGoodCallerArgumentExpressionAttribute_MultipleAttributes()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = true, Inherited = false)]
    public sealed class CallerArgumentExpressionAttribute : Attribute
    {
        public CallerArgumentExpressionAttribute(string parameterName)
        {
            ParameterName = parameterName;
        }
        public string ParameterName { get; }
    }
}
 
class Program
{
    public static void Main()
    {
        Log(123, 456);
    }
    const string p1 = nameof(p1);
    const string p2 = nameof(p2);
    static void Log(int p1, int p2, [CallerArgumentExpression(p1), CallerArgumentExpression(p2)] string arg = ""<default-arg>"")
    {
        Console.WriteLine(arg);
    }
}
";
 
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "456").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestGoodCallerArgumentExpressionAttribute_MultipleAttributes_IncorrectCtor()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = true, Inherited = false)]
    public sealed class CallerArgumentExpressionAttribute : Attribute
    {
        public CallerArgumentExpressionAttribute(string parameterName, int extraParam)
        {
            ParameterName = parameterName;
        }
        public string ParameterName { get; }
    }
}
 
class Program
{
    public static void Main()
    {
        Log(123, 456);
    }
    const string p1 = nameof(p1);
    const string p2 = nameof(p2);
    static void Log(int p1, int p2, [CallerArgumentExpression(p1, 0), CallerArgumentExpression(p2, 1)] string arg = ""<default-arg>"")
    {
        Console.WriteLine(arg);
    }
}
";
 
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "<default-arg>").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestGoodCallerArgumentExpressionAttribute_ExpressionHasTrivia()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    public static void Main()
    {
        Log(// comment
               123 /* comment */ +
               5 /* comment */ // comment
        );
    }
    const string p = nameof(p);
    static void Log(int p, [CallerArgumentExpression(p)] string arg = ""<default-arg>"")
    {
        Console.WriteLine(arg);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput:
@"123 /* comment */ +
               5").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestGoodCallerArgumentExpressionAttribute_Pragmas()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    public static void Main()
    {
        Log(
            #pragma warning disable IDE0001
            #nullable enable
               123 +
            #pragma warning disable IDE0002
            #nullable disable
               5 +
            #pragma warning disable IDE0003
            #nullable restore
               5
            #pragma warning disable IDE0004
            #nullable enable
        );
    }
    const string p = nameof(p);
    static void Log(int p, [CallerArgumentExpression(p)] string arg = ""<default-arg>"")
    {
        Console.WriteLine(arg);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput:
@"123 +
            #pragma warning disable IDE0002
            #nullable disable
               5 +
            #pragma warning disable IDE0003
            #nullable restore
               5
").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestGoodCallerArgumentExpressionAttribute_ImplicitAndExplicitConstructorBaseCalls()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Base
{
    const string p = nameof(p);
    public Base(int p = 0, [CallerArgumentExpression(p)] string arg = ""<default-arg-base>"")
    {
        Console.WriteLine(""Base class: "" + arg);
    }
}
 
class Derived1 : Base
{
    const string ppp = nameof(ppp);
    public Derived1(int ppp, [CallerArgumentExpression(ppp)] string arg = ""<default-arg-derived1>"")
        : base(ppp)
    {
        Console.WriteLine(""Derived1 class: "" + arg);
    }
}
 
class Derived2 : Base
{
    const string p = nameof(p);
    public Derived2(int p, [CallerArgumentExpression(p)] string arg = ""<default-arg-derived2>"")
    {
        Console.WriteLine(""Derived2 class: "" + arg);
    }
}
 
 
class Program
{
    public static void Main(string[] args)
    {
        _ = new Base(1+4);
        Console.WriteLine();
        _ = new Derived1(2+ 5);
        Console.WriteLine();
        _ = new Derived2(3 +  6);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput:
@"Base class: 1+4
 
Base class: ppp
Derived1 class: 2+ 5
 
Base class: <default-arg-base>
Derived2 class: 3 +  6
").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestGoodCallerArgumentExpressionAttribute_SwapArguments()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    public static void Main()
    {
        Log(q: 123, p: 124);
    }
    const string p = nameof(p);
    static void Log(int p, int q, [CallerArgumentExpression(p)] string arg = ""<default-arg>"")
    {
        Console.WriteLine($""{p}, {q}, {arg}"");
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "124, 123, 124").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestGoodCallerArgumentExpressionAttribute_DifferentAssembly()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
public static class FromFirstAssembly
{
    const string p = nameof(p);
    public static void Log(int p, int q, [CallerArgumentExpression(p)] string arg = ""<default-arg>"")
    {
        Console.WriteLine(arg);
    }
}
";
            var comp1 = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, parseOptions: TestOptions.Regular9);
            comp1.VerifyDiagnostics();
            var ref1 = comp1.EmitToImageReference();
 
            var source2 = @"
public static class Program
{
    public static void Main() => FromFirstAssembly.Log(2 + 2, 3 + 1);
}
";
 
            var compilation = CreateCompilation(source2, references: new[] { ref1 }, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "2 + 2").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestGoodCallerArgumentExpressionAttribute_ExtensionMethod_ThisParameter()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
public static class Program
{
    public static void Main()
    {
        int myIntegerExpression = 5;
        myIntegerExpression.M();
    }
    const string p = nameof(p);
    public static void M(this int p, [CallerArgumentExpression(p)] string arg = ""<default-arg>"")
    {
        Console.WriteLine(arg);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "myIntegerExpression").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestGoodCallerArgumentExpressionAttribute_ExtensionMethod_NotThisParameter()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
public static class Program
{
    public static void Main()
    {
        int myIntegerExpression = 5;
        myIntegerExpression.M(myIntegerExpression * 2);
    }
    const string q = nameof(q);
    public static void M(this int p, int q, [CallerArgumentExpression(q)] string arg = ""<default-arg>"")
    {
        Console.WriteLine(arg);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "myIntegerExpression * 2").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestIncorrectParameterNameInCallerArgumentExpressionAttribute()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    public static void Main()
    {
        Log();
    }
    const string pp = nameof(pp);
    static void Log([CallerArgumentExpression(pp)] string arg = ""<default>"")
    {
        Console.WriteLine(arg);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9);
            CompileAndVerify(compilation, expectedOutput: "<default>").VerifyDiagnostics(
                // (12,22): warning CS8918: The CallerArgumentExpressionAttribute applied to parameter 'arg' will have no effect. It is applied with an invalid parameter name.
                //     static void Log([CallerArgumentExpression(pp)] string arg = "<default>")
                Diagnostic(ErrorCode.WRN_CallerArgumentExpressionAttributeHasInvalidParameterName, "CallerArgumentExpression").WithArguments("arg").WithLocation(12, 22)
                );
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentWithMemberNameAttributes()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    public static void Main()
    {
        Log(default(int));
    }
    const string p = nameof(p);
    static void Log(int p, [CallerArgumentExpression(p)] [CallerMemberName] string arg = ""<default>"")
    {
        Console.WriteLine(arg);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9);
            CompileAndVerify(compilation, expectedOutput: "Main").VerifyDiagnostics(
                // (12,29): warning CS8962: The CallerArgumentExpressionAttribute applied to parameter 'arg' will have no effect. It is overridden by the CallerMemberNameAttribute.
                //     static void Log(int p, [CallerArgumentExpression(p)] [CallerMemberName] string arg = "<default>")
                Diagnostic(ErrorCode.WRN_CallerMemberNamePreferredOverCallerArgumentExpression, "CallerArgumentExpression").WithArguments("arg").WithLocation(12, 29)
                );
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentWithMemberNameAttributes2()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    public static void Main()
    {
        Log(default(int));
    }
    const string p = nameof(p);
    static void Log(int p, [CallerArgumentExpression(p)] [CallerMemberName] string arg = ""<default>"")
    {
        Console.WriteLine(arg);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "Main").VerifyDiagnostics(
                // (12,29): warning CS8962: The CallerArgumentExpressionAttribute applied to parameter 'arg' will have no effect. It is overridden by the CallerMemberNameAttribute.
                //     static void Log(int p, [CallerArgumentExpression(p)] [CallerMemberName] string arg = "<default>")
                Diagnostic(ErrorCode.WRN_CallerMemberNamePreferredOverCallerArgumentExpression, "CallerArgumentExpression").WithArguments("arg").WithLocation(12, 29)
                );
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentWitLineNumberAttributes()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    public static void Main()
    {
        Log(default(int));
    }
    const string p = nameof(p);
    static void Log(int p, [CallerArgumentExpression(p)] [CallerLineNumber] string arg = ""<default>"")
    {
        Console.WriteLine(arg);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9);
            compilation.VerifyDiagnostics(
                // (9,9): error CS0029: Cannot implicitly convert type 'int' to 'string'
                //         Log(default(int));
                Diagnostic(ErrorCode.ERR_NoImplicitConv, "Log(default(int))").WithArguments("int", "string").WithLocation(9, 9),
                // (12,29): warning CS8960: The CallerArgumentExpressionAttribute applied to parameter 'arg' will have no effect. It is overridden by the CallerLineNumberAttribute.
                //     static void Log(int p, [CallerArgumentExpression(p)] [CallerLineNumber] string arg = "<default>")
                Diagnostic(ErrorCode.WRN_CallerLineNumberPreferredOverCallerArgumentExpression, "CallerArgumentExpression").WithArguments("arg").WithLocation(12, 29),
                // (12,59): error CS4017: CallerLineNumberAttribute cannot be applied because there are no standard conversions from type 'int' to type 'string'
                //     static void Log(int p, [CallerArgumentExpression(p)] [CallerLineNumber] string arg = "<default>")
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithArguments("int", "string").WithLocation(12, 59)
                );
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentWithLineNumberAttributes2()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    public static void Main()
    {
        Log(default(int));
    }
    const string p = nameof(p);
    static void Log(int p, [CallerArgumentExpression(p)] [CallerLineNumber] string arg = ""<default>"")
    {
        Console.WriteLine(arg);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            compilation.VerifyDiagnostics(
                // (9,9): error CS0029: Cannot implicitly convert type 'int' to 'string'
                //         Log(default(int));
                Diagnostic(ErrorCode.ERR_NoImplicitConv, "Log(default(int))").WithArguments("int", "string").WithLocation(9, 9),
                // (12,29): warning CS8960: The CallerArgumentExpressionAttribute applied to parameter 'arg' will have no effect. It is overridden by the CallerLineNumberAttribute.
                //     static void Log(int p, [CallerArgumentExpression(p)] [CallerLineNumber] string arg = "<default>")
                Diagnostic(ErrorCode.WRN_CallerLineNumberPreferredOverCallerArgumentExpression, "CallerArgumentExpression").WithArguments("arg").WithLocation(12, 29),
                // (12,59): error CS4017: CallerLineNumberAttribute cannot be applied because there are no standard conversions from type 'int' to type 'string'
                //     static void Log(int p, [CallerArgumentExpression(p)] [CallerLineNumber] string arg = "<default>")
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithArguments("int", "string").WithLocation(12, 59)
                );
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentWitLineNumberAttributes3()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    public static void Main()
    {
        Log(default(int));
    }
    const string p = nameof(p);
    static void Log(int p, [CallerArgumentExpression(p)] [CallerLineNumber] int arg = 0)
    {
        Console.WriteLine(arg);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9);
            compilation.VerifyDiagnostics(
                // (12,29): error CS8959: CallerArgumentExpressionAttribute cannot be applied because there are no standard conversions from type 'string' to type 'int'
                //     static void Log(int p, [CallerArgumentExpression(p)] [CallerLineNumber] int arg = 0)
                Diagnostic(ErrorCode.ERR_NoConversionForCallerArgumentExpressionParam, "CallerArgumentExpression").WithArguments("string", "int").WithLocation(12, 29)
                );
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentWithLineNumberAttributes4()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    public static void Main()
    {
        Log(default(int));
    }
    const string p = nameof(p);
    static void Log(int p, [CallerArgumentExpression(p)] [CallerLineNumber] int arg = 0)
    {
        Console.WriteLine(arg);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            compilation.VerifyDiagnostics(
                // (12,29): error CS8959: CallerArgumentExpressionAttribute cannot be applied because there are no standard conversions from type 'string' to type 'int'
                //     static void Log(int p, [CallerArgumentExpression(p)] [CallerLineNumber] int arg = 0)
                Diagnostic(ErrorCode.ERR_NoConversionForCallerArgumentExpressionParam, "CallerArgumentExpression").WithArguments("string", "int").WithLocation(12, 29)
                );
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentNonOptionalParameter()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    public static void Main()
    {
        Log(default(int));
    }
    const string p = nameof(p);
    static void Log(int p, [CallerArgumentExpression(p)] string arg)
    {
        Console.WriteLine(arg);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            compilation.VerifyDiagnostics(
                // (9,9): error CS7036: There is no argument given that corresponds to the required parameter 'arg' of 'Program.Log(int, string)'
                //         Log(default(int));
                Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "Log").WithArguments("arg", "Program.Log(int, string)").WithLocation(9, 9),
                // (12,29): error CS8964: The CallerArgumentExpressionAttribute may only be applied to parameters with default values
                //     static void Log(int p, [CallerArgumentExpression(p)] string arg)
                Diagnostic(ErrorCode.ERR_BadCallerArgumentExpressionParamWithoutDefaultValue, "CallerArgumentExpression").WithLocation(12, 29)
                );
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentNonOptionalParameter2()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    public static void Main()
    {
        Log(default(int));
    }
    const string p = nameof(p);
    static void Log(int p, [CallerArgumentExpression(p)] string arg)
    {
        Console.WriteLine(arg);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9);
            compilation.VerifyDiagnostics(
                // (9,9): error CS7036: There is no argument given that corresponds to the required parameter 'arg' of 'Program.Log(int, string)'
                //         Log(default(int));
                Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "Log").WithArguments("arg", "Program.Log(int, string)").WithLocation(9, 9),
                // (12,29): error CS8964: The CallerArgumentExpressionAttribute may only be applied to parameters with default values
                //     static void Log(int p, [CallerArgumentExpression(p)] string arg)
                Diagnostic(ErrorCode.ERR_BadCallerArgumentExpressionParamWithoutDefaultValue, "CallerArgumentExpression").WithLocation(12, 29)
                );
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentWithOverride()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
abstract class Base
{
    const string p = nameof(p);
    public abstract void Log_RemoveAttributeInOverride(int p, [CallerArgumentExpression(p)] string arg =""default"");
    public abstract void Log_AddAttributeInOverride(int p, string arg =""default"");
}
 
class Derived : Base
{
    const string p = nameof(p);
    public override void Log_AddAttributeInOverride(int p, [CallerArgumentExpression(p)] string arg = ""default"")
        => Console.WriteLine(arg);
 
    public override void Log_RemoveAttributeInOverride(int p, string arg = ""default"")
        => Console.WriteLine(arg);
}
 
class Program
{
    public static void Main()
    {
        var derived = new Derived();
        derived.Log_AddAttributeInOverride(5 + 4);
        derived.Log_RemoveAttributeInOverride(5 + 5);
 
        ((Base)derived).Log_AddAttributeInOverride(5 + 4);
        ((Base)derived).Log_RemoveAttributeInOverride(5 + 5);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: @"5 + 4
default
default
5 + 5").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentWithUserDefinedConversionFromString()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class C
{
    public C(string s) => S = s;
    public string S { get; }
    public static implicit operator C(string s) => new C(s);
}
 
class Program
{
    public static void Main()
    {
        Log(default(int));
    }
    const string p = nameof(p);
    static void Log(int p, [CallerArgumentExpression(p)] C arg = null)
    {
        Console.WriteLine(arg.S);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            compilation.VerifyDiagnostics(
                // (19,29): error CS8959: CallerArgumentExpressionAttribute cannot be applied because there are no standard conversions from type 'string' to type 'C'
                //     static void Log(int p, [CallerArgumentExpression(p)] C arg = null)
                Diagnostic(ErrorCode.ERR_NoConversionForCallerArgumentExpressionParam, "CallerArgumentExpression").WithArguments("string", "C").WithLocation(19, 29)
                );
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentWithExtensionGetEnumerator()
        {
            string source = @"
using System;
using System.Collections;
using System.Runtime.CompilerServices;
 
public static class Extensions
{
    public static IEnumerator GetEnumerator(this IEnumerator enumerator, [CallerArgumentExpression(""enumerator"")] string s = ""default"")
    {
        Console.WriteLine(s);
        return enumerator;
    }
}
 
class Program
{
    static void Main()
    {
        var x = new [] { """", """" }.GetEnumerator();
 
        foreach (var y in x)
        {
        }
    }
}
 
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "x").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentWithExtensionDeconstruct()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
public static class Extensions
{
    public static void Deconstruct(this Person p, out string firstName, out string lastName, [CallerArgumentExpression(""firstName"")] string s = ""default"")
    {
        firstName = p.FirstName;
        lastName = p.LastName;
        Console.WriteLine(s);
    }
}
 
public class Person
{
    public Person(string firstName, string lastName)
        => (FirstName, LastName) = (firstName, lastName);
 
    public string FirstName { get; }
    public string LastName { get; }
}
 
class Program
{
    static void Main()
    {
        var p = new Person(""myFirstName"", ""myLastName"");
        var (first, last) = p;
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            compilation.VerifyDiagnostics(
                // (29,14): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'first'.
                //         var (first, last) = p;
                Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "first").WithArguments("first").WithLocation(29, 14),
                // (29,21): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'last'.
                //         var (first, last) = p;
                Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "last").WithArguments("last").WithLocation(29, 21),
                // (29,29): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'Person', with 2 out parameters and a void return type.
                //         var (first, last) = p;
                Diagnostic(ErrorCode.ERR_MissingDeconstruct, "p").WithArguments("Person", "2").WithLocation(29, 29)
                );
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentExpressionWithOptionalTargetParameter()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    public static void Main()
    {
        string callerTargetExp = ""caller target value"";
        Log(0);
        Log(0, callerTargetExp);
    }
    const string target = nameof(target);
    static void Log(int p, string target = ""target default value"", [CallerArgumentExpression(target)] string arg = ""arg default value"")
    {
        Console.WriteLine(target);
        Console.WriteLine(arg);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput:
@"target default value
arg default value
caller target value
callerTargetExp").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentExpressionWithMultipleOptionalAttribute()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    public static void Main()
    {
        string callerTargetExp = ""caller target value"";
        Log(0);
        Log(0, callerTargetExp);
        Log(0, target: callerTargetExp);
        Log(0, notTarget: ""Not target value"");
        Log(0, notTarget: ""Not target value"", target: callerTargetExp);
    }
    const string target = nameof(target);
    static void Log(int p, string target = ""target default value"", string notTarget = ""not target default value"", [CallerArgumentExpression(target)] string arg = ""arg default value"")
    {
        Console.WriteLine(target);
        Console.WriteLine(arg);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput:
@"target default value
arg default value
caller target value
callerTargetExp
caller target value
callerTargetExp
target default value
arg default value
caller target value
callerTargetExp").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentExpressionWithDifferentParametersReferringToEachOther()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    public static void Main()
    {
        M();
        M(""param1_value"");
        M(param1: ""param1_value"");
        M(param2: ""param2_value"");
        M(param1: ""param1_value"", param2: ""param2_value"");
        M(param2: ""param2_value"", param1: ""param1_value"");
    }
 
    static void M([CallerArgumentExpression(""param2"")] string param1 = ""param1_default"", [CallerArgumentExpression(""param1"")] string param2 = ""param2_default"")
    {
        Console.WriteLine($""param1: {param1}, param2: {param2}"");
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput:
@"param1: param1_default, param2: param2_default
param1: param1_value, param2: ""param1_value""
param1: param1_value, param2: ""param1_value""
param1: ""param2_value"", param2: param2_value
param1: param1_value, param2: param2_value
param1: param1_value, param2: param2_value").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestArgumentExpressionIsCallerMember()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
C.M();
 
public static class C
{
    public static void M(
        [CallerMemberName] string callerName = ""<default-caller-name>"",
        [CallerArgumentExpression(""callerName"")] string argumentExp = ""<default-arg-expression>"")
    {
        Console.WriteLine(callerName);
        Console.WriteLine(argumentExp);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9);
            CompileAndVerify(compilation, expectedOutput: @"<Main>$
<default-arg-expression>").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestArgumentExpressionIsSelfReferential()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
C.M();
C.M(""value"");
 
public static class C
{
    public static void M(
        [CallerArgumentExpression(""p"")] string p = ""<default>"")
    {
        Console.WriteLine(p);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: @"<default>
value").VerifyDiagnostics(
                // (11,10): warning CS8965: The CallerArgumentExpressionAttribute applied to parameter 'p' will have no effect because it's self-referential.
                //         [CallerArgumentExpression("p")] string p = "<default>")
                Diagnostic(ErrorCode.WRN_CallerArgumentExpressionAttributeSelfReferential, "CallerArgumentExpression").WithArguments("p").WithLocation(11, 10)
                );
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestArgumentExpressionIsSelfReferential_Metadata()
        {
            string il = @".class private auto ansi '<Module>'
{
} // end of class <Module>
 
.class public auto ansi abstract sealed beforefieldinit C
    extends [mscorlib]System.Object
{
    // Methods
    .method public hidebysig static 
        void M (
            [opt] string p
        ) cil managed 
    {
        .param [1] = ""<default>""
            .custom instance void [mscorlib]System.Runtime.CompilerServices.CallerArgumentExpressionAttribute::.ctor(string) = (
                01 00 01 70 00 00
            )
        // Method begins at RVA 0x2050
        // Code size 9 (0x9)
        .maxstack 8
 
        IL_0000: nop
        IL_0001: ldarg.0
        IL_0002: call void [mscorlib]System.Console::WriteLine(string)
        IL_0007: nop
        IL_0008: ret
    } // end of method C::M
 
} // end of class C
";
            string source = @"
C.M();
C.M(""value"");
";
 
            var compilation = CreateCompilationWithIL(source, il, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: @"<default>
value").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestInterpolatedStringHandler()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
using System.Text;
 
M(1 + /**/ 1, $""""); // Should print ""1 + 1""
 
void M(object o, [InterpolatedStringHandlerArgument(""o"")] CustomHandler c) => Console.WriteLine(c.ToString());
 
[InterpolatedStringHandler]
public ref struct CustomHandler
{
    private readonly StringBuilder _builder;
    public CustomHandler(int literalLength, int formattedCount, object o, [CallerArgumentExpression(""o"")] string s = """")
    {
        _builder = new StringBuilder();
        _builder.Append(s);
    }
    public void AppendLiteral(string s) => _builder.AppendLine(s.ToString());
    public void AppendFormatted(object o) => _builder.AppendLine(""value:"" + o.ToString());
    public override string ToString() => _builder.ToString();
}
 
namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
    public sealed class InterpolatedStringHandlerArgumentAttribute : Attribute
    {
        public InterpolatedStringHandlerArgumentAttribute(string argument) => Arguments = new string[] { argument };
        public InterpolatedStringHandlerArgumentAttribute(params string[] arguments) => Arguments = arguments;
        public string[] Arguments { get; }
    }
 
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
    public sealed class InterpolatedStringHandlerAttribute : Attribute
    {
        public InterpolatedStringHandlerAttribute()
        {
        }
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.Net50, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "1 + /**/ 1").VerifyDiagnostics();
        }
        #endregion
 
        #region CallerArgumentExpression - Attribute constructor
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestGoodCallerArgumentExpressionAttribute_Attribute()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
public class MyAttribute : Attribute
{
    const string p = nameof(p);
    public MyAttribute(int p, [CallerArgumentExpression(p)] string arg = ""<default-arg>"")
    {
        Console.WriteLine(arg);
    }
}
 
[My(123)]
public class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttribute(typeof(MyAttribute));
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "123").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestGoodCallerArgumentExpressionAttribute_ExpressionHasTrivia_Attribute()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
public class MyAttribute : Attribute
{
    const string p = nameof(p);
    public MyAttribute(int p, [CallerArgumentExpression(p)] string arg = ""<default-arg>"")
    {
        Console.WriteLine(arg);
    }
}
 
[My(// comment
               123 /* comment */ +
               5 /* comment */ // comment
        )]
public class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttribute(typeof(MyAttribute));
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput:
@"123 /* comment */ +
               5").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestGoodCallerArgumentExpressionAttribute_SwapArguments_AttributeConstructor()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
public class MyAttribute : Attribute
{
    const string p = nameof(p);
    public MyAttribute(int p, int q, [CallerArgumentExpression(p)] string arg = ""<default-arg>"")
    {
        Console.WriteLine($""{p}, {q}, {arg}"");
    }
}
 
[My(q: 123, p: 124)]
public class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttribute(typeof(MyAttribute));
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "124, 123, 124").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestGoodCallerArgumentExpressionAttribute_DifferentAssembly_AttributeConstructor()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
public class MyAttribute : Attribute
{
    const string p = nameof(p);
    public MyAttribute(int p, int q, [CallerArgumentExpression(p)] string arg = ""<default-arg>"")
    {
        Console.WriteLine(arg);
    }
}
";
            var comp1 = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp);
            comp1.VerifyDiagnostics();
            var ref1 = comp1.EmitToImageReference();
 
            var source2 = @"
using System.Reflection;
 
[My(2 + 2, 3 + 1)]
public class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttribute(typeof(MyAttribute));
    }
}
";
 
            var compilation = CreateCompilation(source2, references: new[] { ref1 }, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "2 + 2").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestIncorrectParameterNameInCallerArgumentExpressionAttribute_AttributeConstructor()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
public class MyAttribute : Attribute
{
    const string pp = nameof(pp);
    public MyAttribute([CallerArgumentExpression(pp)] string arg = ""<default>"")
    {
        Console.WriteLine(arg);
    }
}
 
[My]
public class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttribute(typeof(MyAttribute));
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9);
            CompileAndVerify(compilation, expectedOutput: "<default>").VerifyDiagnostics(
                // (12,22): warning CS8918: The CallerArgumentExpressionAttribute applied to parameter 'arg' will have no effect. It is applied with an invalid parameter name.
                //     static void Log([CallerArgumentExpression(pp)] string arg = "<default>")
                Diagnostic(ErrorCode.WRN_CallerArgumentExpressionAttributeHasInvalidParameterName, "CallerArgumentExpression").WithArguments("arg").WithLocation(9, 25)
                );
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentWithMemberNameAttributes_AttributeConstructor()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
public class MyAttribute : Attribute
{
    const string p = nameof(p);
    public MyAttribute(int p, [CallerArgumentExpression(p)] [CallerMemberName] string arg = ""<default>"")
    {
        Console.WriteLine(arg);
    }
}
 
[My(default(int))]
public class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttribute(typeof(MyAttribute));
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9);
            CompileAndVerify(compilation, expectedOutput: "<default>").VerifyDiagnostics(
                // (9,32): warning CS8917: The CallerArgumentExpressionAttribute applied to parameter 'arg' will have no effect. It is overridden by the CallerMemberNameAttribute.
                //     public MyAttribute(int p, [CallerArgumentExpression(p)] [CallerMemberName] string arg = "<default>")
                Diagnostic(ErrorCode.WRN_CallerMemberNamePreferredOverCallerArgumentExpression, "CallerArgumentExpression").WithArguments("arg").WithLocation(9, 32)
                );
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentExpressionWithOptionalTargetParameter_AttributeConstructor()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class MyAttribute : Attribute
{
    const string target = nameof(target);
 
    public MyAttribute(int p, string target = ""target default value"", [CallerArgumentExpression(target)] string arg = ""arg default value"")
    {
        Console.WriteLine(target);
        Console.WriteLine(arg);
    }
}
 
[My(0)]
[My(0, callerTargetExp)]
public class Program
{
    private const string callerTargetExp = ""caller target value"";
    static void Main()
    {
        typeof(Program).GetCustomAttributes(typeof(MyAttribute));
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput:
@"target default value
arg default value
caller target value
callerTargetExp").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentExpressionWithMultipleOptionalAttribute_AttributeConstructor()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class MyAttribute : Attribute
{
    const string target = nameof(target);
    public MyAttribute(int p, string target = ""target default value"", string notTarget = ""not target default value"", [CallerArgumentExpression(target)] string arg = ""arg default value"")
    {
        Console.WriteLine(target);
        Console.WriteLine(arg);
    }
}
 
[My(0)]
[My(0, callerTargetExp)]
[My(0, target: callerTargetExp)]
[My(0, notTarget: ""Not target value"")]
[My(0, notTarget: ""Not target value"", target: callerTargetExp)]
public class Program
{
    private const string callerTargetExp = ""caller target value"";
    static void Main()
    {
        typeof(Program).GetCustomAttributes(typeof(MyAttribute));
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput:
@"target default value
arg default value
caller target value
callerTargetExp
caller target value
callerTargetExp
target default value
arg default value
caller target value
callerTargetExp").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestCallerArgumentExpressionWithDifferentParametersReferringToEachOther_AttributeConstructor()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class MyAttribute : Attribute
{
    public MyAttribute([CallerArgumentExpression(""param2"")] string param1 = ""param1_default"", [CallerArgumentExpression(""param1"")] string param2 = ""param2_default"")
    {
        Console.WriteLine($""param1: {param1}, param2: {param2}"");
    }
}
 
[My()]
[My(""param1_value"")]
[My(param1: ""param1_value"")]
[My(param2: ""param2_value"")]
[My(param1: ""param1_value"", param2: ""param2_value"")]
[My(param2: ""param2_value"", param1: ""param1_value"")]
public class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttributes(typeof(MyAttribute));
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput:
@"param1: param1_default, param2: param2_default
param1: param1_value, param2: ""param1_value""
param1: param1_value, param2: ""param1_value""
param1: ""param2_value"", param2: param2_value
param1: param1_value, param2: param2_value
param1: param1_value, param2: param2_value").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestArgumentExpressionIsCallerMember_AttributeConstructor()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
public class MyAttribute : Attribute
{
    public MyAttribute(
        [CallerMemberName] string callerName = ""<default-caller-name>"",
        [CallerArgumentExpression(""callerName"")] string argumentExp = ""<default-arg-expression>"")
    {
        Console.WriteLine(callerName);
        Console.WriteLine(argumentExp);
    }
}
 
[My]
public class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttribute(typeof(MyAttribute));
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9);
            CompileAndVerify(compilation, expectedOutput: @"<default-caller-name>
<default-arg-expression>").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestArgumentExpressionIsReferringToItself_AttributeConstructor()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class MyAttribute : Attribute
{
    public MyAttribute(
        [CallerArgumentExpression(""p"")] string p = ""<default>"")
    {
        Console.WriteLine(p);
    }
}
 
[My]
[My(""value"")]
public class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttributes(typeof(MyAttribute));
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9);
            CompileAndVerify(compilation, expectedOutput: @"<default>
value").VerifyDiagnostics(
                // (10,10): warning CS8965: The CallerArgumentExpressionAttribute applied to parameter 'p' will have no effect because it's self-referential.
                //         [CallerArgumentExpression("p")] string p = "<default>")
                Diagnostic(ErrorCode.WRN_CallerArgumentExpressionAttributeSelfReferential, "CallerArgumentExpression").WithArguments("p").WithLocation(10, 10)
                );
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestArgumentExpressionIsReferringToItself_AttributeConstructor_Metadata()
        {
            string il = @"
.class private auto ansi '<Module>'
{
} // end of class <Module>
 
.class public auto ansi beforefieldinit MyAttribute
    extends [mscorlib]System.Attribute
{
    .custom instance void [mscorlib]System.AttributeUsageAttribute::.ctor(valuetype [mscorlib]System.AttributeTargets) = (
        01 00 04 00 00 00 01 00 54 02 0d 41 6c 6c 6f 77
        4d 75 6c 74 69 70 6c 65 01
    )
    // Methods
    .method public hidebysig specialname rtspecialname 
        instance void .ctor (
            [opt] string p
        ) cil managed 
    {
        .param [1] = ""<default>""
            .custom instance void [mscorlib]System.Runtime.CompilerServices.CallerArgumentExpressionAttribute::.ctor(string) = (
                01 00 01 70 00 00
            )
        // Method begins at RVA 0x2050
        // Code size 16 (0x10)
        .maxstack 8
 
        IL_0000: ldarg.0
        IL_0001: call instance void [mscorlib]System.Attribute::.ctor()
        IL_0006: nop
        IL_0007: nop
        IL_0008: ldarg.1
        IL_0009: call void [mscorlib]System.Console::WriteLine(string)
        IL_000e: nop
        IL_000f: ret
    } // end of method MyAttribute::.ctor
 
} // end of class MyAttribute
";
            string source = @"
using System.Reflection;
 
[My]
[My(""value"")]
public class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttributes(typeof(MyAttribute));
    }
}
";
 
            var compilation = CreateCompilationWithIL(source, il, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9);
            CompileAndVerify(compilation, expectedOutput: @"<default>
value").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestArgumentExpressionInAttributeConstructor()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
public class MyAttribute : Attribute
{
    public MyAttribute(string s, [CallerArgumentExpression(""s"")] string x = """") => Console.WriteLine($""'{s}', '{x}'"");
}
 
[My(""Hello"")]
public class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttribute(typeof(MyAttribute));
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "'Hello', '\"Hello\"'").VerifyDiagnostics();
            var namedType = compilation.GetTypeByMetadataName("Program").GetPublicSymbol();
            var attributeArguments = namedType.GetAttributes().Single().ConstructorArguments;
            Assert.Equal(2, attributeArguments.Length);
            Assert.Equal("Hello", attributeArguments[0].Value);
            Assert.Equal("\"Hello\"", attributeArguments[1].Value);
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestArgumentExpressionInAttributeConstructor_NamedArgument()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
public class MyAttribute : Attribute
{
    public MyAttribute(string s, [CallerArgumentExpression(""s"")] string x = """") => Console.WriteLine($""'{s}', '{x}'"");
}
 
[My(s:""Hello"")]
public class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttribute(typeof(MyAttribute));
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "'Hello', '\"Hello\"'").VerifyDiagnostics();
            var namedType = compilation.GetTypeByMetadataName("Program").GetPublicSymbol();
            var attributeArguments = namedType.GetAttributes().Single().ConstructorArguments;
            Assert.Equal(2, attributeArguments.Length);
            Assert.Equal("Hello", attributeArguments[0].Value);
            Assert.Equal("\"Hello\"", attributeArguments[1].Value);
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestArgumentExpressionInAttributeConstructor_NamedArgumentsSameOrder()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
public class MyAttribute : Attribute
{
    public MyAttribute(string s, string s2, [CallerArgumentExpression(""s"")] string x = """") => Console.WriteLine($""'{s}', '{s2}', '{x}'"");
}
 
[My(s:""Hello"", s2:""World"")]
public class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttribute(typeof(MyAttribute));
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "'Hello', 'World', '\"Hello\"'").VerifyDiagnostics();
            var namedType = compilation.GetTypeByMetadataName("Program").GetPublicSymbol();
            var attributeArguments = namedType.GetAttributes().Single().ConstructorArguments;
            Assert.Equal(3, attributeArguments.Length);
            Assert.Equal("Hello", attributeArguments[0].Value);
            Assert.Equal("World", attributeArguments[1].Value);
            Assert.Equal("\"Hello\"", attributeArguments[2].Value);
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestArgumentExpressionInAttributeConstructor_NamedArgumentsOutOfOrder()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
public class MyAttribute : Attribute
{
    public MyAttribute(string s, string s2, [CallerArgumentExpression(""s"")] string x = """") => Console.WriteLine($""'{s}', '{s2}', '{x}'"");
}
 
[My(s2:""World"", s:""Hello"")]
public class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttribute(typeof(MyAttribute));
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "'Hello', 'World', '\"Hello\"'").VerifyDiagnostics();
            var namedType = compilation.GetTypeByMetadataName("Program").GetPublicSymbol();
            var attributeArguments = namedType.GetAttributes().Single().ConstructorArguments;
            Assert.Equal(3, attributeArguments.Length);
            Assert.Equal("Hello", attributeArguments[0].Value);
            Assert.Equal("World", attributeArguments[1].Value);
            Assert.Equal("\"Hello\"", attributeArguments[2].Value);
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestArgumentExpressionInAttributeConstructor_Complex()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class MyAttribute : Attribute
{
    public MyAttribute([CallerArgumentExpression(""param2"")] string param1 = ""param1_default"", [CallerArgumentExpression(""param1"")] string param2 = ""param2_default"") => Console.WriteLine($""param1: {param1}, param2: {param2}"");
}
 
[My]
[My()]
[My(""param1_value"")]
[My(param1: ""param1_value"")]
[My(param2: ""param2_value"")]
[My(param1: ""param1_value"", param2: ""param2_value"")]
[My(param2: ""param2_value"", param1: ""param1_value"")]
public class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttributes(typeof(MyAttribute), false);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput:
@"param1: param1_default, param2: param2_default
param1: param1_default, param2: param2_default
param1: param1_value, param2: ""param1_value""
param1: param1_value, param2: ""param1_value""
param1: ""param2_value"", param2: param2_value
param1: param1_value, param2: param2_value
param1: param1_value, param2: param2_value").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestArgumentExpressionInAttributeConstructor_NamedAndOptionalParameters()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
class MyAttribute : Attribute
{
    public MyAttribute(int a = 1, int b = 2, int c = 3, [CallerArgumentExpression(""a"")] string expr_a = """", [CallerArgumentExpression(""b"")] string expr_b = """", [CallerArgumentExpression(""c"")] string expr_c = """")
    {
        Console.WriteLine($""'{a}', '{b}', '{c}', '{expr_a}', '{expr_b}', '{expr_c}'"");
        A = a;
        B = b;
        C = c;
    }
 
    public int X;
    public int A;
    public int B;
    public int C;
}
 
[My(0+0, c:1+1, X=2+2)]
class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttribute(typeof(MyAttribute));
        _ = new MyAttribute(0+0, c: 1+1);
    }
}";
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: @"'0', '2', '2', '0+0', '', '1+1'
'0', '2', '2', '0+0', '', '1+1'").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestArgumentExpressionInAttributeConstructor_OptionalAndFieldInitializer()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
class MyAttribute : Attribute
{
    public MyAttribute([CallerArgumentExpression(""a"")] string expr_a = ""<default0>"", string a = ""<default1>"")
    {
        Console.WriteLine($""'{a}', '{expr_a}'"");
    }
 
    public int A;
    public int B;
}
 
[My(A=1, B=2)]
class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttribute(typeof(MyAttribute));
    }
}";
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "'<default1>', '<default0>'").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestArgumentExpressionInAttributeConstructor_LangVersion9()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
class MyAttribute : Attribute
{
    public MyAttribute(int a = 1, [CallerArgumentExpression(""a"")] string expr_a = """")
    {
        Console.WriteLine($""'{a}', '{expr_a}'"");
    }
}
 
[My(1+2)]
class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttribute(typeof(MyAttribute));
    }
}";
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9);
            CompileAndVerify(compilation, expectedOutput: "'3', '1+2'").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestArgumentExpression_ImplicitConversionFromStringExists()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
class MyAttribute : Attribute
{
    public MyAttribute(int a = 1, [CallerArgumentExpression(""a"")] object expr_a = null)
    {
        Console.WriteLine($""'{a}', '{expr_a}'"");
    }
}
 
[My(1+2)]
class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttribute(typeof(MyAttribute));
    }
}";
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: @"'3', '1+2'").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestArgumentExpression_ImplicitConversionFromStringDoesNotExists()
        {
            string source = @"
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
 
class MyAttribute : Attribute
{
    public MyAttribute(int a = 1, [CallerArgumentExpression(""a"")] int expr_a = 0)
    {
        Console.WriteLine($""'{a}', '{expr_a}'"");
    }
}
 
[My(1+2)]
class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttribute(typeof(MyAttribute));
    }
}";
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            compilation.VerifyDiagnostics(
                // (8,36): error CS8913: CallerArgumentExpressionAttribute cannot be applied because there are no standard conversions from type 'string' to type 'int'
                //     public MyAttribute(int a = 1, [CallerArgumentExpression("a")] int expr_a = 0)
                Diagnostic(ErrorCode.ERR_NoConversionForCallerArgumentExpressionParam, "CallerArgumentExpression").WithArguments("string", "int").WithLocation(8, 36)
            );
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestArgumentExpression_ImplicitConversionFromStringDoesNotExists_Metadata()
        {
            string il = @"
.class public auto ansi beforefieldinit MyAttribute
    extends [mscorlib]System.Attribute
{
    // Methods
    .method public hidebysig specialname rtspecialname
        instance void .ctor (
            [opt] int32 a,
            [opt] int32 expr_a
        ) cil managed
    {
        .param [1] = int32(1)
        .param [2] = int32(0)
            .custom instance void [mscorlib]System.Runtime.CompilerServices.CallerArgumentExpressionAttribute::.ctor(string) = (
                01 00 01 61 00 00
            )
        // Method begins at RVA 0x2050
        // Code size 37 (0x25)
        .maxstack 8
 
        IL_0000: ldarg.0
        IL_0001: call instance void [mscorlib]System.Attribute::.ctor()
        IL_0006: nop
        IL_0007: nop
        IL_0008: ldstr ""'{0}', '{1}'""
        IL_000d: ldarg.1
        IL_000e: box [mscorlib]System.Int32
        IL_0013: ldarg.2
        IL_0014: box [mscorlib]System.Int32
        IL_0019: call string [mscorlib]System.String::Format(string, object, object)
        IL_001e: call void [mscorlib]System.Console::WriteLine(string)
        IL_0023: nop
        IL_0024: ret
    } // end of method MyAttribute::.ctor
 
} // end of class MyAttribute
";
 
            string source = @"
using System.Reflection;
 
[My(1+2)]
class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttribute(typeof(MyAttribute));
    }
}";
            var compilation = CreateCompilationWithILAndMscorlib40(source, il, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: "'3', '0'").VerifyDiagnostics();
            var arguments = compilation.GetTypeByMetadataName("Program").GetAttributes().Single().CommonConstructorArguments;
            Assert.Equal(2, arguments.Length);
            Assert.Equal(3, arguments[0].Value);
            Assert.Equal(0, arguments[1].Value);
        }
        #endregion
 
        #region CallerArgumentExpression - Test various symbols
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestIndexers()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    const string i = nameof(i);
    public int this[int i, [CallerArgumentExpression(i)] string s = ""<default-arg>""]
    {
        get => i;
        set => Console.WriteLine($""{i}, {s}"");
    }
 
    public static void Main()
    {
        new Program()[1+  1] = 5;
        new Program()[2+  2, ""explicit-value""] = 5;
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: @"2, 1+  1
4, explicit-value").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestDelegate()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    const string s1 = nameof(s1);
    delegate void D(string s1, ref string s2, out string s3, [CallerArgumentExpression(s1)] string s4 = """");
 
    static void M(string s1, ref string s2, out string s3, string s4 = """")
    {
        s3 = """";
        Console.WriteLine($""s1: {s1}"");
        Console.WriteLine($""s2: {s2}"");
        Console.WriteLine($""s3: {s3}"");
        Console.WriteLine($""s4: {s4}"");
    }
 
    public static void Main()
    {
        D d = M;
        string s2 = ""s2-arg"";
        d.Invoke(""s1-arg"", ref s2, out _);
        //d.EndInvoke(ref s2, out _, null);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: @"s1: s1-arg
s2: s2-arg
s3: 
s4: ""s1-arg""").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestDelegate2()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    const string s3 = nameof(s3);
    delegate void D(string s1, ref string s2, out string s3, [CallerArgumentExpression(s3)] string s4 = """");
 
    static void M(string s1, ref string s2, out string s3, string s4 = """")
    {
        s3 = """";
        Console.WriteLine($""s1: {s1}"");
        Console.WriteLine($""s2: {s2}"");
        Console.WriteLine($""s3: {s3}"");
        Console.WriteLine($""s4: {s4}"");
    }
 
    public static void Main()
    {
        D d = M;
        string s2 = ""s2-arg"";
        d.Invoke(""s1-arg"", ref s2, out _);
        //d.EndInvoke(ref s2, out _, null);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation, expectedOutput: @"s1: s1-arg
s2: s2-arg
s3: 
s4: _").VerifyDiagnostics();
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestDelegate3()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    const string s1 = nameof(s1);
    delegate void D(string s1, ref string s2, out string s3, [CallerArgumentExpression(s1)] string s4 = """");
 
    static void M(string s1, ref string s2, out string s3, string s4 = """")
    {
        s3 = """";
        Console.WriteLine($""s1: {s1}"");
        Console.WriteLine($""s2: {s2}"");
        Console.WriteLine($""s3: {s3}"");
        Console.WriteLine($""s4: {s4}"");
    }
 
    public static void Main()
    {
        D d = M;
        string s2 = ""s2-arg"";
        d.EndInvoke(ref s2, out _, null);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.Net50, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation).VerifyDiagnostics().VerifyIL("Program.Main", @"
{
  // Code size       29 (0x1d)
  .maxstack  4
  .locals init (string V_0, //s2
                string V_1)
  IL_0000:  ldnull
  IL_0001:  ldftn      ""void Program.M(string, ref string, out string, string)""
  IL_0007:  newobj     ""Program.D..ctor(object, System.IntPtr)""
  IL_000c:  ldstr      ""s2-arg""
  IL_0011:  stloc.0
  IL_0012:  ldloca.s   V_0
  IL_0014:  ldloca.s   V_1
  IL_0016:  ldnull
  IL_0017:  callvirt   ""void Program.D.EndInvoke(ref string, out string, System.IAsyncResult)""
  IL_001c:  ret
}
");
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void TestDelegate4()
        {
            string source = @"
using System;
using System.Runtime.CompilerServices;
 
class Program
{
    const string s3 = nameof(s3);
    delegate void D(string s1, ref string s2, out string s3, [CallerArgumentExpression(s3)] string s4 = """");
 
    static void M(string s1, ref string s2, out string s3, string s4 = """")
    {
        s3 = """";
        Console.WriteLine($""s1: {s1}"");
        Console.WriteLine($""s2: {s2}"");
        Console.WriteLine($""s3: {s3}"");
        Console.WriteLine($""s4: {s4}"");
    }
 
    public static void Main()
    {
        D d = M;
        string s2 = ""s2-arg"";
        d.EndInvoke(ref s2, out _, null);
    }
}
";
 
            var compilation = CreateCompilation(source, targetFramework: TargetFramework.Net50, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular10);
            CompileAndVerify(compilation).VerifyDiagnostics().VerifyIL("Program.Main", @"
{
  // Code size       29 (0x1d)
  .maxstack  4
  .locals init (string V_0, //s2
                string V_1)
  IL_0000:  ldnull
  IL_0001:  ldftn      ""void Program.M(string, ref string, out string, string)""
  IL_0007:  newobj     ""Program.D..ctor(object, System.IntPtr)""
  IL_000c:  ldstr      ""s2-arg""
  IL_0011:  stloc.0
  IL_0012:  ldloca.s   V_0
  IL_0014:  ldloca.s   V_1
  IL_0016:  ldnull
  IL_0017:  callvirt   ""void Program.D.EndInvoke(ref string, out string, System.IAsyncResult)""
  IL_001c:  ret
}
");
        }
        #endregion
 
        [Fact]
        public void TestCallerInfoAttributesWithSaneDefaultValues()
        {
            string source = @"
using System.Runtime.CompilerServices;
 
class Test {
    static void LogCallerLineNumber([CallerLineNumber] int lineNumber = -1) { }
 
    static void LogCallerFilePath([CallerFilePath] string filePath = """") { }
 
    static void LogCallerMemberName([CallerMemberName] string memberName = """") { }
}";
 
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
        }
 
        [Fact]
        public void TestBadCallerInfoAttributesWithoutDefaultValues()
        {
            string source = @"
using System.Runtime.CompilerServices;
 
class Test {
    static void LogCallerLineNumber([CallerLineNumber] int lineNumber) { }
 
    static void LogCallerFilePath([CallerFilePath] string filePath) { }
 
    static void LogCallerMemberName([CallerMemberName] string memberName) { }
}";
 
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (5,38): error CS4020: The CallerLineNumberAttribute may only be applied to parameters with default values
                //     static void LogCallerLineNumber([CallerLineNumber] int lineNumber) { }
                Diagnostic(ErrorCode.ERR_BadCallerLineNumberParamWithoutDefaultValue, @"CallerLineNumber").WithLocation(5, 38),
 
                // (7,36): error CS4021: The CallerFilePathAttribute may only be applied to parameters with default values
                //     static void LogCallerFilePath([CallerFilePath] string filePath) { }
                Diagnostic(ErrorCode.ERR_BadCallerFilePathParamWithoutDefaultValue, @"CallerFilePath").WithLocation(7, 36),
 
                // (9,38): error CS4022: The CallerMemberNameAttribute may only be applied to parameters with default values
                //     static void LogCallerMemberName([CallerMemberName] string memberName) { }
                Diagnostic(ErrorCode.ERR_BadCallerMemberNameParamWithoutDefaultValue, @"CallerMemberName").WithLocation(9, 38));
        }
 
        [Fact]
        public void TestConversionForCallerLineNumber()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System;
 
class Test {
    static void LogCallerLineNumber1([CallerLineNumber, Optional, DefaultParameterValue(1 )] decimal lineNumber) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber2([CallerLineNumber, Optional, DefaultParameterValue(2 )] double  lineNumber) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber3([CallerLineNumber, Optional, DefaultParameterValue(3 )] float   lineNumber) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber4([CallerLineNumber, Optional, DefaultParameterValue(4 )] int     lineNumber) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber5([CallerLineNumber, Optional, DefaultParameterValue(5u)] uint    lineNumber) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber6([CallerLineNumber, Optional, DefaultParameterValue(6 )] long    lineNumber) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber7([CallerLineNumber, Optional, DefaultParameterValue(7u)] ulong   lineNumber) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber8([CallerLineNumber, Optional, DefaultParameterValue(8 )] object  lineNumber) { Console.WriteLine(""line: "" + lineNumber); }
 
    static void LogCallerLineNumber9 ([CallerLineNumber] decimal lineNumber =  9  ) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber10([CallerLineNumber] double  lineNumber = 10  ) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber11([CallerLineNumber] float   lineNumber = 11  ) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber12([CallerLineNumber] int     lineNumber = 12  ) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber13([CallerLineNumber] uint    lineNumber = 13  ) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber14([CallerLineNumber] long    lineNumber = 14  ) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber15([CallerLineNumber] ulong   lineNumber = 15  ) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber16([CallerLineNumber] object  lineNumber = null) { Console.WriteLine(""line: "" + lineNumber); }
 
    static void LogCallerLineNumber17([CallerLineNumber, Optional, DefaultParameterValue(17 )] decimal? lineNumber) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber18([CallerLineNumber, Optional, DefaultParameterValue(18 )] double?  lineNumber) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber19([CallerLineNumber, Optional, DefaultParameterValue(19 )] float?   lineNumber) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber20([CallerLineNumber, Optional, DefaultParameterValue(20 )] int?     lineNumber) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber21([CallerLineNumber, Optional, DefaultParameterValue(21u)] uint?    lineNumber) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber22([CallerLineNumber, Optional, DefaultParameterValue(22 )] long?    lineNumber) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber23([CallerLineNumber, Optional, DefaultParameterValue(23u)] ulong?   lineNumber) { Console.WriteLine(""line: "" + lineNumber); }
 
    static void LogCallerLineNumber25([CallerLineNumber] decimal? lineNumber = 25  ) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber26([CallerLineNumber] double?  lineNumber = 26  ) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber27([CallerLineNumber] float?   lineNumber = 27  ) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber28([CallerLineNumber] int?     lineNumber = 28  ) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber29([CallerLineNumber] uint?    lineNumber = 29  ) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber30([CallerLineNumber] long?    lineNumber = 30  ) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber31([CallerLineNumber] ulong?   lineNumber = 31  ) { Console.WriteLine(""line: "" + lineNumber); }
 
    static void LogCallerFilePath1([CallerFilePath] string filePath = """") { }
    static void LogCallerFilePath2([CallerFilePath] object filePath = null) { }
    static void LogCallerFilePath3([CallerFilePath] IComparable filePath = null) { }
 
    static void LogCallerMemberName1([CallerMemberName] string memberName = """") { }
    static void LogCallerMemberName2([CallerMemberName] object memberName = null) { }
    static void LogCallerMemberName3([CallerMemberName] IComparable memberName = null) { }
 
    public static void Main() {
        LogCallerLineNumber1();
        LogCallerLineNumber2();
        LogCallerLineNumber3();
        LogCallerLineNumber4();
        LogCallerLineNumber5();
        LogCallerLineNumber6();
        LogCallerLineNumber7();
        LogCallerLineNumber8();
        LogCallerLineNumber9();
        LogCallerLineNumber10();
        LogCallerLineNumber11();
        LogCallerLineNumber12();
        LogCallerLineNumber13();
        LogCallerLineNumber14();
        LogCallerLineNumber15();
        LogCallerLineNumber16();
        LogCallerLineNumber17();
        LogCallerLineNumber18();
        LogCallerLineNumber19();
        LogCallerLineNumber20();
        LogCallerLineNumber21();
        LogCallerLineNumber22();
        LogCallerLineNumber23();
        LogCallerLineNumber25();
        LogCallerLineNumber26();
        LogCallerLineNumber27();
        LogCallerLineNumber28();
        LogCallerLineNumber29();
        LogCallerLineNumber30();
        LogCallerLineNumber31();
    }
}";
 
            string expected = @"
line: 50
line: 51
line: 52
line: 53
line: 54
line: 55
line: 56
line: 57
line: 58
line: 59
line: 60
line: 61
line: 62
line: 63
line: 64
line: 65
line: 66
line: 67
line: 68
line: 69
line: 70
line: 71
line: 72
line: 73
line: 74
line: 75
line: 76
line: 77
line: 78
line: 79
";
            var compilation = CreateCompilationWithMscorlib461(source, new MetadataReference[] { SystemRef }, TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestDelegateInvoke()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System;
using System.Collections.Generic;
 
class Test {
    static void LogCallerLineNumber1(int lineNumber = -1) { Console.WriteLine(""line: "" + lineNumber); }
 
    public static void Main() {
        List<Action> list = new List<Action>();
        list.Add(() => LogCallerLineNumber1());
        list.Add(() => LogCallerLineNumber1());
        list.Add(() => LogCallerLineNumber1());
        
        foreach (var x in list) {
            x();
        }
    }
}";
 
            string expected = @"
line: -1
line: -1
line: -1
";
 
            var compilation = CreateCompilationWithMscorlib461(source, new MetadataReference[] { SystemRef }, TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestConversionForCallerInfoAttributes()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System;
 
class Test {
    static void LogCallerLineNumber1([CallerLineNumber, Optional, DefaultParameterValue(1)] int lineNumber) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber2([CallerLineNumber] long lineNumber   = 2) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber3([CallerLineNumber] double lineNumber = 3) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber4([CallerLineNumber] float lineNumber  = 4) { Console.WriteLine(""line: "" + lineNumber); }
    static void LogCallerLineNumber5([CallerLineNumber] int? lineNumber   = 5) { Console.WriteLine(""line: "" + lineNumber); }
 
    static void LogCallerFilePath1([CallerFilePath] string filePath = """") { }
    static void LogCallerFilePath2([CallerFilePath] object filePath = null) { }
    static void LogCallerFilePath3([CallerFilePath] IComparable filePath = null) { }
 
    static void LogCallerMemberName1([CallerMemberName] string memberName = """") { }
    static void LogCallerMemberName2([CallerMemberName] object memberName = null) { }
    static void LogCallerMemberName3([CallerMemberName] IComparable memberName = null) { }
 
    public static void Main() {
        LogCallerLineNumber1();
        LogCallerLineNumber2();
        LogCallerLineNumber3();
        LogCallerLineNumber4();
        LogCallerLineNumber5();
    }
}";
 
            string expected = @"
line: 22
line: 23
line: 24
line: 25
line: 26
";
 
            var compilation = CreateCompilationWithMscorlib461(source, new[] { SystemRef }, TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestBadConversionForCallerInfoAttributes()
        {
            string source = @"
using System.Runtime.CompilerServices;
 
class Test {
    static void LogCallerLineNumber1([CallerLineNumber] string lineNumber = """") { }
    static void LogCallerLineNumber2([CallerLineNumber] char lineNumber = '\0') { }
    static void LogCallerLineNumber3([CallerLineNumber] bool lineNumber = false) { }
    static void LogCallerLineNumber3([CallerLineNumber] short lineNumber = 0) { }
    static void LogCallerLineNumber3([CallerLineNumber] ushort lineNumber = 0) { }
 
    static void LogCallerFilePath1([CallerFilePath] int filePath = 0) { }
    static void LogCallerFilePath2([CallerFilePath] long filePath = 0) { }
    static void LogCallerFilePath3([CallerFilePath] double filePath = 0) { }
    static void LogCallerFilePath4([CallerFilePath] float filePath = 0) { }
    static void LogCallerFilePath5([CallerFilePath] int? filePath = 0) { }
 
    static void LogCallerMemberName1([CallerMemberName] int memberName = 0) { }
    static void LogCallerMemberName2([CallerMemberName] long memberName = 0) { }
    static void LogCallerMemberName3([CallerMemberName] double memberName = 0) { }
    static void LogCallerMemberName4([CallerMemberName] float memberName = 0) { }
    static void LogCallerMemberName5([CallerMemberName] int? memberName = 0) { }
}";
 
            CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { SystemRef }).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithLocation(5, 39).WithArguments("int", "string"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithLocation(6, 39).WithArguments("int", "char"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithLocation(7, 39).WithArguments("int", "bool"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithLocation(8, 39).WithArguments("int", "short"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithLocation(9, 39).WithArguments("int", "ushort"),
 
                Diagnostic(ErrorCode.ERR_NoConversionForCallerFilePathParam, "CallerFilePath").WithLocation(11, 37).WithArguments("string", "int"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerFilePathParam, "CallerFilePath").WithLocation(12, 37).WithArguments("string", "long"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerFilePathParam, "CallerFilePath").WithLocation(13, 37).WithArguments("string", "double"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerFilePathParam, "CallerFilePath").WithLocation(14, 37).WithArguments("string", "float"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerFilePathParam, "CallerFilePath").WithLocation(15, 37).WithArguments("string", "int?"),
 
                Diagnostic(ErrorCode.ERR_NoConversionForCallerMemberNameParam, "CallerMemberName").WithLocation(17, 39).WithArguments("string", "int"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerMemberNameParam, "CallerMemberName").WithLocation(18, 39).WithArguments("string", "long"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerMemberNameParam, "CallerMemberName").WithLocation(19, 39).WithArguments("string", "double"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerMemberNameParam, "CallerMemberName").WithLocation(20, 39).WithArguments("string", "float"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerMemberNameParam, "CallerMemberName").WithLocation(21, 39).WithArguments("string", "int?"));
        }
 
        [Fact]
        public void TestCallerLineNumber()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class Test
{
    static void Log(
        string message,
        [CallerLineNumber] int lineNumber = -1)
    {
        Console.WriteLine(""message: "" + message);
        Console.WriteLine(""line: "" + lineNumber);
    }
 
    public static void Main()
    {
        Log(""something happened"");
        // comment
        Log
            // comment
            (
            // comment
            ""something happened""
            // comment
            )
            // comment
            ;
        // comment
    }
}";
 
            var expected = @"
message: something happened
line: 17
message: something happened
line: 21
";
 
            var compilation = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerLineNumber_LocalFunctionAttribute()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class Test
{
    public static void Main()
    {
        log(""something happened"");
        // comment
        log
            // comment
            (
            // comment
            ""something happened""
            // comment
            )
            // comment
            ;
        // comment
 
        static void log(
            string message,
            [CallerLineNumber] int lineNumber = -1)
        {
            Console.WriteLine(""message: "" + message);
            Console.WriteLine(""line: "" + lineNumber);
        }
    }
}";
 
            var expected = @"
message: something happened
line: 9
message: something happened
line: 13
";
 
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerLineNumberImplicitCall()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class A
{
    public A([CallerLineNumber] int lineNumber = -1)
    {
        Console.WriteLine(""line: "" + lineNumber);
    }
}
 
class B : A
{
}
 
class Test
{
    public static void Main()
    {
        new B();
    }
}";
 
            var expected = @"
line: -1
";
 
            var compilation = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerLineNumberConstructorCall()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class A
{
    public A([CallerLineNumber] int lineNumber = -1)
    {
        Console.WriteLine(""line: "" + lineNumber);
    }
}
 
class Test
{
    public static void Main()
    {
        new A();
    }
}";
 
            var expected = @"
line: 17
";
 
            var compilation = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerLineNumberCustomAttributeConstructorCall()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System.Reflection;
using System;
 
class MyCallerInfoAttribute : Attribute
{
    public MyCallerInfoAttribute(
        string message,
        [CallerLineNumber] int lineNumber = -1)
    {
        Console.WriteLine(""message: "" + message);
        Console.WriteLine(""line: "" + lineNumber);
    }
}
 
class MyCallerInfo2Attribute : Attribute
{
    public MyCallerInfo2Attribute([CallerLineNumber] int lineNumber = -1)
    {
        Console.WriteLine(""line: "" + lineNumber);
    }
}
 
[MyCallerInfo(""this is a message"")]
class A
{
}
 
// comment
[
// comment
MyCallerInfo
    // comment
    (
    // comment
    ""this is a message""
    // comment
    )
// comment
]
// comment
class B
{
}
 
[MyCallerInfo2]
class C
{
}
 
// comment
[
// comment
MyCallerInfo2
// comment
]
// comment
class D
{
}
 
class Test
{
    public static void Main()
    {
        typeof(A).GetCustomAttribute(typeof(MyCallerInfoAttribute), false);
        typeof(B).GetCustomAttribute(typeof(MyCallerInfoAttribute), false);
        typeof(C).GetCustomAttribute(typeof(MyCallerInfo2Attribute), false);
        typeof(D).GetCustomAttribute(typeof(MyCallerInfo2Attribute), false);
    }
}";
 
            var expected = @"
message: this is a message
line: 25
message: this is a message
line: 33
line: 47
line: 55
";
 
            var compilation = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerLineNumberMemberCall()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
public class B
{
    public void Log([CallerLineNumber] int a = -1)
    {
        Console.WriteLine(""line: "" + a);
    }
}
 
class Test
{
    public static void Main()
    {
        new B().Log();
    }
}";
 
            var expected = @"
line: 17
";
 
            var compilation = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestBadCallerLineNumberMetadata()
        {
            var iLSource = @"
.class public auto ansi beforefieldinit Test
       extends [mscorlib]System.Object
{
  .method public hidebysig static void  LogCallerLineNumber1([opt] int32 lineNumber) cil managed
  {
    .param [1] = int32(0xFFFFFFFF)
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CallerLineNumberAttribute::.ctor() = ( 01 00 00 00 ) 
    // Code size       24 (0x18)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ldstr      ""line: ""
    IL_0006:  ldarg.0
    IL_0007:  box        [mscorlib]System.Int32
    IL_000c:  call       string [mscorlib]System.String::Concat(object,
                                                                object)
    IL_0011:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_0016:  nop
    IL_0017:  ret
  } // end of method Test::LogCallerLineNumber1
 
  .method public hidebysig static void  LogCallerLineNumber2(int32 lineNumber) cil managed
  {
	.custom instance void [mscorlib]System.Runtime.CompilerServices.CallerLineNumberAttribute::.ctor() = ( 01 00 00 00 ) 
    // Code size       24 (0x18)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ldstr      ""line: ""
    IL_0006:  ldarg.0
    IL_0007:  box        [mscorlib]System.Int32
    IL_000c:  call       string [mscorlib]System.String::Concat(object,
                                                                object)
    IL_0011:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_0016:  nop
    IL_0017:  ret
  } // end of method Test::LogCallerLineNumber2
 
  .method public hidebysig static void  LogCallerLineNumber3([opt] string lineNumber) cil managed
  {
	.param [1] = ""hello""
	.custom instance void [mscorlib]System.Runtime.CompilerServices.CallerLineNumberAttribute::.ctor() = ( 01 00 00 00 ) 
    // Code size       19 (0x13)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ldstr      ""line: ""
    IL_0006:  ldarg.0
    IL_0007:  call       string [mscorlib]System.String::Concat(string,
                                                                string)
    IL_000c:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_0011:  nop
    IL_0012:  ret
  } // end of method Test::LogCallerLineNumber3
 
  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // Code size       7 (0x7)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  ret
  } // end of method Test::.ctor
 
} // end of class Test
";
 
            var source = @"
using System.Runtime.CompilerServices;
using System;
 
class Driver {
    public static void Main() {
        Test.LogCallerLineNumber1();
        Test.LogCallerLineNumber2(42);
        Test.LogCallerLineNumber3();
    }
}
";
 
            var expected = @"
line: 7
line: 42
line: hello
";
 
            MetadataReference libReference = CompileIL(iLSource);
            var compilation = CreateCompilationWithMscorlib461(source, new[] { libReference }, TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerLineNumberDuplicateAttribute()
        {
            string source = @"
using System.Runtime.CompilerServices;
 
partial class D
{
    partial void Goo([CallerLineNumber] int x = 2);
}
 
partial class D
{
    partial void Goo([CallerLineNumber] int x)
    {
    }
 
    public static void Main()
    {
    }
}";
 
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_DuplicateAttribute, "CallerLineNumber").WithArguments("CallerLineNumber"),
                Diagnostic(ErrorCode.WRN_CallerLineNumberParamForUnconsumedLocation, "CallerLineNumber").WithArguments("x").WithLocation(11, 23));
        }
 
        [Fact, WorkItem(531044, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531044")]
        public void TestUnconsumedCallerInfoAttributes()
        {
            string source = @"
using System.Runtime.CompilerServices;
 
partial class D
{
    partial void Goo(int line, string member, string path);
}
 
partial class D
{
    partial void Goo(
        [CallerLineNumber] int line,
        [CallerMemberName] string member,
        [CallerFilePath] string path) { }
 
    public static void Main()
    {
    }
}";
 
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (12,10): warning CS4024: The CallerLineNumberAttribute applied to parameter 'line' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //         [CallerLineNumber] int line,
                Diagnostic(ErrorCode.WRN_CallerLineNumberParamForUnconsumedLocation, "CallerLineNumber").WithArguments("line"),
                // (13,10): warning CS4026: The CallerMemberNameAttribute applied to parameter 'member' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //         [CallerMemberName] string member,
                Diagnostic(ErrorCode.WRN_CallerMemberNameParamForUnconsumedLocation, "CallerMemberName").WithArguments("member"),
                // (14,10): warning CS4025: The CallerFilePathAttribute applied to parameter 'path' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //         [CallerFilePath] string path) { }
                Diagnostic(ErrorCode.WRN_CallerFilePathParamForUnconsumedLocation, "CallerFilePath").WithArguments("path"));
 
            CompileAndVerify(source, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: verify);
 
            void verify(ModuleSymbol module)
            {
                // https://github.com/dotnet/roslyn/issues/73482
                // These are ignored in source but they still get written out to metadata.
                // This means if the method is accessible from another compilation, then the attribute will be respected there, but not in the declaring compilation.
                var goo = module.GlobalNamespace.GetMember<MethodSymbol>("D.Goo");
                AssertEx.Equal(["System.Runtime.CompilerServices.CallerLineNumberAttribute"], goo.Parameters[0].GetAttributes().SelectAsArray(attr => attr.ToString()));
                AssertEx.Equal(["System.Runtime.CompilerServices.CallerMemberNameAttribute"], goo.Parameters[1].GetAttributes().SelectAsArray(attr => attr.ToString()));
                AssertEx.Equal(["System.Runtime.CompilerServices.CallerFilePathAttribute"], goo.Parameters[2].GetAttributes().SelectAsArray(attr => attr.ToString()));
            }
        }
 
        [Fact]
        public void TestCallerLineNumberViaDelegate()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class Test
{
    public static void Log([CallerLineNumber] int x = 1)
    {
        Console.WriteLine(""line: "" + x);
    }
 
    delegate void Del([CallerLineNumber] int x = 1);
 
    public static void Main()
    {
        Log();
        Del d = new Del(Log);
        d();
    }
}";
 
            var expected = @"
line: 16
line: 18
";
 
            var compilation = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestBadConversionCallerInfoMultipleAttributes()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class Test
{
    public static void Log1([CallerLineNumber, CallerFilePath, CallerMemberName] int x = 1) { Console.WriteLine(""line: "" + x); }
    public static void Log2([CallerLineNumber, CallerMemberName, CallerFilePath] int x = 1) { Console.WriteLine(""line: "" + x); }
    public static void Log3([CallerMemberName, CallerLineNumber, CallerFilePath] int x = 1) { Console.WriteLine(""line: "" + x); }
    public static void Log4([CallerMemberName, CallerFilePath, CallerLineNumber] int x = 1) { Console.WriteLine(""line: "" + x); }
    public static void Log5([CallerFilePath, CallerMemberName, CallerLineNumber] int x = 1) { Console.WriteLine(""line: "" + x); }
    public static void Log6([CallerFilePath, CallerLineNumber, CallerMemberName] int x = 1) { Console.WriteLine(""line: "" + x); }
 
    public static void Log7([CallerLineNumber, CallerFilePath, CallerMemberName] string x = """") { }
    public static void Log8([CallerLineNumber, CallerMemberName, CallerFilePath] string x = """") { }
    public static void Log9([CallerMemberName, CallerLineNumber, CallerFilePath] string x = """") { }
    public static void Log10([CallerMemberName, CallerFilePath, CallerLineNumber] string x = """") { }
    public static void Log11([CallerFilePath, CallerMemberName, CallerLineNumber] string x = """") { }
    public static void Log12([CallerFilePath, CallerLineNumber, CallerMemberName] string x = """") { }
 
    public static void Log13([CallerFilePath, CallerMemberName] string x = """") { }
    public static void Log14([CallerMemberName, CallerFilePath] string x = """") { }
 
    public static void Log15([CallerLineNumber, CallerFilePath] string x = """") { }
    public static void Log16([CallerFilePath, CallerLineNumber] string x = """") { }
 
    public static void Log17([CallerMemberName, CallerLineNumber] string x = """") { }
    public static void Log18([CallerLineNumber, CallerMemberName] string x = """") { }
 
    public static void Log19([CallerFilePath, CallerMemberName] int x = 1) { }
    public static void Log20([CallerMemberName, CallerFilePath] int x = 1) { }
 
    public static void Log21([CallerLineNumber, CallerFilePath] int x = 1) { Console.WriteLine(""line: "" + x); }
    public static void Log22([CallerFilePath, CallerLineNumber] int x = 1) { Console.WriteLine(""line: "" + x); }
 
    public static void Log23([CallerMemberName, CallerLineNumber] int x = 1) { Console.WriteLine(""line: "" + x); }
    public static void Log24([CallerLineNumber, CallerMemberName] int x = 1) { Console.WriteLine(""line: "" + x); }
}";
            CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseDll.WithWarningLevel(0)).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_NoConversionForCallerFilePathParam, "CallerFilePath").WithLocation(7, 48).WithArguments("string", "int"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerMemberNameParam, "CallerMemberName").WithLocation(7, 64).WithArguments("string", "int"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerMemberNameParam, "CallerMemberName").WithLocation(8, 48).WithArguments("string", "int"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerFilePathParam, "CallerFilePath").WithLocation(8, 66).WithArguments("string", "int"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerMemberNameParam, "CallerMemberName").WithLocation(9, 30).WithArguments("string", "int"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerFilePathParam, "CallerFilePath").WithLocation(9, 66).WithArguments("string", "int"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerMemberNameParam, "CallerMemberName").WithLocation(10, 30).WithArguments("string", "int"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerFilePathParam, "CallerFilePath").WithLocation(10, 48).WithArguments("string", "int"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerFilePathParam, "CallerFilePath").WithLocation(11, 30).WithArguments("string", "int"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerMemberNameParam, "CallerMemberName").WithLocation(11, 46).WithArguments("string", "int"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerFilePathParam, "CallerFilePath").WithLocation(12, 30).WithArguments("string", "int"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerMemberNameParam, "CallerMemberName").WithLocation(12, 64).WithArguments("string", "int"),
 
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithLocation(14, 30).WithArguments("int", "string"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithLocation(15, 30).WithArguments("int", "string"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithLocation(16, 48).WithArguments("int", "string"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithLocation(17, 65).WithArguments("int", "string"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithLocation(18, 65).WithArguments("int", "string"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithLocation(19, 47).WithArguments("int", "string"),
 
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithLocation(24, 31).WithArguments("int", "string"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithLocation(25, 47).WithArguments("int", "string"),
 
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithLocation(27, 49).WithArguments("int", "string"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithLocation(28, 31).WithArguments("int", "string"),
 
                Diagnostic(ErrorCode.ERR_NoConversionForCallerFilePathParam, "CallerFilePath").WithLocation(30, 31).WithArguments("string", "int"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerMemberNameParam, "CallerMemberName").WithLocation(30, 47).WithArguments("string", "int"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerMemberNameParam, "CallerMemberName").WithLocation(31, 31).WithArguments("string", "int"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerFilePathParam, "CallerFilePath").WithLocation(31, 49).WithArguments("string", "int"),
 
                Diagnostic(ErrorCode.ERR_NoConversionForCallerFilePathParam, "CallerFilePath").WithLocation(33, 49).WithArguments("string", "int"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerFilePathParam, "CallerFilePath").WithLocation(34, 31).WithArguments("string", "int"),
 
                Diagnostic(ErrorCode.ERR_NoConversionForCallerMemberNameParam, "CallerMemberName").WithLocation(36, 31).WithArguments("string", "int"),
                Diagnostic(ErrorCode.ERR_NoConversionForCallerMemberNameParam, "CallerMemberName").WithLocation(37, 49).WithArguments("string", "int"));
        }
 
        [Fact]
        public void TestCallerInfoMultipleAttributes()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class Test
{
    public static void Log7([CallerFilePath, CallerMemberName] string x = """") { Console.WriteLine(x); }
    public static void Log8([CallerMemberName, CallerFilePath] string x = """") { Console.WriteLine(x); }
 
    public static void Main()
    {
        Log7();
        Log8();
    }
}";
 
            var expected = @"
C:\file.cs
C:\file.cs
";
 
            var compilation = CreateCompilationWithMscorlib461(
                new[] { Parse(source, @"C:\file.cs") },
                new[] { SystemRef },
                TestOptions.ReleaseExe);
 
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerAttributeBash()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System.Reflection;
using System;
 
class MyCallerInfoAttribute : Attribute
{
    public MyCallerInfoAttribute(
        [CallerLineNumber] double lineNumber = -1)
    {
        Console.WriteLine(""line: "" + lineNumber);
    }
}
 
[MyCallerInfo]
class A
{
}
 
class Test
{
    public static void Main()
    {
        typeof(A).GetCustomAttribute(typeof(MyCallerInfoAttribute), false);
    }
}";
 
            var expected = @"
line: 15
";
 
            var compilation = CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { SystemRef }, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerLineNumberUnconsumedBadType()
        {
            string source = @"
using System.Runtime.CompilerServices;
 
partial class D
{
    partial void Goo(string x = """");
}
 
partial class D
{
    partial void Goo([CallerLineNumber] string x)
    {
    }
 
    public static void Main()
    {
    }
}";
 
            var compilation = CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { SystemRef });
            compilation.VerifyDiagnostics(
                Diagnostic(ErrorCode.WRN_CallerLineNumberParamForUnconsumedLocation, "CallerLineNumber").WithArguments("x").WithLocation(11, 23));
        }
 
        [WorkItem(689618, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/689618")]
        [Fact]
        public void TestCallerMemberNameUnconsumedBadType()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
partial class D
{
    partial void Goo(string x = """");
}
 
partial class D
{
    partial void Goo([CallerMemberName] string x)
    {
        Console.WriteLine(x);
    }
 
    public static void Main()
    {
        new D().Goo();
    }
}";
 
            var compilation = CreateCompilationWithMscorlib461(source, new[] { SystemRef }, TestOptions.ReleaseExe);
 
            compilation.VerifyEmitDiagnostics(
                // (12,23): warning CS4026: The CallerMemberNameAttribute applied to parameter 'x' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     partial void Goo([CallerMemberName] string x)
                Diagnostic(ErrorCode.WRN_CallerMemberNameParamForUnconsumedLocation, "CallerMemberName").WithArguments("x").WithLocation(12, 23));
 
            CompileAndVerify(compilation, expectedOutput: "");
        }
 
        [WorkItem(689618, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/689618")]
        [Fact]
        public void TestCallerMemberNameUnconsumedBadType02()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
partial class D
{
    partial void Goo([CallerMemberName] string x = """");
}
 
partial class D
{
    partial void Goo(string x)
    {
        Console.WriteLine(x);
    }
 
    public static void Main()
    {
        new D().Goo();
    }
}";
 
            var compilation = CreateCompilationWithMscorlib461(source, new[] { SystemRef }, TestOptions.ReleaseExe);
            compilation.VerifyEmitDiagnostics();
            CompileAndVerify(compilation, expectedOutput: "Main");
        }
 
        [Fact]
        public void TestCallerMemberName_Lambda()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class D
{
    public void LambdaCaller()
    {
        new Action(() =>
        {
            Test.Log();
        })();
    }
}
 
class Test
{
    public static int Log([CallerMemberName] string callerName = """")
    {
        Console.WriteLine(""name: "" + callerName);
        return 1;
    }
 
    public static void Main()
    {
        var d = new D();
        d.LambdaCaller();
    }
}";
 
            var expected = @"
name: LambdaCaller
";
 
            var compilation = CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { SystemRef }, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerMemberName_LocalFunction()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class D
{
    public void LocalFunctionCaller()
    {
        void Local()
        {
            void LocalNested() => Test.Log();
            LocalNested();
        }
        Local();
    }
}
 
class Test
{
    public static int Log([CallerMemberName] string callerName = """")
    {
        Console.WriteLine(""name: "" + callerName);
        return 1;
    }
 
    public static void Main()
    {
        var d = new D();
        d.LocalFunctionCaller();
    }
}";
 
            var expected = @"
name: LocalFunctionCaller
";
 
            var compilation = CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { SystemRef }, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerMemberName_LocalFunctionAttribute_01()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class D
{
    public void LocalFunctionCaller()
    {
        static int log([CallerMemberName] string callerName = """")
        {
            Console.WriteLine(""name: "" + callerName);
            return 1;
        }
 
        log();
    }
}
 
class Test
{
 
    public static void Main()
    {
        var d = new D();
        d.LocalFunctionCaller();
    }
}";
 
            var expected = @"
name: LocalFunctionCaller
";
 
            var compilation = CreateCompilation(
                source,
                options: TestOptions.ReleaseExe,
                parseOptions: TestOptions.Regular9);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerMemberName_LocalFunctionAttribute_02()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class D
{
    public void LocalFunctionCaller()
    {
        static void local1()
        {
            static void log([CallerMemberName] string callerName = """")
            {
                Console.WriteLine(""name: "" + callerName);
            }
 
            log();
        }
 
        local1();
    }
}
 
class Test
{
 
    public static void Main()
    {
        var d = new D();
        d.LocalFunctionCaller();
    }
}";
 
            var expected = @"
name: LocalFunctionCaller
";
 
            var compilation = CreateCompilation(
                source,
                options: TestOptions.ReleaseExe,
                parseOptions: TestOptions.Regular9);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerMemberName_LocalFunctionAttribute_03()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class D
{
    public void LocalFunctionCaller()
    {
        new Action(() =>
        {
            static void local1()
            {
                static void log([CallerMemberName] string callerName = """")
                {
                    Console.WriteLine(""name: "" + callerName);
                }
 
                log();
            }
 
            local1();
        }).Invoke();
    }
}
 
class Test
{
 
    public static void Main()
    {
        var d = new D();
        d.LocalFunctionCaller();
    }
}";
 
            var expected = @"
name: LocalFunctionCaller
";
 
            var compilation = CreateCompilation(
                source,
                options: TestOptions.ReleaseExe,
                parseOptions: TestOptions.Regular9);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerMemberName_Operator()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class D
{
    public static D operator ++(D d)
    {
        Test.Log();
        return d;
    }
}
 
class Test
{
    public static int Log([CallerMemberName] string callerName = """")
    {
        Console.WriteLine(""name: "" + callerName);
        return 1;
    }
 
    public static void Main()
    {
        var d = new D();
        d++;
    }
}";
 
            var expected = @"
name: op_Increment
";
 
            var compilation = CreateCompilationWithMscorlib461(source, new[] { SystemRef }, TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerMemberName_Property()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class D
{
    public bool IsTrue
    {
        get
        {
            Test.Log();
            return true;
        }
        set
        {
            Test.Log();
        }
    }
}
 
class Test
{
    public static int Log([CallerMemberName] string callerName = """")
    {
        Console.WriteLine(""name: "" + callerName);
        return 1;
    }
 
    public static void Main()
    {
        var d = new D();
        bool truth = d.IsTrue;
        d.IsTrue = truth;
    }
}";
 
            var expected = @"
name: IsTrue
name: IsTrue
";
 
            var compilation = CreateCompilationWithMscorlib461(source, new[] { SystemRef }, TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerMemberName_CustomAttribute()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class DummyAttribute : Attribute
{
    public DummyAttribute([CallerMemberName] string callerName = """")
    {
        Console.WriteLine(""name: "" + callerName);
    }
}
 
class A
{
    [Dummy]
    public void MyMethod() {
    }
}
 
class Test
{
    public static void Main()
    {
         typeof(A).GetMethod(""MyMethod"").GetCustomAttributes(typeof(DummyAttribute), false);
    }
}";
 
            var expected = @"
name: MyMethod
";
 
            var compilation = CreateCompilationWithMscorlib461(source, new[] { SystemRef }, TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerMemberName_Generic()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class G
{
    public static int Compare<T>(T a, T b) where T : IComparable {
        A.Log();
        return a.CompareTo(b);
    }
}
 
class A
{
    public static int Log([CallerMemberName] string callerName = """")
    {
        Console.WriteLine(""name: "" + callerName);
        return 1;
    }
 
    public static void Main()
    {
         G.Compare<int>(1, 2);
    }
}";
 
            var expected = @"
name: Compare
";
 
            var compilation = CreateCompilationWithMscorlib461(
                source,
                new[] { SystemRef },
                TestOptions.ReleaseExe);
 
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerMemberName_ExplicitInterfaceInstantiation()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
interface I
{
    int Add(int a, int b);
 
    bool HasThing { get; }
}
 
class II : I
{
    int I.Add(int a, int b)
    {
        A.Log();
        return a + b;
    }
 
    bool I.HasThing
    {
        get
        {
            A.Log();
            return false;
        }
    }
}
 
class A
{
    public static int Log([CallerMemberName] string callerName = """")
    {
        Console.WriteLine(""name: "" + callerName);
        return 1;
    }
 
    public static void Main()
    {
        var ii = new II();
        ((I)ii).Add(1, 2);
        bool truth = ((I)ii).HasThing;
    }
}";
 
            var expected = @"
name: Add
name: HasThing
";
 
            var compilation = CreateCompilationWithMscorlib461(source, new[] { SystemRef }, TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerMemberName_Event()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class E
{
    public event Action ThingHappened
    {
        add { A.Log(); }
        remove { A.Log(); }
    }
}
 
class A
{
    public static int Log([CallerMemberName] string callerName = """")
    {
        Console.WriteLine(""name: "" + callerName);
        return 1;
    }
 
    public static void Main()
    {
        Action goo = new Action(() => { });
        var e = new E();
        e.ThingHappened += goo;
        e.ThingHappened -= goo;
    }
}";
 
            var expected = @"
name: ThingHappened
name: ThingHappened
";
 
            var compilation = CreateCompilationWithMscorlib461(source, new[] { SystemRef }, TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [ConditionalFact(typeof(DesktopOnly))]
        public void TestCallerMemberName_ConstructorDestructor()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class D
{
    static D()
    {
        A.Log();
    }
 
    public D()
    {
        A.Log();
    }
 
    ~D()
    {
        A.Log();
    }
}
 
class A
{
    public static int Log([CallerMemberName] string callerName = """")
    {
        Console.WriteLine(""name: "" + callerName);
        return 1;
    }
 
    public static void Main()
    {
        D d = new D();
        d = null;
        GC.Collect(GC.MaxGeneration);
        GC.WaitForPendingFinalizers();
    }
}";
 
            var expected = @"
name: .cctor
name: .ctor
name: Finalize
";
 
            var compilation = CreateCompilationWithMscorlib461(source, new[] { SystemRef }, TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerMemberName_Indexer()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
 
class D
{
    [IndexerName(""TheIndexer"")]
    public int this[int index]
    {
        get
        {
            A.Log();
            return -1;
        }
        set
        {
            A.Log();
        }
    }
}
 
class DX
{
    public int this[int index]
    {
        get
        {
            A.Log();
            return -1;
        }
        set
        {
            A.Log();
        }
    }
}
 
class A
{
    public static int Log([CallerMemberName] string callerName = """")
    {
        Console.WriteLine(""name: "" + callerName);
        return 1;
    }
 
    public static void Main()
    {
        {
            var d = new D();
            int i = d[0];
            d[0] = i;
        }
        {
            var d = new DX();
            int i = d[0];
            d[0] = i;
        }
    }
}";
 
            var expected = @"
name: TheIndexer
name: TheIndexer
name: Item
name: Item
";
 
            var compilation = CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { SystemRef }, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerFilePath1()
        {
            string source1 = @"
using System.Runtime.CompilerServices;
using System;
 
partial class A
{
    static int i;
 
    public static void Log([CallerFilePath] string filePath = """")
    {
        Console.WriteLine(""{0}: '{1}'"", ++i, filePath);
    }
 
    public static void Main()
    {
        Log();
        Main2();
        Main3();
        Main4();
    }
}";
            string source2 = @"partial class A { static void Main2() { Log(); } }";
            string source3 = @"partial class A { static void Main3() { Log(); } }";
            string source4 = @"partial class A { static void Main4() { Log(); } }";
 
            var compilation = CreateCompilationWithMscorlib461(
                new[]
                {
                    SyntaxFactory.ParseSyntaxTree(source1, path: @"C:\filename", encoding: Encoding.UTF8),
                    SyntaxFactory.ParseSyntaxTree(source2, path: @"a\b\..\c\d", encoding: Encoding.UTF8),
                    SyntaxFactory.ParseSyntaxTree(source3, path: @"*", encoding: Encoding.UTF8),
                    SyntaxFactory.ParseSyntaxTree(source4, path: @"       ", encoding: Encoding.UTF8),
                },
                new[] { SystemRef },
                TestOptions.ReleaseExe.WithSourceReferenceResolver(SourceFileResolver.Default));
 
            CompileAndVerify(compilation, expectedOutput: @"
1: 'C:\filename'
2: 'a\b\..\c\d'
3: '*'
4: '       '
");
        }
 
        [Fact]
        public void TestCallerFilePath_LocalFunctionAttribute()
        {
            string source1 = @"
using System.Runtime.CompilerServices;
using System;
 
partial class A
{
    static int i;
 
    public static void Main()
    {
        log();
        log();
 
        static void log([System.Runtime.CompilerServices.CallerFilePathAttribute] string filePath = """")
        {
            Console.WriteLine(""{0}: '{1}'"", ++i, filePath);
        }
    }
}";
 
            var compilation = CreateCompilation(
                new[]
                {
                    SyntaxFactory.ParseSyntaxTree(source1, options: TestOptions.Regular9, path: @"C:\filename", encoding: Encoding.UTF8)
                },
                options: TestOptions.ReleaseExe.WithSourceReferenceResolver(SourceFileResolver.Default));
 
            CompileAndVerify(compilation, expectedOutput: @"
1: 'C:\filename'
2: 'C:\filename'
");
        }
 
        [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.TestExecutionHasNewLineDependency)]
        public void TestCallerFilePath2()
        {
            string source1 = @"
using System.Runtime.CompilerServices;
using System;
 
partial class A
{
    static int i;
 
    public static void Log([CallerFilePath] string filePath = """")
    {
        Console.WriteLine(""{0}: '{1}'"", ++i, filePath);
    }
 
    public static void Main()
    {
        Log();
        Main2();
        Main3();
        Main4();
        Main5();
    }
}";
            string source2 = @"partial class A { static void Main2() { Log(); } }";
            string source3 = @"
#line hidden
partial class A { static void Main3() { Log(); } }
";
 
            string source4 = @"
#line 30 ""abc""
partial class A { static void Main4() { Log(); } }
";
            string source5 = @"
#line 30 ""     ""
partial class A { static void Main5() { Log(); } }
";
 
            var compilation = CreateCompilationWithMscorlib461(
                new[]
                {
                    SyntaxFactory.ParseSyntaxTree(source1, path: @"C:\filename", encoding: Encoding.UTF8),
                    SyntaxFactory.ParseSyntaxTree(source2, path: @"a\b\..\c\d.cs", encoding: Encoding.UTF8),
                    SyntaxFactory.ParseSyntaxTree(source3, path: @"*", encoding: Encoding.UTF8),
                    SyntaxFactory.ParseSyntaxTree(source4, path: @"C:\x.cs", encoding: Encoding.UTF8),
                    SyntaxFactory.ParseSyntaxTree(source5, path: @"C:\x.cs", encoding: Encoding.UTF8),
                },
                new[] { SystemRef },
                TestOptions.ReleaseExe.WithSourceReferenceResolver(new SourceFileResolver(ImmutableArray<string>.Empty, baseDirectory: @"C:\A\B")));
 
            // On CoreClr the '*' is a legal path character
            // https://github.com/dotnet/docs/issues/4483
            var expectedStarPath = ExecutionConditionUtil.IsCoreClr
                ? @"C:\A\B\*"
                : "*";
            CompileAndVerify(compilation, expectedOutput: $@"
1: 'C:\filename'
2: 'C:\A\B\a\c\d.cs'
3: '{expectedStarPath}'
4: 'C:\abc'
5: '     '
");
        }
 
        [Fact]
        public void TestAssemblyAttribute()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
using System.Reflection;
using System.Runtime.InteropServices;
 
[assembly: MyNamespace.MyCallerMemberName]
 
namespace MyNamespace
{
 
    class MyCallerMemberNameAttribute : Attribute
    {
        public MyCallerMemberNameAttribute(
            [CallerMemberName] string memberName = """")
        {
            Console.WriteLine(""member: "" + memberName);
        }
    }
 
    class B
    {
        [MyCallerMemberName]
        public static void MyMethod() { }
    }
 
    class A
    {
        public static void Main()
        {
            B b = new B();
            Type Type1;
            Type1 = b.GetType();
 
            typeof(B).GetMethod(""MyMethod"").GetCustomAttribute(typeof(MyCallerMemberNameAttribute));
 
            Assembly.GetAssembly(Type1).GetCustomAttribute(typeof(MyCallerMemberNameAttribute));
        }
    }
}";
 
            var expected = @"
member: MyMethod
member: 
";
 
            var compilation = CreateCompilationWithMscorlib461(source, new[] { SystemRef }, TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestCallerMemberNameConversion()
        {
            string source = @"
using System.Runtime.CompilerServices;
using System;
using System.Reflection;
 
namespace MyNamespace
{
 
    class MyCallerMemberNameAttribute : Attribute
    {
        public MyCallerMemberNameAttribute(
            [CallerMemberName] object memberName = null)
        {
            Console.WriteLine(""member: "" + memberName);
        }
    }
 
    class B
    {
        [MyCallerMemberName]
        public static void MyMethod() { }
    }
 
    class A
    {
        public static void Main()
        {
            typeof(B).GetMethod(""MyMethod"").GetCustomAttribute(typeof(MyCallerMemberNameAttribute));
        }
    }
}";
 
            var expected = @"
member: MyMethod
";
 
            var compilation = CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { SystemRef }, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestRecursiveAttribute()
        {
            string source = @"
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
 
public class Goo: Attribute
{
    public Goo([Goo] int y = 1) {}
}
 
class Test
{
    public static void Main() { }
}
";
            var compilation = CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { SystemRef }, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: "");
 
            var ctor = compilation.GetMember<MethodSymbol>("Goo..ctor");
            Assert.Equal(MethodKind.Constructor, ctor.MethodKind);
            var attr = ctor.Parameters.Single().GetAttributes().Single();
            Assert.Equal(ctor, attr.AttributeConstructor);
            Assert.Equal(1, attr.CommonConstructorArguments.Length);
            // We want to ensure that we don't accidentally use default(T) instead of the real default value for the parameter.
            Assert.Equal(1, attr.CommonConstructorArguments[0].Value);
        }
 
        [Fact]
        public void TestRecursiveAttribute2()
        {
            string source = @"
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
 
public class Goo: Attribute
{
    public Goo([Goo, Optional, DefaultParameterValue(1)] int y) {}
}
 
class Test
{
    public static void Main() { }
}
";
            var compilation = CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { SystemRef }, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: "");
 
            var ctor = compilation.GetMember<MethodSymbol>("Goo..ctor");
            Assert.Equal(MethodKind.Constructor, ctor.MethodKind);
            var attr = ctor.Parameters.Single().GetAttributes()[0];
            Assert.Equal(ctor, attr.AttributeConstructor);
            Assert.Equal(1, attr.CommonConstructorArguments.Length);
            // We want to ensure that we don't accidentally use default(T) instead of the real default value for the parameter.
            Assert.Equal(1, attr.CommonConstructorArguments[0].Value);
        }
 
        [Fact]
        public void TestRecursiveAttributeMetadata()
        {
            var iLSource = @"
.class public auto ansi beforefieldinit Goo
       extends [mscorlib]System.Attribute
{
  .method public hidebysig specialname rtspecialname 
          instance void  .ctor([opt] int32 y) cil managed
  {
    .param [1] = int32(0x00000000)
    .custom instance void Goo::.ctor(int32) = ( 01 00 00 00 00 00 00 00 ) 
    // Code size       10 (0xa)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Attribute::.ctor()
    IL_0006:  nop
    IL_0007:  nop
    IL_0008:  nop
    IL_0009:  ret
  } // end of method Goo::.ctor
 
} // end of class Goo
";
 
            var source = @"
using System.Runtime.CompilerServices;
using System;
 
class Driver {
 
    [Goo]
    public static void AttrTarget() { }
 
    public static void Main() { }
}
";
 
            var expected = @"";
 
            MetadataReference libReference = CompileIL(iLSource);
            var compilation = CreateCompilationWithMscorlib461(source, new[] { libReference }, TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestMemberNameLookup()
        {
            var source = @"
using System.Reflection;
using System.Runtime.CompilerServices;
using System;
 
class My : Attribute
{
    public My([CallerMemberName] string a = """")
    {
        Console.WriteLine(a);
    }
}
 
class Driver
{
    public static void Bar([My] int x)
    {
    }
 
    public static void Main()
    {
        typeof(Driver).GetMethod(""Bar"").GetParameters()[0].GetCustomAttribute(typeof(My));
    }
}
";
 
            var expected = @"Bar";
 
            var compilation = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact]
        public void TestDuplicateCallerInfoMetadata()
        {
            var iLSource = @"
.class public auto ansi beforefieldinit Goo
       extends [mscorlib]System.Object
{
  .method public hidebysig static int32  Log([opt] int32 callerName) cil managed
  {
    .param [1] = int32(0x00000000)
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CallerLineNumberAttribute::.ctor() = ( 01 00 00 00 ) 
	.custom instance void [mscorlib]System.Runtime.CompilerServices.CallerMemberNameAttribute::.ctor() = ( 01 00 00 00 ) 
    // Code size       29 (0x1d)
    .maxstack  2
    .locals init (int32 V_0)
    IL_0000:  nop
    IL_0001:  ldstr      ""name: ""
    IL_0006:  ldarg.0
    IL_0007:  box        [mscorlib]System.Int32
    IL_000c:  call       string [mscorlib]System.String::Concat(object,
                                                                object)
    IL_0011:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_0016:  nop
    IL_0017:  ldc.i4.1
    IL_0018:  stloc.0
    IL_0019:  br.s       IL_001b
 
    IL_001b:  ldloc.0
    IL_001c:  ret
  } // end of method Goo::Log
 
  .method public hidebysig static int32  Log2([opt] string callerName) cil managed
  {
    .param [1] = """"
	.custom instance void [mscorlib]System.Runtime.CompilerServices.CallerLineNumberAttribute::.ctor() = ( 01 00 00 00 ) 
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CallerMemberNameAttribute::.ctor() = ( 01 00 00 00 ) 
    // Code size       24 (0x18)
    .maxstack  2
    .locals init (int32 V_0)
    IL_0000:  nop
    IL_0001:  ldstr      ""name: ""
    IL_0006:  ldarg.0
    IL_0007:  call       string [mscorlib]System.String::Concat(string,
                                                                string)
    IL_000c:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_0011:  nop
    IL_0012:  ldc.i4.1
    IL_0013:  stloc.0
    IL_0014:  br.s       IL_0016
 
    IL_0016:  ldloc.0
    IL_0017:  ret
  } // end of method Goo::Log2
 
  .method public hidebysig static int32  Log3([opt] string callerName) cil managed
  {
    .param [1] = """"
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CallerMemberNameAttribute::.ctor() = ( 01 00 00 00 ) 
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CallerFilePathAttribute::.ctor() = ( 01 00 00 00 ) 
    // Code size       24 (0x18)
    .maxstack  2
    .locals init (int32 V_0)
    IL_0000:  nop
    IL_0001:  ldstr      ""name: ""
    IL_0006:  ldarg.0
    IL_0007:  call       string [mscorlib]System.String::Concat(string,
                                                                string)
    IL_000c:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_0011:  nop
    IL_0012:  ldc.i4.1
    IL_0013:  stloc.0
    IL_0014:  br.s       IL_0016
 
    IL_0016:  ldloc.0
    IL_0017:  ret
  } // end of method Goo::Log3
 
  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // Code size       7 (0x7)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  ret
  } // end of method Goo::.ctor
 
} // end of class Goo
";
 
            var source = @"
using System.Runtime.CompilerServices;
using System;
 
class Driver {
    public static void Main() {
        Goo.Log();
        Goo.Log2();
        Goo.Log3();
    }
}
";
 
            var expected = @"
name: 7
name: 
name: C:\file.cs
";
 
            MetadataReference libReference = CompileIL(iLSource);
 
            var compilation = CreateCompilationWithMscorlib461(
                new[] { Parse(source, @"C:\file.cs") },
                new[] { libReference },
                TestOptions.ReleaseExe);
 
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact, WorkItem(546977, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546977")]
        public void Bug_17433()
        {
            var source = @"using System.Reflection;
using System.Runtime.CompilerServices;
using System;
 
class My : Attribute
{
    public My([CallerLineNumber] int x = -1)
    {
        Console.WriteLine(x);
    }
}
 
[My]
class Driver
{
    public static void Main()
    {
        typeof(Driver).GetCustomAttribute(typeof(My));
    }
}
";
 
            var expected = @"13";
 
            var compilation = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact, WorkItem(531036, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531036")]
        public void Repro_17443()
        {
            var source = @"
using System;
using System.Runtime.CompilerServices;
 
public class CallerInfoAttributedAttribute : Attribute
{
    public string FilePath { get; private set; }
    public int LineNumber { get; private set; }
    public string MemberName { get; private set; }
    public CallerInfoAttributedAttribute(
        [CallerFilePath] string filePath = """",
        [CallerLineNumber] int lineNumber = 0,
        [CallerMemberName] string memberName = """")
    {
        FilePath = filePath;
        LineNumber = lineNumber;
        MemberName = memberName;
    }
}
class Program
{
    [CallerInfoAttributed]
    public int Property1 { get; set; }
    static void Main(string[] args)
    {
        System.Reflection.PropertyInfo pi = typeof(Program).GetProperty(""Property1"");
        if (pi != null)
        {
            var a = Attribute.GetCustomAttribute(pi, typeof(CallerInfoAttributedAttribute)) as
CallerInfoAttributedAttribute;
            if (a != null)
            {
                Console.WriteLine(""CallerInfoAttributed: ({0}, {1}, {2})"", a.FilePath ?? ""<null>"",
a.LineNumber, a.MemberName ?? ""<null>"");
            }
        }
    }
}
";
 
            var expected = @"
CallerInfoAttributed: (, 22, Property1)
";
 
            var compilation = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact, WorkItem(531036, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531036")]
        public void CallerMemberNameAttributedAttributeOnNonMethodMembers()
        {
            var source = @"
using System.Reflection;
using System.Runtime.CompilerServices;
using System;
using System.Collections.Generic;
 
class NameAttr : Attribute
{
    public NameAttr([CallerMemberName] string name = ""<none>"")
    {
        Console.WriteLine(name);
    }
}
 
[NameAttr]
class Driver
{
    [NameAttr]
    public int myField;
 
    [NameAttr]
    public int MyProperty { get; set; }
 
    [NameAttr]
    public event Action MyEvent
    {
        add { }
        remove { }
    }
 
    [NameAttr]
    public int this[int i]
    {
        get { return -1; }
        set { }
    }
 
    [NameAttr]
    public int MyMethod() {
        return -1;
    }
 
    public static void Main()
    {
        typeof(Driver).GetCustomAttribute(typeof(NameAttr));
        typeof(Driver).GetField(""myField"").GetCustomAttribute(typeof(NameAttr));
        typeof(Driver).GetProperty(""MyProperty"").GetCustomAttribute(typeof(NameAttr));
        typeof(Driver).GetEvent(""MyEvent"").GetCustomAttribute(typeof(NameAttr));
        typeof(Driver).GetProperty(""Item"").GetCustomAttribute(typeof(NameAttr));
        typeof(Driver).GetMethod(""MyMethod"").GetCustomAttribute(typeof(NameAttr));
    }
}
";
 
            var expected = @"
<none>
<none>
MyProperty
MyEvent
Item
MyMethod
";
 
            var compilation = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact, WorkItem(531040, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531040")]
        public void Repro_17449()
        {
            var source = @"
using System;
using System.Runtime.CompilerServices;
 
public class LineNumber2ObjectAttribute : Attribute
{
    public LineNumber2ObjectAttribute([CallerLineNumber] object lineNumber = null)
    {
        Console.WriteLine(lineNumber);
    }
}
 
[LineNumber2Object]
class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttributes(typeof(LineNumber2ObjectAttribute), false);
    }
}
";
 
            var expected = @"
13
";
 
            var compilation = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact, WorkItem(531040, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531040")]
        public void TestBadAttributeParameterTypeWithCallerLineNumber()
        {
            var source = @"
using System;
using System.Runtime.CompilerServices;
 
public class LineNumber2NullableIntAttribute : Attribute
{
    public LineNumber2NullableIntAttribute([CallerLineNumber] int? lineNumber = null)
    {
        Console.WriteLine(lineNumber);
    }
}
 
public class LineNumber2ValueTypeAttribute : Attribute
{
    public LineNumber2ValueTypeAttribute([CallerLineNumber] ValueType lineNumber = null)
    {
        Console.WriteLine(lineNumber);
    }
}
 
[LineNumber2NullableInt, LineNumber2ValueType]
class Program
{
    static void Main()
    {
        typeof(Program).GetCustomAttributes(typeof(LineNumber2NullableIntAttribute), false);
        typeof(Program).GetCustomAttributes(typeof(LineNumber2ValueTypeAttribute), false);
    }
}
";
 
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (21,2): error CS0181: Attribute constructor parameter 'lineNumber' has type 'int?', which is not a valid attribute parameter type
                // [LineNumber2NullableInt, LineNumber2ValueType]
                Diagnostic(ErrorCode.ERR_BadAttributeParamType, "LineNumber2NullableInt").WithArguments("lineNumber", "int?"),
                // (21,26): error CS0181: Attribute constructor parameter 'lineNumber' has type 'System.ValueType', which is not a valid attribute parameter type
                // [LineNumber2NullableInt, LineNumber2ValueType]
                Diagnostic(ErrorCode.ERR_BadAttributeParamType, "LineNumber2ValueType").WithArguments("lineNumber", "System.ValueType"));
        }
 
        [Fact, WorkItem(531043, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531043")]
        public void Repro_17457()
        {
            var source = @"
using System;
using System.Runtime.CompilerServices;
public class LineNumber2LongAttribute : Attribute
{
    public LineNumber2LongAttribute([CallerLineNumber] long lineNumber = 0)
    {
        Console.WriteLine(lineNumber);
    }
}
public class LineNumber2FloatAttribute : Attribute
{
    public LineNumber2FloatAttribute([CallerLineNumber] float lineNumber = 0)
    {
        Console.WriteLine(lineNumber);
    }
}
[LineNumber2Long]
[LineNumber2Float]
class Test
{
    public static void Main()
    {
        typeof(Test).GetCustomAttributes(false);
    }
}
";
 
            var expected = @"
18
19
";
 
            var compilation = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact, WorkItem(531043, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531043")]
        public void InvalidDecimalInCustomAttributeParameterWithCallerLineNumber()
        {
            var source = @"
using System;
using System.Runtime.CompilerServices;
 
public class LineNumber2DecimalAttribute : Attribute
{
    public LineNumber2DecimalAttribute([CallerLineNumber] decimal lineNumber = 42)
    {
        Console.WriteLine(lineNumber);
    }
}
 
[LineNumber2DecimalAttribute]
class Test
{
    public static void Main()
    {
        typeof(Test).GetCustomAttributes(false);
    }
}
";
 
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (13,2): error CS0181: Attribute constructor parameter 'lineNumber' has type 'decimal', which is not a valid attribute parameter type
                // [LineNumber2DecimalAttribute]
                Diagnostic(ErrorCode.ERR_BadAttributeParamType, "LineNumber2DecimalAttribute").WithArguments("lineNumber", "decimal"));
        }
 
        [Fact, WorkItem(531043, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531043")]
        public void AllLegalConversionForCallerLineNumber()
        {
            var source = @"
using System;
using System.Runtime.CompilerServices;
 
public class LineNumber2ObjectAttribute : Attribute
{
    public LineNumber2ObjectAttribute([CallerLineNumber] object lineNumber = null)
    {
        Console.WriteLine(lineNumber);
    }
}
 
public class LineNumber2UintAttribute : Attribute
{
    public LineNumber2UintAttribute([CallerLineNumber] uint lineNumber = 42)
    {
        Console.WriteLine(lineNumber);
    }
}
 
public class LineNumber2UlongAttribute : Attribute
{
    public LineNumber2UlongAttribute([CallerLineNumber] ulong lineNumber = 42)
    {
        Console.WriteLine(lineNumber);
    }
}
 
public class LineNumber2IntAttribute : Attribute
{
    public LineNumber2IntAttribute([CallerLineNumber] int lineNumber = 42)
    {
        Console.WriteLine(lineNumber);
    }
}
 
public class LineNumber2LongAttribute : Attribute
{
    public LineNumber2LongAttribute([CallerLineNumber] long lineNumber = 42)
    {
        Console.WriteLine(lineNumber);
    }
}
 
public class LineNumber2DoubleAttribute : Attribute
{
    public LineNumber2DoubleAttribute([CallerLineNumber] double lineNumber = 42)
    {
        Console.WriteLine(lineNumber);
    }
}
 
public class LineNumber2FloatAttribute : Attribute
{
    public LineNumber2FloatAttribute([CallerLineNumber] float lineNumber = 42)
    {
        Console.WriteLine(lineNumber);
    }
}
 
[LineNumber2UintAttribute, LineNumber2UlongAttribute, LineNumber2IntAttribute, LineNumber2LongAttribute, LineNumber2DoubleAttribute, LineNumber2FloatAttribute, LineNumber2ObjectAttribute]
class Test
{
    public static void Main()
    {
 
        typeof(Test).GetCustomAttributes(false);
    }
}";
 
            var expected = @"
61
61
61
61
61
61
61
";
 
            var compilation = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact, WorkItem(531046, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531046")]
        public void TestUserDefinedImplicitConversion()
        {
            var source = @"
using System;
using System.Runtime.CompilerServices;
 
class Test
{
    public string Prop { get; set; }
 
    public static implicit operator Test(int i)
    {
        return new Test() { Prop = i.ToString() };
    }
 
    public static implicit operator Test(string i)
    {
        return new Test() { Prop = i };
    }
 
    public bool M1(string expected, [CallerLineNumber] Test line = null)
    {
        Console.WriteLine(""expected: {0}; actual: {1}"", expected, line);
        return expected == line.Prop;
    }
 
    public bool M2(string expected, [CallerMemberName] Test line = null)
    {
        Console.WriteLine(""expected: {0}; actual: {1}"", expected, line);
        return expected == line.Prop;
    }
}
";
 
            CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
                // (19,38): error CS4017: CallerLineNumberAttribute cannot be applied because there are no standard conversions from type 'int' to type 'Test'
                //     public bool M1(string expected, [CallerLineNumber] Test line = null)
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithArguments("int", "Test"),
                // (25,38): error CS4019: CallerMemberNameAttribute cannot be applied because there are no standard conversions from type 'string' to type 'Test'
                //     public bool M2(string expected, [CallerMemberName] Test line = null)
                Diagnostic(ErrorCode.ERR_NoConversionForCallerMemberNameParam, "CallerMemberName").WithArguments("string", "Test"));
        }
 
        [Fact, WorkItem(546980, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546980")]
        public void TestBaseCtorInvocation()
        {
            var source = @"
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Linq;
 
public class B
{
    public B(
        [CallerMemberName] string memberName = ""<default>"",
        [CallerLineNumber] int lineNumber = -1,
        [CallerFilePath] string filePath = ""<default>"")
    {
        Console.WriteLine(""name : "" + memberName);
        Console.WriteLine(""line : "" + lineNumber);
        Console.WriteLine(""path : "" + filePath);
    }
 
    public B(bool b) : this
        (
        ) { }
}
 
public class D : B
{
    public D()  : base
        (
        ) { }
}
 
public class E : B
{
    public E()
    {
    }
}
 
public class I
{
    public int GetInt(
        [CallerMemberName] string memberName = ""<default>"",
        [CallerLineNumber] int lineNumber = -1,
        [CallerFilePath] string filePath = ""<default>"")
    {
        Console.WriteLine(""query name : "" + memberName);
        Console.WriteLine(""query line : "" + lineNumber);
        Console.WriteLine(""query path : "" + filePath);
        return lineNumber;
    }
}
 
class Program
{
    static void Main(string[] args)
    {
        new B(false);
        new D();
        new 
        B
        ();
        new E();
 
        var query =
            from x in new I[] { new I(), new I() }
            where x.GetInt
            (
            ) >= 0
            select x;
 
        foreach (var x in query) { }
    }
}
";
 
            var expected = @"
name : .ctor
line : 20
path : C:\filename
name : .ctor
line : 27
path : C:\filename
name : Main
line : 58
path : C:\filename
name : <default>
line : -1
path : <default>
query name : Main
query line : 66
query path : C:\filename
query name : Main
query line : 66
query path : C:\filename
";
 
            var compilation = CreateCompilationWithMscorlib461(
                new[] { SyntaxFactory.ParseSyntaxTree(source, path: @"C:\filename", encoding: Encoding.UTF8) },
                new[] { SystemCoreRef },
                TestOptions.ReleaseExe);
 
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact, WorkItem(531034, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531034")]
        public void WarnOnCallerInfoCollision()
        {
            var source = @"
using System;
using System.Runtime.CompilerServices;
 
class Test
{
    static void M1([CallerMemberName,CallerFilePath] string s = null) { Console.WriteLine(s); }
    static void M2([CallerFilePath,CallerMemberName] string s = null) { Console.WriteLine(s); }
    static void M3([CallerLineNumber,CallerFilePath,CallerMemberName] object o = null) { Console.WriteLine(o); }
    static void M4([CallerLineNumber,CallerMemberName,CallerFilePath] object o = null) { Console.WriteLine(o); }
    static void M5([CallerFilePath,CallerLineNumber,CallerMemberName] object o = null) { Console.WriteLine(o); }
    static void M6([CallerMemberName,CallerLineNumber,CallerFilePath] object o = null) { Console.WriteLine(o); }
    static void M7([CallerFilePath,CallerMemberName,CallerLineNumber] object o = null) { Console.WriteLine(o); }
    static void M8([CallerMemberName,CallerFilePath,CallerLineNumber] object o = null) { Console.WriteLine(o); }
 
    static void Main(string[] args)
    {
        M1();
        M2();
        M3();
        M4();
        M5();
        M6();
        M7();
        M8();
    }
}
";
 
            var expected = @"
C:\filename
C:\filename
20
21
22
23
24
25
";
 
            var compilation = CreateCompilationWithMscorlib461(
                new[] { SyntaxFactory.ParseSyntaxTree(source, options: TestOptions.Regular7, path: @"C:\filename", encoding: Encoding.UTF8) },
                options: TestOptions.ReleaseExe);
 
            compilation.VerifyDiagnostics(
                // C:\filename(7,21): warning CS7072: The CallerMemberNameAttribute applied to parameter 's' will have no effect. It is overridden by the CallerFilePathAttribute.
                //     static void M1([CallerMemberName,CallerFilePath] string s = null) { Console.WriteLine(s); }
                Diagnostic(ErrorCode.WRN_CallerFilePathPreferredOverCallerMemberName, "CallerMemberName").WithArguments("s"),
                // C:\filename(8,36): warning CS7072: The CallerMemberNameAttribute applied to parameter 's' will have no effect. It is overridden by the CallerFilePathAttribute.
                //     static void M2([CallerFilePath,CallerMemberName] string s = null) { Console.WriteLine(s); }
                Diagnostic(ErrorCode.WRN_CallerFilePathPreferredOverCallerMemberName, "CallerMemberName").WithArguments("s"),
                // C:\filename(9,38): warning CS7074: The CallerFilePathAttribute applied to parameter 'o' will have no effect. It is overridden by the CallerLineNumberAttribute.
                //     static void M3([CallerLineNumber,CallerFilePath,CallerMemberName] object o = null) { Console.WriteLine(o); }
                Diagnostic(ErrorCode.WRN_CallerLineNumberPreferredOverCallerFilePath, "CallerFilePath").WithArguments("o"),
                // C:\filename(9,53): warning CS7073: The CallerMemberNameAttribute applied to parameter 'o' will have no effect. It is overridden by the CallerLineNumberAttribute.
                //     static void M3([CallerLineNumber,CallerFilePath,CallerMemberName] object o = null) { Console.WriteLine(o); }
                Diagnostic(ErrorCode.WRN_CallerLineNumberPreferredOverCallerMemberName, "CallerMemberName").WithArguments("o"),
                // C:\filename(10,38): warning CS7073: The CallerMemberNameAttribute applied to parameter 'o' will have no effect. It is overridden by the CallerLineNumberAttribute.
                //     static void M4([CallerLineNumber,CallerMemberName,CallerFilePath] object o = null) { Console.WriteLine(o); }
                Diagnostic(ErrorCode.WRN_CallerLineNumberPreferredOverCallerMemberName, "CallerMemberName").WithArguments("o"),
                // C:\filename(10,55): warning CS7074: The CallerFilePathAttribute applied to parameter 'o' will have no effect. It is overridden by the CallerLineNumberAttribute.
                //     static void M4([CallerLineNumber,CallerMemberName,CallerFilePath] object o = null) { Console.WriteLine(o); }
                Diagnostic(ErrorCode.WRN_CallerLineNumberPreferredOverCallerFilePath, "CallerFilePath").WithArguments("o"),
                // C:\filename(11,21): warning CS7074: The CallerFilePathAttribute applied to parameter 'o' will have no effect. It is overridden by the CallerLineNumberAttribute.
                //     static void M5([CallerFilePath,CallerLineNumber,CallerMemberName] object o = null) { Console.WriteLine(o); }
                Diagnostic(ErrorCode.WRN_CallerLineNumberPreferredOverCallerFilePath, "CallerFilePath").WithArguments("o"),
                // C:\filename(11,53): warning CS7073: The CallerMemberNameAttribute applied to parameter 'o' will have no effect. It is overridden by the CallerLineNumberAttribute.
                //     static void M5([CallerFilePath,CallerLineNumber,CallerMemberName] object o = null) { Console.WriteLine(o); }
                Diagnostic(ErrorCode.WRN_CallerLineNumberPreferredOverCallerMemberName, "CallerMemberName").WithArguments("o"),
                // C:\filename(12,21): warning CS7073: The CallerMemberNameAttribute applied to parameter 'o' will have no effect. It is overridden by the CallerLineNumberAttribute.
                //     static void M6([CallerMemberName,CallerLineNumber,CallerFilePath] object o = null) { Console.WriteLine(o); }
                Diagnostic(ErrorCode.WRN_CallerLineNumberPreferredOverCallerMemberName, "CallerMemberName").WithArguments("o"),
                // C:\filename(12,55): warning CS7074: The CallerFilePathAttribute applied to parameter 'o' will have no effect. It is overridden by the CallerLineNumberAttribute.
                //     static void M6([CallerMemberName,CallerLineNumber,CallerFilePath] object o = null) { Console.WriteLine(o); }
                Diagnostic(ErrorCode.WRN_CallerLineNumberPreferredOverCallerFilePath, "CallerFilePath").WithArguments("o"),
                // C:\filename(13,21): warning CS7074: The CallerFilePathAttribute applied to parameter 'o' will have no effect. It is overridden by the CallerLineNumberAttribute.
                //     static void M7([CallerFilePath,CallerMemberName,CallerLineNumber] object o = null) { Console.WriteLine(o); }
                Diagnostic(ErrorCode.WRN_CallerLineNumberPreferredOverCallerFilePath, "CallerFilePath").WithArguments("o"),
                // C:\filename(13,36): warning CS7073: The CallerMemberNameAttribute applied to parameter 'o' will have no effect. It is overridden by the CallerLineNumberAttribute.
                //     static void M7([CallerFilePath,CallerMemberName,CallerLineNumber] object o = null) { Console.WriteLine(o); }
                Diagnostic(ErrorCode.WRN_CallerLineNumberPreferredOverCallerMemberName, "CallerMemberName").WithArguments("o"),
                // C:\filename(14,21): warning CS7073: The CallerMemberNameAttribute applied to parameter 'o' will have no effect. It is overridden by the CallerLineNumberAttribute.
                //     static void M8([CallerMemberName,CallerFilePath,CallerLineNumber] object o = null) { Console.WriteLine(o); }
                Diagnostic(ErrorCode.WRN_CallerLineNumberPreferredOverCallerMemberName, "CallerMemberName").WithArguments("o"),
                // C:\filename(14,38): warning CS7074: The CallerFilePathAttribute applied to parameter 'o' will have no effect. It is overridden by the CallerLineNumberAttribute.
                //     static void M8([CallerMemberName,CallerFilePath,CallerLineNumber] object o = null) { Console.WriteLine(o); }
                Diagnostic(ErrorCode.WRN_CallerLineNumberPreferredOverCallerFilePath, "CallerFilePath").WithArguments("o"));
 
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [Fact, WorkItem(531034, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531034")]
        public void WarnOnCallerInfoCollisionWithBadType()
        {
            var source = @"
using System;
using System.Runtime.CompilerServices;
 
class Test
{
    static void M1([CallerLineNumber,CallerFilePath,CallerMemberName] int i = 0) { Console.WriteLine(); }
    static void M2([CallerLineNumber,CallerFilePath,CallerMemberName] string s = null) { Console.WriteLine(s); }
 
    static void Main(string[] args)
    {
        M1();
        M2();
    }
}
";
 
            var compilation = CreateCompilationWithMscorlib461(new SyntaxTree[] { SyntaxFactory.ParseSyntaxTree(source, options: TestOptions.Regular7, path: @"C:\filename") }).VerifyDiagnostics(
                // C:\filename(7,38): error CS4018: CallerFilePathAttribute cannot be applied because there are no standard conversions from type 'string' to type 'int'
                //     static void M1([CallerLineNumber,CallerFilePath,CallerMemberName] int i = 0) { Console.WriteLine(); }
                Diagnostic(ErrorCode.ERR_NoConversionForCallerFilePathParam, "CallerFilePath").WithArguments("string", "int").WithLocation(7, 38),
                // C:\filename(7,53): error CS4019: CallerMemberNameAttribute cannot be applied because there are no standard conversions from type 'string' to type 'int'
                //     static void M1([CallerLineNumber,CallerFilePath,CallerMemberName] int i = 0) { Console.WriteLine(); }
                Diagnostic(ErrorCode.ERR_NoConversionForCallerMemberNameParam, "CallerMemberName").WithArguments("string", "int").WithLocation(7, 53),
                // C:\filename(8,21): error CS4017: CallerLineNumberAttribute cannot be applied because there are no standard conversions from type 'int' to type 'string'
                //     static void M2([CallerLineNumber,CallerFilePath,CallerMemberName] string s = null) { Console.WriteLine(s); }
                Diagnostic(ErrorCode.ERR_NoConversionForCallerLineNumberParam, "CallerLineNumber").WithArguments("int", "string").WithLocation(8, 21),
                // C:\filename(8,38): warning CS7082: The CallerFilePathAttribute applied to parameter 's' will have no effect. It is overridden by the CallerLineNumberAttribute.
                //     static void M2([CallerLineNumber,CallerFilePath,CallerMemberName] string s = null) { Console.WriteLine(s); }
                Diagnostic(ErrorCode.WRN_CallerLineNumberPreferredOverCallerFilePath, "CallerFilePath").WithArguments("s").WithLocation(8, 38),
                // C:\filename(8,53): warning CS7081: The CallerMemberNameAttribute applied to parameter 's' will have no effect. It is overridden by the CallerLineNumberAttribute.
                //     static void M2([CallerLineNumber,CallerFilePath,CallerMemberName] string s = null) { Console.WriteLine(s); }
                Diagnostic(ErrorCode.WRN_CallerLineNumberPreferredOverCallerMemberName, "CallerMemberName").WithArguments("s").WithLocation(8, 53),
                // C:\filename(13,9): error CS0029: Cannot implicitly convert type 'int' to 'string'
                //         M2();
                Diagnostic(ErrorCode.ERR_NoImplicitConv, "M2()").WithArguments("int", "string").WithLocation(13, 9));
        }
 
        [WorkItem(604367, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/604367")]
        [Fact]
        public void TestCallerInfoInQuery()
        {
            string source =
@"using System;
using System.Runtime.CompilerServices;
 
class Test
{
    static int result = 0;
    static void Main()
    {
        var q = from x in new Test()
                where x != null
                select x.ToString();
        Console.WriteLine(result == 0 ? ""PASS"" : ""FAIL"");
    }
    public Test Select(
        Func<object, object> selector,
        [CallerFilePath]string file = null,
        [CallerLineNumber]int line = -1,
        [CallerMemberName]string member = null
    )
    {
        if (file != FILEPATH)
        {
            result++;
            Console.WriteLine(""File: Exp={0} Act={1} "", FILEPATH, file);
        }
        if (line != 11)
        {
            result++;
            Console.WriteLine(""Line: Exp=11 Act={0} "", line);
        }
        if (member != ""Main"")
        {
            result++;
            Console.WriteLine(""Member: Exp='Main' Act={0}"", member);
        }
        return new Test();
    }
    public Test Where(
        Func<object, bool> predicate,
        [CallerFilePath]string file = null,
        [CallerLineNumber]int line = -1,
        [CallerMemberName]string member = null
    )
    {
        if (file != FILEPATH)
        {
            result++;
            Console.WriteLine(""File: Exp={0} Act={1} "", FILEPATH, file);
        }
        if (line != 10)
        {
            result++;
            Console.WriteLine(""Line: Exp=10 Act={0} "", line);
        }
        if (member != ""Main"")
        {
            result++;
            Console.WriteLine(""Member: Exp='Main' Act={0}"", member);
        }
        return new Test();
    }
    public static readonly string FILEPATH = GetFilePath();
    public static string GetFilePath([CallerFilePath]string filePath = null) { return filePath; }
}";
 
            string expected = @"PASS";
            var compilation = CreateCompilationWithMscorlib461(source, new MetadataReference[] { SystemRef }, TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [WorkItem(949118, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/949118")]
        [WorkItem(152, "CodePlex")]
        [Fact]
        public void Bug949118_1()
        {
            string source =
@"using System;
using System.Runtime.CompilerServices;
using System.Globalization;
class Program
{
  static void Main()
  {
   var x = Goo.F1;
   var y = new Goo().F2;
  }
}
public class Goo
{
  static object Test([CallerMemberName] string bar = null)
  {
    Console.WriteLine(bar);
    return null;
  }
  
  public static readonly object F1 = Test();
  public readonly object F2 = Test();
}
";
 
            string expected = @"F1
F2";
            var compilation = CreateCompilationWithMscorlib461(source, new MetadataReference[] { SystemRef }, TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [WorkItem(949118, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/949118")]
        [WorkItem(152, "CodePlex")]
        [Fact]
        public void Bug949118_2()
        {
            string source =
@"using System;
using System.Runtime.CompilerServices;
using System.Globalization;
class Program
{
  static void Main()
  {
   var x = Goo.F1;
   var y = new Goo().F2;
  }
}
public class Goo
{
  static object Test([CallerMemberName] string bar = null)
  {
    Console.WriteLine(bar);
    return null;
  }
  
  public static object F1 {get;} = Test();
  public object F2 {get;} = Test();
}
";
 
            string expected = @"F1
F2";
            var compilation = CreateCompilationWithMscorlib461(source, new MetadataReference[] { SystemRef }, TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [WorkItem(949118, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/949118")]
        [WorkItem(152, "CodePlex")]
        [Fact]
        public void Bug949118_3()
        {
            string source =
@"using System;
using System.Runtime.CompilerServices;
using System.Globalization;
class Program
{
  static void Main()
  {
   var y = ((I1)new Goo()).F2;
  }
}
 
interface I1
{
  object F2 {get;}
}
 
public class Goo : I1
{
  static object Test([CallerMemberName] string bar = null)
  {
    Console.WriteLine(bar);
    return null;
  }
  
  object I1.F2 {get;} = Test();
}
";
 
            string expected = @"F2";
            var compilation = CreateCompilationWithMscorlib461(source, new MetadataReference[] { SystemRef }, TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        /// <summary>
        /// DELIBERATE SPEC VIOLATION: The C# spec currently requires to provide caller information only in explicit invocations and query expressions.
        /// We also provide caller information to an invocation of an <c>Add</c> method generated for an element-initializer in a collection-initializer
        /// to match the native compiler behavior and user requests. 
        /// </summary>
        [WorkItem(991476, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/991476")]
        [WorkItem(171, "CodePlex")]
        [Fact]
        public void Bug991476_1()
        {
            const string source =
@"using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
 
public class MyCollectionWithInitializer : IEnumerable<DBNull>
{
    public string LastCallerFilePath { get; set; }
 
    public void Add<T>(T something, [CallerFilePath] string callerFilePath = """") where T : struct
    {
        LastCallerFilePath = callerFilePath;
        Console.WriteLine(""Caller file path: "" + (!string.IsNullOrEmpty(callerFilePath) ? callerFilePath : ""(nothing)""));
    }
 
    public IEnumerator<DBNull> GetEnumerator()
    {
        throw new NotSupportedException();
    }
 
    IEnumerator IEnumerable.GetEnumerator()
    {
        throw new NotSupportedException();
    }
}
 
class Program
{
    public static void Main()
    {
        var coll1 = new MyCollectionWithInitializer();
        coll1.Add(123);
        Console.WriteLine(coll1.LastCallerFilePath);
 
        var coll2 = new MyCollectionWithInitializer { 345 };
        Console.WriteLine(coll2.LastCallerFilePath);
    }
}";
 
            const string expected = @"Caller file path: C:\filename
C:\filename
Caller file path: C:\filename
C:\filename";
 
            var compilation = CreateCompilationWithMscorlib461(
                new[] { SyntaxFactory.ParseSyntaxTree(source, path: @"C:\filename", encoding: Encoding.UTF8) },
                new[] { SystemCoreRef },
                TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [WorkItem(991476, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/991476")]
        [WorkItem(171, "CodePlex")]
        [Fact]
        public void Bug991476_2()
        {
            const string source =
@"using System;
using System.Collections;
using System.Runtime.CompilerServices;
 
class C : Stack
{
    static void Main()
    {
        new C
        {
            1, // line 11
            2  // line 12
        };
 
        new C
        {
            {  // line 17
                1,
                true
            },
            {  // line 21
                ""Hi""
            }
        };
 
 
    }
 
    public void Add(int x, [CallerLineNumber] int n = -1) { Console.WriteLine(n); }
    public void Add(int x, bool y, [CallerLineNumber] int n = -1) { Console.WriteLine(n); }
}
 
static class E
{
    public static void Add(this C c, string s, [CallerMemberName] string m = ""Default"", [CallerLineNumber] int n = -1)
    {
        Console.WriteLine(m);
        Console.WriteLine(n);
    }
}";
 
            const string expected = @"11
12
17
Main
21";
 
            var compilation = CreateCompilationWithMscorlib461(
                new[] { SyntaxFactory.ParseSyntaxTree(source, path: @"C:\filename", encoding: Encoding.UTF8) },
                new[] { SystemCoreRef },
                TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [WorkItem(1006447, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1006447")]
        [Fact]
        public void Bug1006447_1()
        {
            const string vbSource =
@"Imports System
Imports System.Runtime.CompilerServices
Imports System.Runtime.InteropServices
Imports System.Text
 
<ComImport>
<Guid(""1F9C3731-6AA1-498A-AFA0-359828FCF0CE"")>
Public Interface I
    Property X(Optional i as Integer = 0, <CallerFilePath> Optional s As String = Nothing) As StringBuilder
End Interface
 
Public Class A
    Implements I
 
    Public Property X(Optional i as Integer = 0, Optional s As String = Nothing) As StringBuilder Implements I.X
        Get
            Console.WriteLine(""Get X(""""{0}"""")"", s)
            Return New StringBuilder
        End Get
        Set(value As StringBuilder)
            Console.WriteLine(""Set X(""""{0}"""")"", s)
        End Set
    End Property
End Class";
 
            var vbReference = BasicCompilationUtils.CompileToMetadata(vbSource, references: new[] { MscorlibRef_v4_0_30316_17626, SystemCoreRef });
 
            const string csSource =
@"using System;
 
class C
{
    I P = new A();
 
    static void Main()
    {
        new C().P.X = null;
        new C().P.X[1] = null;
        new C { P = { X = null } };
        new C { P = { X = { Length = 0 } } };
    }
}
";
            var compilation = CreateCompilationWithMscorlib461(
                new[] { SyntaxFactory.ParseSyntaxTree(csSource, path: @"C:\filename", encoding: Encoding.UTF8) },
                new[] { SystemCoreRef, vbReference },
                TestOptions.ReleaseExe);
 
            CompileAndVerify(compilation, expectedOutput:
@"Set X(""C:\filename"")
Set X(""C:\filename"")
Set X(""C:\filename"")
Get X(""C:\filename"")
");
        }
 
        [WorkItem(1006447, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1006447")]
        [Fact]
        public void Bug1006447_2()
        {
            const string source =
@"using System;
using System.Runtime.CompilerServices;
 
class C
{
    static void Main()
    {
        new C()[0] = 0;
    }
 
    int this[int x, [CallerMemberName] string s = null]
    {
        set
        {
            Console.WriteLine(s);
        }
    }
}";
 
            const string expected = "Main";
 
            var compilation = CreateCompilationWithMscorlib461(
                source,
                new[] { SystemCoreRef },
                TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: expected);
        }
 
        [WorkItem(1006447, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1006447")]
        [Fact]
        public void Bug1006447_3()
        {
            const string vbSource =
@"Imports System
Imports System.Runtime.CompilerServices
Imports System.Runtime.InteropServices
 
<ComImport>
<Guid(""1F9C3731-6AA1-498A-AFA0-359828FCF0CE"")>
Public Interface I
    ReadOnly Property [Select](<CallerMemberName> Optional s As String = Nothing) As Func(Of Func(Of Integer, Integer), String)
End Interface
 
Public Class A
    Implements I
 
    Public ReadOnly Property [Select](<CallerMemberName> Optional s As String = Nothing) As Func(Of Func(Of Integer, Integer), String) Implements I.Select
         Get
            Console.WriteLine(""Get Select(""""{0}"""")"", s)
            Return Function() ""ABC""
        End Get
    End Property
End Class";
 
            var vbReference = BasicCompilationUtils.CompileToMetadata(vbSource, references: new[] { MscorlibRef_v4_0_30316_17626, SystemCoreRef });
 
            const string csSource =
@"using System;
 
class Program
{
    static void Main()
    {
        I x = new A();
        Console.WriteLine(from y in x select y);
    }
}";
            var compilation = CreateCompilationWithMscorlib461(
                csSource,
                new[] { SystemCoreRef, vbReference },
                TestOptions.ReleaseExe);
 
            CompileAndVerify(compilation, expectedOutput:
@"Get Select(""Main"")
ABC
");
        }
 
        [Theory]
        [InlineData("out")]
        [InlineData("ref")]
        [InlineData("in")]
        public void CallerArgumentExpression_OnRefParameter01(string refType)
        {
            var comp = CreateCompilation(@$"
using System.Runtime.CompilerServices;
#pragma warning disable CS8321
 
void M(int i, [CallerArgumentExpression(""i"")] {refType} string s)
{{
    {(refType == "out" ? "s = null;" : "")}
}}
", targetFramework: TargetFramework.NetCoreApp);
 
            comp.VerifyDiagnostics(
                // (5,16): error CS8964: The CallerArgumentExpressionAttribute may only be applied to parameters with default values
                // void M(int i, [CallerArgumentExpression("i")] ref string s)
                Diagnostic(ErrorCode.ERR_BadCallerArgumentExpressionParamWithoutDefaultValue, "CallerArgumentExpression").WithLocation(5, 16)
            );
        }
 
        [Theory]
        [InlineData("out")]
        [InlineData("ref")]
        public void CallerArgumentExpression_OnRefParameter02(string refType)
        {
            var comp = CreateCompilation(@$"
using System.Runtime.CompilerServices;
#pragma warning disable CS8321
 
void M(int i, [CallerArgumentExpression(""i"")] {refType} string s = null)
{{
    {(refType == "out" ? "s = null;" : "")}
}}
", targetFramework: TargetFramework.NetCoreApp);
 
            comp.VerifyDiagnostics(
                // (5,16): error CS8964: The CallerArgumentExpressionAttribute may only be applied to parameters with default values
                // void M(int i, [CallerArgumentExpression("i")] out string s = null)
                Diagnostic(ErrorCode.ERR_BadCallerArgumentExpressionParamWithoutDefaultValue, "CallerArgumentExpression").WithLocation(5, 16),
                // (5,47): error CS1741: A ref or out parameter cannot have a default value
                // void M(int i, [CallerArgumentExpression("i")] out string s = null)
                Diagnostic(ErrorCode.ERR_RefOutDefaultValue, refType).WithLocation(5, 47)
            );
        }
 
        [ConditionalFact(typeof(CoreClrOnly))]
        public void CallerArgumentExpression_OnRefParameter03()
        {
            var comp = CreateCompilation(@"
using System;
using System.Runtime.CompilerServices;
 
M(1 + 1);
 
void M(int i, [CallerArgumentExpression(""i"")] in string s = ""default value"")
{
    Console.WriteLine(s);
}
", targetFramework: TargetFramework.NetCoreApp);
 
            CompileAndVerify(comp, expectedOutput: "1 + 1").VerifyDiagnostics();
        }
 
        [Fact]
        public void CallerArgumentExpression_Cycle()
        {
            string source =
@"namespace System.Runtime.CompilerServices
{
    public sealed class CallerArgumentExpressionAttribute : Attribute
    {
        public CallerArgumentExpressionAttribute([CallerArgumentExpression(nameof(parameterName))] string parameterName)
        {
            ParameterName = parameterName;
        }
        public string ParameterName { get; }
    }
}";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (5,51): error CS8964: The CallerArgumentExpressionAttribute may only be applied to parameters with default values
                //         public CallerArgumentExpressionAttribute([CallerArgumentExpression(nameof(parameterName))] string parameterName)
                Diagnostic(ErrorCode.ERR_BadCallerArgumentExpressionParamWithoutDefaultValue, "CallerArgumentExpression").WithLocation(5, 51));
        }
 
        [Fact]
        public void CallerMemberName_SetterValueParam()
        {
            // There is no way in C# to call a setter without passing an argument for the value, so the CallerMemberName effectively does nothing.
            var source = """
                using System;
                using System.Runtime.CompilerServices;
                using System.Runtime.InteropServices;
 
                public partial class C
                {
                    public static void Main()
                    {
                        var c = new C();
                        c[1] = "1";
                    }
 
                    public string this[int x]
                    {
                        [param: Optional, DefaultParameterValue("0")]
                        [param: CallerMemberName]
                        set
                        {
                            Console.Write(value);
                        }
                    }
                }
                """;
 
            var verifier = CompileAndVerify(source, expectedOutput: "1");
            verifier.VerifyDiagnostics();
 
            var source1 = """
                class D
                {
                    void M()
                    {
                        var c = new C();
                        c.set_Item(1);
                    }
                }
                """;
            var comp1 = CreateCompilation(source1, references: [verifier.Compilation.EmitToImageReference()]);
            comp1.VerifyEmitDiagnostics(
                // (6,11): error CS0571: 'C.this[int].set': cannot explicitly call operator or accessor
                //         c.set_Item(1);
                Diagnostic(ErrorCode.ERR_CantCallSpecialMethod, "set_Item").WithArguments("C.this[int].set").WithLocation(6, 11));
        }
 
        [Fact]
        public void CallerArgumentExpression_SetterValueParam()
        {
            var source = """
                using System;
                using System.Runtime.CompilerServices;
 
                namespace System.Runtime.CompilerServices
                {
                    [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = true, Inherited = false)]
                    public sealed class CallerArgumentExpressionAttribute : Attribute
                    {
                        public CallerArgumentExpressionAttribute(string parameterName)
                        {
                            ParameterName = parameterName;
                        }
                        public string ParameterName { get; }
                    }
                }
 
                partial class C
                {
                    public static void Main()
                    {
                        var c = new C();
                        c[1] = GetNumber();
                    }
 
                    public static int GetNumber() => 1;
 
                    public int this[int x, [CallerArgumentExpression("value")] string argumentExpression = "0"]
                    {
                        set
                        {
                            Console.Write(argumentExpression);
                        }
                    }
                }
                """;
            var verifier = CompileAndVerify(source, expectedOutput: "0", symbolValidator: verify);
            verifier.VerifyDiagnostics(
                // (27,29): warning CS8963: The CallerArgumentExpressionAttribute applied to parameter 'argumentExpression' will have no effect. It is applied with an invalid parameter name.
                //     public int this[int x, [CallerArgumentExpression("value")] string argumentExpression = "0"]
                Diagnostic(ErrorCode.WRN_CallerArgumentExpressionAttributeHasInvalidParameterName, "CallerArgumentExpression").WithArguments("argumentExpression").WithLocation(27, 29));
 
            void verify(ModuleSymbol module)
            {
                var indexer = (PropertySymbol)module.GlobalNamespace.GetMember<NamedTypeSymbol>("C").Indexers.Single();
                AssertEx.Equal(["""System.Runtime.CompilerServices.CallerArgumentExpressionAttribute("value")"""], indexer.Parameters[1].GetAttributes().SelectAsArray(attr => attr.ToString()));
            }
        }
    }
}