Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -641,9 +641,10 @@ UsingsAndDiagnostics buildUsings(
ImmutableDictionary<string, AliasAndUsingDirective>.Builder? usingAliasesMap = null;
ArrayBuilder<AliasAndUsingDirective>? usingAliases = null;

// A binder that contains the extern aliases but not the usings. The resolution of the target of a using directive or alias
// Binders that contain the extern aliases but not the usings. The resolution of the target of a using directive or alias
// should not make use of other peer usings.
Binder? declarationBinder = null;
Binder? declarationBinderSafe = null;
Binder? declarationBinderUnsafe = null; // with UnsafeRegion flag

PooledHashSet<NamespaceOrTypeSymbol>? uniqueUsings = null;
PooledHashSet<NamespaceOrTypeSymbol>? uniqueGlobalUsings = null;
Expand Down Expand Up @@ -732,7 +733,7 @@ UsingsAndDiagnostics buildUsings(
continue;
}

var flags = BinderFlags.SuppressConstraintChecks;
bool needsUnsafeBinder = false;
if (usingDirective.UnsafeKeyword != default)
{
var unsafeKeywordLocation = usingDirective.UnsafeKeyword.GetLocation();
Expand All @@ -746,7 +747,7 @@ UsingsAndDiagnostics buildUsings(
declaringSymbol.CheckUnsafeModifier(DeclarationModifiers.Unsafe, unsafeKeywordLocation, diagnostics);
}

flags |= BinderFlags.UnsafeRegion;
needsUnsafeBinder = true;
}
else
{
Expand All @@ -755,14 +756,26 @@ UsingsAndDiagnostics buildUsings(
// List<int*[]>;` to be written. In 12.0 and onwards though, we require the code to
// explicitly contain the `unsafe` keyword.
if (!compilation.IsFeatureEnabled(MessageID.IDS_FeatureUsingTypeAlias))
flags |= BinderFlags.UnsafeRegion;
needsUnsafeBinder = true;
}

var directiveDiagnostics = BindingDiagnosticBag.GetInstance();
Debug.Assert(directiveDiagnostics.DiagnosticBag is object);
Debug.Assert(directiveDiagnostics.DependenciesBag is object);

declarationBinder ??= compilation.GetBinderFactory(declarationSyntax.SyntaxTree).GetBinder(usingDirective.NamespaceOrType).WithAdditionalFlags(flags);
declarationBinderSafe ??= compilation.GetBinderFactory(declarationSyntax.SyntaxTree).GetBinder(usingDirective.NamespaceOrType).WithAdditionalFlags(BinderFlags.SuppressConstraintChecks);

Binder declarationBinder;
if (needsUnsafeBinder)
{
declarationBinderUnsafe ??= declarationBinderSafe.WithAdditionalFlags(BinderFlags.UnsafeRegion);
declarationBinder = declarationBinderUnsafe;
}
else
{
declarationBinder = declarationBinderSafe;
}

var imported = declarationBinder.BindNamespaceOrTypeSymbol(usingDirective.NamespaceOrType, directiveDiagnostics, basesBeingResolved).NamespaceOrTypeSymbol;
bool addDirectiveDiagnostics = true;

Expand Down
48 changes: 48 additions & 0 deletions src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13251,6 +13251,54 @@ unsafe void M2(X t) { }
Diagnostic(ErrorCode.ERR_UnsafeNeeded, "X").WithLocation(6, 13));
}

[Fact]
public void UsingAlias_Multiple()
{
CreateCompilation("""
#pragma warning disable CS8019 // unnecessary using
using unsafe X = System.Collections.Generic.List<int*[]>;
using Y = System.Collections.Generic.List<long*[]>;
""",
options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (3,43): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
// using Y = System.Collections.Generic.List<long*[]>;
Diagnostic(ErrorCode.ERR_UnsafeNeeded, "long*").WithLocation(3, 43));

CreateCompilation("""
#pragma warning disable CS8019 // unnecessary using
using X = System.Collections.Generic.List<int*[]>;
using unsafe Y = System.Collections.Generic.List<long*[]>;
""",
options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (2,43): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
// using X = System.Collections.Generic.List<int*[]>;
Diagnostic(ErrorCode.ERR_UnsafeNeeded, "int*").WithLocation(2, 43));
}

[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/82426")]
public void UsingStatic_Multiple()
{
CreateCompilation("""
#pragma warning disable CS8019 // unnecessary using
using static unsafe System.Collections.Generic.List<int*[]>;
using static System.Collections.Generic.List<long*[]>;
""",
options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (3,46): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
// using static System.Collections.Generic.List<long*[]>;
Diagnostic(ErrorCode.ERR_UnsafeNeeded, "long*").WithLocation(3, 46));

CreateCompilation("""
#pragma warning disable CS8019 // unnecessary using
using static System.Collections.Generic.List<int*[]>;
using static unsafe System.Collections.Generic.List<long*[]>;
""",
options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (2,46): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
// using static System.Collections.Generic.List<int*[]>;
Diagnostic(ErrorCode.ERR_UnsafeNeeded, "int*").WithLocation(2, 46));
}

[Fact]
public void TestStructWithReferenceToItselfThroughAliasPointer1()
{
Expand Down