diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs
index 56b8ec335ae06..b06635bcc4edd 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs
@@ -155,7 +155,7 @@ private Binder SkipSemanticModelBinder()
private static BoundAttribute BindAttributeCore(Binder binder, AttributeSyntax node, NamedTypeSymbol attributeType, Symbol? attributedMember, BindingDiagnosticBag diagnostics)
{
Debug.Assert(binder.SkipSemanticModelBinder() == binder.GetRequiredBinder(node).SkipSemanticModelBinder());
- binder = binder.WithAdditionalFlags(BinderFlags.AttributeArgument);
+ Debug.Assert(binder.InAttributeArgument);
// If attribute name bound to an error type with a single named type
// candidate symbol, we want to bind the attribute constructor
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
index 538a8090f72ab..ab79a8b8e3c72 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
@@ -2717,7 +2717,7 @@ private bool MemberGroupFinalValidationAccessibilityChecks(BoundExpression? rece
diagnostics.Add(ErrorCode.ERR_ObjectRequired, node.Location, memberSymbol);
return true;
}
- else if (WasImplicitReceiver(receiverOpt))
+ else if (WasImplicitReceiver(receiverOpt) && !(IsInsideNameof && Compilation.IsFeatureEnabled(MessageID.IDS_FeatureInstanceMemberInNameof)))
{
if (InFieldInitializer && !ContainingType!.IsScriptClass || InConstructorInitializer || InAttributeArgument)
{
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
index 7634bda3b55aa..abf24c2296825 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
@@ -35,6 +35,12 @@ internal partial class Binder
/// True if a reference to "this" is available.
internal bool HasThis(bool isExplicit, out bool inStaticContext)
{
+ if (!isExplicit && IsInsideNameof && Compilation.IsFeatureEnabled(MessageID.IDS_FeatureInstanceMemberInNameof))
+ {
+ inStaticContext = false;
+ return true;
+ }
+
var memberOpt = this.ContainingMemberOrLambda?.ContainingNonLambdaMember();
if (memberOpt?.IsStatic == true)
{
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
index b1165208e4ac6..71c7c0f79fb50 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
@@ -2351,6 +2351,7 @@ private bool TryBindNameofOperator(InvocationExpressionSyntax node, BindingDiagn
if (node.MayBeNameofOperator())
{
var binder = this.GetBinder(node);
+ Debug.Assert(binder.Flags == this.Flags);
if (binder.EnclosingNameofArgument == node.ArgumentList.Arguments[0].Expression)
{
result = binder.BindNameofOperatorInternal(node, diagnostics);
diff --git a/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs b/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs
index ecc379f4611ba..214620d607059 100644
--- a/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs
+++ b/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs
@@ -478,7 +478,7 @@ public override void VisitEqualsValueClause(EqualsValueClauseSyntax node)
public override void VisitAttribute(AttributeSyntax node)
{
- var attrBinder = new ExpressionVariableBinder(node, _enclosing);
+ var attrBinder = new ExpressionVariableBinder(node, _enclosing.WithAdditionalFlags(BinderFlags.AttributeArgument));
AddToMap(node, attrBinder);
if (node.ArgumentList?.Arguments.Count > 0)
diff --git a/src/Compilers/CSharp/Portable/Compilation/PublicSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/PublicSemanticModel.cs
index a20b8224e5fd1..4886d23b4700f 100644
--- a/src/Compilers/CSharp/Portable/Compilation/PublicSemanticModel.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/PublicSemanticModel.cs
@@ -28,7 +28,7 @@ protected AttributeSemanticModel CreateModelForAttribute(Binder enclosingBinder,
attributeType,
aliasOpt,
attributeTarget,
- enclosingBinder.WithAdditionalFlags(BinderFlags.AttributeArgument),
+ enclosingBinder,
containingModel?.GetRemappedSymbols());
Symbol? getAttributeTarget(SyntaxNode? targetSyntax)
diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests.cs
index bbf72a68dc844..25d23480f1c35 100644
--- a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests.cs
+++ b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests.cs
@@ -47359,5 +47359,112 @@ class D
CompileAndVerify(CreateCompilationWithSpan([source, CollectionBuilderAttributeDefinition]), expectedOutput: "").VerifyDiagnostics();
}
+
+ [Fact]
+ [WorkItem("https://github.com/dotnet/roslyn/issues/81576")]
+ public void Issue81576_01()
+ {
+ var source = """
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Runtime.CompilerServices;
+
+ [CollectionBuilder(typeof(MyFancyCollection), nameof(MyFancyCollection.))]
+ public class MyFancyCollection : IEnumerable
+ {
+ public MyFancyCollection Create(ReadOnlySpan ints)
+ {
+ return null;
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ throw new NotImplementedException();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+ """;
+
+ CreateCompilationWithSpan([source, CollectionBuilderAttributeDefinition]).VerifyEmitDiagnostics(
+ // (6,72): error CS1001: Identifier expected
+ // [CollectionBuilder(typeof(MyFancyCollection), nameof(MyFancyCollection.))]
+ Diagnostic(ErrorCode.ERR_IdentifierExpected, ")").WithLocation(6, 72)
+ );
+ }
+
+ [Fact]
+ [WorkItem("https://github.com/dotnet/roslyn/issues/81576")]
+ public void Issue81576_02()
+ {
+ var source = """
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Runtime.CompilerServices;
+
+ [CollectionBuilder(typeof(MyFancyCollection), nameof(MyFancyCollection.Missing))]
+ public class MyFancyCollection : IEnumerable
+ {
+ public MyFancyCollection Create(ReadOnlySpan ints)
+ {
+ return null;
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ throw new NotImplementedException();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+ """;
+
+ CreateCompilationWithSpan([source, CollectionBuilderAttributeDefinition]).VerifyEmitDiagnostics(
+ // (6,72): error CS0117: 'MyFancyCollection' does not contain a definition for 'Missing'
+ // [CollectionBuilder(typeof(MyFancyCollection), nameof(MyFancyCollection.Missing))]
+ Diagnostic(ErrorCode.ERR_NoSuchMember, "Missing").WithArguments("MyFancyCollection", "Missing").WithLocation(6, 72)
+ );
+ }
+
+ [Fact]
+ [WorkItem("https://github.com/dotnet/roslyn/issues/81576")]
+ public void Issue81576_03()
+ {
+ var source = """
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Runtime.CompilerServices;
+
+ [CollectionBuilder(typeof(MyFancyCollection), nameof(MyFancyCollection.Create))]
+ public class MyFancyCollection : IEnumerable
+ {
+ public MyFancyCollection Create(ReadOnlySpan ints)
+ {
+ return null;
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ throw new NotImplementedException();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+ """;
+
+ CreateCompilationWithSpan([source, CollectionBuilderAttributeDefinition]).VerifyEmitDiagnostics();
+ }
}
}
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs
index 992c884f56c44..7a73e7f95f154 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs
@@ -2348,7 +2348,7 @@ class Attr : System.Attribute { public Attr(string s) {} }";
}
[Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
- public void TestInvalidRecursiveUsageOfNameofInAttributesDoesNotCrashCompiler2()
+ public void TestInvalidRecursiveUsageOfNameofInAttributesDoesNotCrashCompiler2_01()
{
var source = @"
class C
@@ -2365,6 +2365,50 @@ class Attr : System.Attribute { public Attr(string s) {} }";
};
CreateCompilation(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics(expectedDiagnostics);
CreateCompilation(source, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(expectedDiagnostics);
+ CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
+ // (4,18): error CS0120: An object reference is required for the non-static field, method, or property 'C.Method()'
+ // [Attr(nameof(Method().Method))]
+ Diagnostic(ErrorCode.ERR_ObjectRequired, "Method").WithArguments("C.Method()").WithLocation(4, 18)
+ );
+ }
+
+ [Fact]
+ public void TestInvalidRecursiveUsageOfNameofInAttributesDoesNotCrashCompiler2_02()
+ {
+ var source = @"
+class C
+{
+ [Attr(nameof(P.P))]
+ C P => default;
+}
+class Attr : System.Attribute { public Attr(string s) {} }";
+ CreateCompilation(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics();
+ CreateCompilation(source, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics();
+ CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
+ // (4,18): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
+ // [Attr(nameof(P.P))]
+ Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "P").WithArguments("instance member in 'nameof'", "12.0").WithLocation(4, 18)
+ );
+ }
+
+ [Fact]
+ public void TestInvalidRecursiveUsageOfNameofInAttributesDoesNotCrashCompiler2_03()
+ {
+ var source = @"
+class C
+{
+ [Attr(nameof(this.P.P))]
+ C P => default;
+}
+class Attr : System.Attribute { public Attr(string s) {} }";
+ var expectedDiagnostics = new[]
+ {
+ // (4,18): error CS0027: Keyword 'this' is not available in the current context
+ // [Attr(nameof(this.P.P))]
+ Diagnostic(ErrorCode.ERR_ThisInBadContext, "this").WithLocation(4, 18)
+ };
+ CreateCompilation(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics(expectedDiagnostics);
+ CreateCompilation(source, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(expectedDiagnostics);
CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(expectedDiagnostics);
}