|
// 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;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics
{
public class AccessCheckTests : CompilingTestBase
{
[Fact]
public void AccessCheckOutsideToInner()
{
CSharpCompilation c = CreateCompilation(@"
class C
{
static public int c_pub;
static internal int c_int;
static protected int c_pro;
static internal protected int c_intpro;
static private int c_priv;
void m()
{
C.c_pub = 1;
C.c_int = 1;
C.c_pro = 1;
C.c_intpro = 1;
C.c_priv = 1;
N1.n1_pub = 1;
N1.n1_int = 1;
N1.n1_pro = 1;
N1.n1_intpro = 1;
N1.n1_priv = 1;
N1.N2.n2_pub = 1;
N1.N2.n2_int = 1;
N1.N2.n2_pro = 1;
N1.N2.n2_intpro = 1;
N1.N2.n2_priv = 1;
N1.N3.n3_pub = 1;
N1.N4.n4_pub = 1;
N1.N5.n5_pub = 1;
N1.N6.n6_pub = 1;
}
private class N1
{
static public int n1_pub;
static internal int n1_int;
static protected int n1_pro;
static internal protected int n1_intpro;
static private int n1_priv;
public class N2
{
static public int n2_pub;
static internal int n2_int;
static protected int n2_pro;
static internal protected int n2_intpro;
static private int n2_priv;
}
private class N3
{
static public int n3_pub;
}
protected class N4
{
static public int n4_pub;
}
internal class N5
{
static public int n5_pub;
}
protected internal class N6
{
static public int n6_pub;
}
}
}
");
c.VerifyDiagnostics(
// (19,12): error CS0122: 'C.N1.n1_pro' is inaccessible due to its protection level
// N1.n1_pro = 1;
Diagnostic(ErrorCode.ERR_BadAccess, "n1_pro").WithArguments("C.N1.n1_pro"),
// (21,12): error CS0122: 'C.N1.n1_priv' is inaccessible due to its protection level
// N1.n1_priv = 1;
Diagnostic(ErrorCode.ERR_BadAccess, "n1_priv").WithArguments("C.N1.n1_priv"),
// (24,15): error CS0122: 'C.N1.N2.n2_pro' is inaccessible due to its protection level
// N1.N2.n2_pro = 1;
Diagnostic(ErrorCode.ERR_BadAccess, "n2_pro").WithArguments("C.N1.N2.n2_pro"),
// (26,15): error CS0122: 'C.N1.N2.n2_priv' is inaccessible due to its protection level
// N1.N2.n2_priv = 1;
Diagnostic(ErrorCode.ERR_BadAccess, "n2_priv").WithArguments("C.N1.N2.n2_priv"),
// (27,12): error CS0122: 'C.N1.N3' is inaccessible due to its protection level
// N1.N3.n3_pub = 1;
Diagnostic(ErrorCode.ERR_BadAccess, "N3").WithArguments("C.N1.N3"),
// (28,12): error CS0122: 'C.N1.N4' is inaccessible due to its protection level
// N1.N4.n4_pub = 1;
Diagnostic(ErrorCode.ERR_BadAccess, "N4").WithArguments("C.N1.N4"),
// (37,30): warning CS0649: Field 'C.N1.n1_pro' is never assigned to, and will always have its default value 0
// static protected int n1_pro;
Diagnostic(ErrorCode.WRN_UnassignedInternalField, "n1_pro").WithArguments("C.N1.n1_pro", "0"),
// (39,28): warning CS0169: The field 'C.N1.n1_priv' is never used
// static private int n1_priv;
Diagnostic(ErrorCode.WRN_UnreferencedField, "n1_priv").WithArguments("C.N1.n1_priv"),
// (45,34): warning CS0649: Field 'C.N1.N2.n2_pro' is never assigned to, and will always have its default value 0
// static protected int n2_pro;
Diagnostic(ErrorCode.WRN_UnassignedInternalField, "n2_pro").WithArguments("C.N1.N2.n2_pro", "0"),
// (47,32): warning CS0169: The field 'C.N1.N2.n2_priv' is never used
// static private int n2_priv;
Diagnostic(ErrorCode.WRN_UnreferencedField, "n2_priv").WithArguments("C.N1.N2.n2_priv"),
// (52,31): warning CS0649: Field 'C.N1.N3.n3_pub' is never assigned to, and will always have its default value 0
// static public int n3_pub;
Diagnostic(ErrorCode.WRN_UnassignedInternalField, "n3_pub").WithArguments("C.N1.N3.n3_pub", "0"),
// (57,31): warning CS0649: Field 'C.N1.N4.n4_pub' is never assigned to, and will always have its default value 0
// static public int n4_pub;
Diagnostic(ErrorCode.WRN_UnassignedInternalField, "n4_pub").WithArguments("C.N1.N4.n4_pub", "0"),
// (8,24): warning CS0414: The field 'C.c_priv' is assigned but its value is never used
// static private int c_priv;
Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "c_priv").WithArguments("C.c_priv")
);
}
[Fact]
public void AccessCheckInnerToOuter()
{
CSharpCompilation c = CreateCompilation(@"
class C
{
static public int c_pub;
static internal int c_int;
static protected int c_pro;
static internal protected int c_intpro;
static private int c_priv;
private class N1
{
static public int n1_pub;
static internal int n1_int;
static protected int n1_pro;
static internal protected int n1_intpro;
static private int n1_priv;
public class N2
{
static public int n2_pub;
static internal int n2_int;
static protected int n2_pro;
static internal protected int n2_intpro;
static private int n2_priv;
void m()
{
c_pub = 1;
c_int = 1;
c_pro = 1;
c_intpro = 1;
c_priv = 1;
n1_pub = 1;
n1_int = 1;
n1_pro = 1;
n1_intpro = 1;
n1_priv = 1;
n2_pub = 1;
n2_int = 1;
n2_pro = 1;
n2_intpro = 1;
n2_priv = 1;
N3.n3_pub = 1;
N4.n4_pub = 1;
N5.n5_pub = 1;
N6.n6_pub = 1;
}
}
private class N3
{
static public int n3_pub;
}
protected class N4
{
static public int n4_pub;
}
internal class N5
{
static public int n5_pub;
}
protected internal class N6
{
static public int n6_pub;
}
}
}
");
c.VerifyDiagnostics(
// (8,24): warning CS0414: The field 'C.c_priv' is assigned but its value is never used
// static private int c_priv;
Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "c_priv").WithArguments("C.c_priv"),
// (17,28): warning CS0414: The field 'C.N1.n1_priv' is assigned but its value is never used
// static private int n1_priv;
Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "n1_priv").WithArguments("C.N1.n1_priv"),
// (25,32): warning CS0414: The field 'C.N1.N2.n2_priv' is assigned but its value is never used
// static private int n2_priv;
Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "n2_priv").WithArguments("C.N1.N2.n2_priv")
);
}
[Fact]
public void AccessCheckDerived()
{
CSharpCompilation c = CreateCompilation(@"
class C
{
static public int c_pub;
static internal int c_int;
static protected int c_pro;
static internal protected int c_intpro;
static private int c_priv;
protected class N3
{
static public int n3_pub;
static internal int n3_int;
static protected int n3_pro;
static internal protected int n3_intpro;
static private int n3_priv;
}
private class N4
{
static public int n4_pub;
}
internal class N5
{
static public int n5_pub;
}
protected internal class N6
{
static public int n6_pub;
}
}
class D: C
{
static public int n1_pub;
static internal int n1_int;
static protected int n1_pro;
static internal protected int n1_intpro;
static private int n1_priv;
}
class E: D
{
static public int n2_pub;
static internal int n2_int;
static protected int n2_pro;
static internal protected int n2_intpro;
static private int n2_priv;
void m()
{
c_pub = 1;
c_int = 1;
c_pro = 1;
c_intpro = 1;
c_priv = 1;
n1_pub = 1;
n1_int = 1;
n1_pro = 1;
n1_intpro = 1;
n1_priv = 1;
n2_pub = 1;
n2_int = 1;
n2_pro = 1;
n2_intpro = 1;
n2_priv = 1;
N3.n3_pub = 1;
N3.n3_int = 1;
N3.n3_pro = 1;
N3.n3_intpro = 1;
N3.n3_priv = 1;
N4.n4_pub = 1;
N5.n5_pub = 1;
N6.n6_pub = 1;
}
}
");
c.VerifyDiagnostics(
// (58,9): error CS0122: 'C.c_priv' is inaccessible due to its protection level
// c_priv = 1;
Diagnostic(ErrorCode.ERR_BadAccess, "c_priv").WithArguments("C.c_priv"),
// (63,9): error CS0122: 'D.n1_priv' is inaccessible due to its protection level
// n1_priv = 1;
Diagnostic(ErrorCode.ERR_BadAccess, "n1_priv").WithArguments("D.n1_priv"),
// (71,12): error CS0122: 'C.N3.n3_pro' is inaccessible due to its protection level
// N3.n3_pro = 1;
Diagnostic(ErrorCode.ERR_BadAccess, "n3_pro").WithArguments("C.N3.n3_pro"),
// (73,12): error CS0122: 'C.N3.n3_priv' is inaccessible due to its protection level
// N3.n3_priv = 1;
Diagnostic(ErrorCode.ERR_BadAccess, "n3_priv").WithArguments("C.N3.n3_priv"),
// (74,9): error CS0122: 'C.N4' is inaccessible due to its protection level
// N4.n4_pub = 1;
Diagnostic(ErrorCode.ERR_BadAccess, "N4").WithArguments("C.N4"),
// (14,30): warning CS0649: Field 'C.N3.n3_pro' is never assigned to, and will always have its default value 0
// static protected int n3_pro;
Diagnostic(ErrorCode.WRN_UnassignedInternalField, "n3_pro").WithArguments("C.N3.n3_pro", "0"),
// (16,28): warning CS0169: The field 'C.N3.n3_priv' is never used
// static private int n3_priv;
Diagnostic(ErrorCode.WRN_UnreferencedField, "n3_priv").WithArguments("C.N3.n3_priv"),
// (21,27): warning CS0649: Field 'C.N4.n4_pub' is never assigned to, and will always have its default value 0
// static public int n4_pub;
Diagnostic(ErrorCode.WRN_UnassignedInternalField, "n4_pub").WithArguments("C.N4.n4_pub", "0"),
// (8,24): warning CS0414: The field 'C.c_priv' is assigned but its value is never used
// static private int c_priv;
Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "c_priv").WithArguments("C.c_priv"),
// (41,24): warning CS0414: The field 'D.n1_priv' is assigned but its value is never used
// static private int n1_priv;
Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "n1_priv").WithArguments("D.n1_priv"),
// (50,24): warning CS0414: The field 'E.n2_priv' is assigned but its value is never used
// static private int n2_priv;
Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "n2_priv").WithArguments("E.n2_priv")
);
}
[Fact]
public void AccessCheckProtected()
{
CSharpCompilation c = CreateCompilation(@"
public class A
{
protected int iField;
static protected int sField;
}
public class B : A
{
public class N : A
{
public class NN
{
public void m(B b, C c, D d, E e) {
int x = b.iField;
int y = B.sField;
int z = c.iField;
int w = C.sField;
int q = d.iField;
int r = D.sField;
int s = e.iField;
int t = E.sField;
}
}
}
}
public class C : B
{}
public class D : A
{}
public class E : B.N
{}");
c.VerifyDiagnostics(
// (19,27): error CS1540: Cannot access protected member 'A.iField' via a qualifier of type 'D'; the qualifier must be of type 'B.N.NN' (or derived from it)
// int q = d.iField;
Diagnostic(ErrorCode.ERR_BadProtectedAccess, "iField").WithArguments("A.iField", "D", "B.N.NN").WithLocation(19, 27));
}
[WorkItem(539561, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539561")]
[Fact]
public void AccessCheckProtected02()
{
CSharpCompilation c = CreateCompilation(@"
interface I<T> { }
class A { }
class C : I<C.D.E>
{
protected class D : A
{
public class E { }
}
}
");
c.VerifyDiagnostics();
}
[WorkItem(539561, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539561")]
[Fact]
public void AccessCheckProtected03()
{
CSharpCompilation c = CreateCompilation(@"
class X<T> { }
class A { }
class B
{
class C : X<C.D.E>
{
protected class D : A
{
public class E { }
}
}
}
");
c.VerifyDiagnostics(
// (8,11): error CS0060: Inconsistent accessibility: base type 'X<B.C.D.E>' is less accessible than class 'B.C'
// class C : X<C.D.E>
Diagnostic(ErrorCode.ERR_BadVisBaseClass, "C").WithArguments("B.C", "X<B.C.D.E>").WithLocation(8, 11));
}
[Fact]
public void AccessCheckProtected04()
{
CSharpCompilation c = CreateCompilation(@"
public class B
{
protected void M(int x) {}
public void M(double x) {}
}
public class D : B
{
public void X()
{
B b = new D();
b.M(123); // because of the receiver type, only M(double x) is accessible.
}
}
");
c.VerifyDiagnostics();
}
[Fact]
public void AccessCheckProtectedColorColor()
{
// Inaccessible methods are not a member of a method group.
// This fact has interesting implications in "Color Color" scenarios; when one
// interpretation would produce an error, we fall back to the non-error producing
// interpretation.
//
// Here we verify that every combination of overload resolution problems involving
// a potential "color color" scenario that *can* succeed *does* succeed, even if
// doing so picks a "worse" method. Case 5, where both the double and int versions
// are protected instance methods must fail, and is therefore omitted. All the rest
// have a way to succeed, either by calling a protected static method or a non-protected
// instance method.
CSharpCompilation c = CreateCompilation(@"
namespace CS1540
{
public class Base
{
public Base() {}
protected static void M0(double x) {}
protected void M1(double x) {}
public static void M2(double x) {}
public void M3(double x) {}
protected static void M4(double x) {}
// protected void M5(double x) {}
public static void M6(double x) {}
public void M7(double x) {}
protected static void M8(double x) {}
protected void M9(double x) {}
public static void Ma(double x) {}
public void Mb(double x) {}
protected static void Mc(double x) {}
protected void Md(double x) {}
public static void Me(double x) {}
public void Mf(double x) {}
protected static void M0(int x) {}
protected static void M1(int x) {}
protected static void M2(int x) {}
protected static void M3(int x) {}
protected void M4(int x) {}
// protected void M5(int x) {}
protected void M6(int x) {}
protected void M7(int x) {}
public static void M8(int x) {}
public static void M9(int x) {}
public static void Ma(int x) {}
public static void Mb(int x) {}
public void Mc(int x) {}
public void Md(int x) {}
public void Me(int x) {}
public void Mf(int x) {}
}
public class Derived : Base
{
public Base Base { get { return new Base(); } }
private void X()
{
Base.M0(123);
Base.M1(123);
Base.M2(123);
Base.M3(123);
Base.M4(123);
//Base.M5(123);
Base.M6(123);
Base.M7(123);
Base.M8(123);
Base.M9(123);
Base.Ma(123);
Base.Mb(123);
Base.Mc(123);
Base.Md(123);
Base.Me(123);
Base.Mf(123);
}
static void Main()
{
}
}
}
");
c.VerifyDiagnostics();
}
[WorkItem(539561, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539561")]
[Fact]
public void AccessCheckPrivate()
{
CSharpCompilation c = CreateCompilation(@"
interface I<T> { }
class A { }
class C : I<C.D.E>
{
private class D : A
{
public class E { }
}
}
");
c.VerifyDiagnostics();
}
[WorkItem(539561, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539561")]
[Fact]
public void AccessCheckPrivate02()
{
CSharpCompilation c = CreateCompilation(@"
class X<T> { }
class A { }
class B
{
class C : X<C.D.E>
{
private class D : A
{
public class E { }
}
}
}
");
c.VerifyDiagnostics(
// (8,11): error CS0060: Inconsistent accessibility: base type 'X<B.C.D.E>' is less accessible than class 'B.C'
// class C : X<C.D.E>
Diagnostic(ErrorCode.ERR_BadVisBaseClass, "C").WithArguments("B.C", "X<B.C.D.E>").WithLocation(8, 11));
}
[Fact]
public void AccessCheckCrossAssembly()
{
CSharpCompilation other = CreateCompilation(@"
public class C
{
static public int c_pub;
static internal int c_int;
static protected int c_pro;
static internal protected int c_intpro;
static private int c_priv;
}
internal class D
{
static public int d_pub;
}");
CSharpCompilation c = CreateCompilation(@"
public class A
{
public void m() {
int a = C.c_pub;
int b = C.c_int;
int c = C.c_pro;
int d = C.c_intpro;
int e = C.c_priv;
int f = D.d_pub;
}
}", new List<MetadataReference>() { new CSharpCompilationReference(other) });
c.VerifyDiagnostics(
// (6,19): error CS0122: 'C.c_int' is inaccessible due to its protection level
// int b = C.c_int;
Diagnostic(ErrorCode.ERR_BadAccess, "c_int").WithArguments("C.c_int").WithLocation(6, 19),
// (7,19): error CS0122: 'C.c_pro' is inaccessible due to its protection level
// int c = C.c_pro;
Diagnostic(ErrorCode.ERR_BadAccess, "c_pro").WithArguments("C.c_pro").WithLocation(7, 19),
// (8,19): error CS0122: 'C.c_intpro' is inaccessible due to its protection level
// int d = C.c_intpro;
Diagnostic(ErrorCode.ERR_BadAccess, "c_intpro").WithArguments("C.c_intpro").WithLocation(8, 19),
// (9,19): error CS0122: 'C.c_priv' is inaccessible due to its protection level
// int e = C.c_priv;
Diagnostic(ErrorCode.ERR_BadAccess, "c_priv").WithArguments("C.c_priv").WithLocation(9, 19),
// (10,17): error CS0122: 'D' is inaccessible due to its protection level
// int f = D.d_pub;
Diagnostic(ErrorCode.ERR_BadAccess, "D").WithArguments("D").WithLocation(10, 17)
);
}
[Fact]
public void AccessCheckCrossAssemblyDerived()
{
CSharpCompilation other = CreateCompilation(@"
public class C
{
static public int c_pub;
static internal int c_int;
static protected int c_pro;
static internal protected int c_intpro;
static private int c_priv;
}
internal class D
{
static public int d_pub;
}");
CSharpCompilation c = CreateCompilation(@"
public class A: C
{
public void m() {
int a = C.c_pub;
int b = C.c_int;
int c = C.c_pro;
int d = C.c_intpro;
int e = C.c_priv;
int f = D.d_pub;
}
}", new[] { new CSharpCompilationReference(other) });
c.VerifyDiagnostics(
// (6,19): error CS0122: 'C.c_int' is inaccessible due to its protection level
// int b = C.c_int;
Diagnostic(ErrorCode.ERR_BadAccess, "c_int").WithArguments("C.c_int").WithLocation(6, 19),
// (9,19): error CS0122: 'C.c_priv' is inaccessible due to its protection level
// int e = C.c_priv;
Diagnostic(ErrorCode.ERR_BadAccess, "c_priv").WithArguments("C.c_priv").WithLocation(9, 19),
// (10,17): error CS0122: 'D' is inaccessible due to its protection level
// int f = D.d_pub;
Diagnostic(ErrorCode.ERR_BadAccess, "D").WithArguments("D").WithLocation(10, 17)
);
}
[Fact]
public void AccessCheckApi_01()
{
Compilation c = CreateCompilation(@"
using System.Collections.Generic;
using AliasForA = A;
class A
{
static private int priv;
static public int pub;
protected int prot;
static private Goo unknowntype;
private class K {}
private K[] karray;
private A[] aarray;
private K* kptr;
private A* aptr;
private delegate*<A, A, K> kinreturnfuncptr;
private delegate*<K, A, A> kinparamfuncptr1;
private delegate*<A, K, A> kinparamfuncptr2;
private delegate*<A, A> afuncptr;
private IEnumerable<K> kenum;
private IEnumerable<A> aenum;
void M()
{
_ = new A.K(); // K discard
_ = new A(); // A discard
}
}
class B
{}
class ADerived: A
{}
class ADerived2: A
{}
");
Compilation compilation = c;
INamespaceSymbol globalNS = c.GlobalNamespace;
IAssemblySymbol sourceAssem = c.SourceModule.ContainingAssembly;
IAssemblySymbol mscorlibAssem = ((CSharpCompilation)c).GetReferencedAssemblySymbol(c.ExternalReferences[0]).GetPublicSymbol();
INamedTypeSymbol classA = globalNS.GetMembers("A").Single() as INamedTypeSymbol;
var tree = c.SyntaxTrees.First();
var model = c.GetSemanticModel(tree);
IAliasSymbol aliasA = model.GetDeclaredSymbol(tree.GetRoot().DescendantNodes().OfType<UsingDirectiveSyntax>().Where(u => u.Alias != null).Single()) as IAliasSymbol;
INamedTypeSymbol classADerived = globalNS.GetMembers("ADerived").Single() as INamedTypeSymbol;
INamedTypeSymbol classADerived2 = globalNS.GetMembers("ADerived2").Single() as INamedTypeSymbol;
INamedTypeSymbol classB = globalNS.GetMembers("B").Single() as INamedTypeSymbol;
INamedTypeSymbol classK = classA.GetMembers("K").Single() as INamedTypeSymbol;
IFieldSymbol privField = classA.GetMembers("priv").Single() as IFieldSymbol;
IFieldSymbol pubField = classA.GetMembers("pub").Single() as IFieldSymbol;
IFieldSymbol protField = classA.GetMembers("prot").Single() as IFieldSymbol;
ITypeSymbol karrayType = (classA.GetMembers("karray").Single() as IFieldSymbol).Type;
ITypeSymbol aarrayType = (classA.GetMembers("aarray").Single() as IFieldSymbol).Type;
ITypeSymbol kptrType = (classA.GetMembers("kptr").Single() as IFieldSymbol).Type;
ITypeSymbol aptrType = (classA.GetMembers("aptr").Single() as IFieldSymbol).Type;
ITypeSymbol kinreturnfuncptrType = (classA.GetMembers("kinreturnfuncptr").Single() as IFieldSymbol).Type;
ITypeSymbol kinparamfuncptr1Type = (classA.GetMembers("kinparamfuncptr1").Single() as IFieldSymbol).Type;
ITypeSymbol kinparamfuncptr2Type = (classA.GetMembers("kinparamfuncptr2").Single() as IFieldSymbol).Type;
ITypeSymbol afuncptrType = (classA.GetMembers("afuncptr").Single() as IFieldSymbol).Type;
ITypeSymbol kenumType = (classA.GetMembers("kenum").Single() as IFieldSymbol).Type;
ITypeSymbol aenumType = (classA.GetMembers("aenum").Single() as IFieldSymbol).Type;
var discards = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(i => i.Identifier.ContextualKind() == SyntaxKind.UnderscoreToken).ToArray();
IDiscardSymbol kdiscard = (IDiscardSymbol)model.GetSymbolInfo(discards[0]).Symbol;
IDiscardSymbol adiscard = (IDiscardSymbol)model.GetSymbolInfo(discards[1]).Symbol;
ITypeSymbol unknownType = (classA.GetMembers("unknowntype").Single() as IFieldSymbol).Type;
ISymbol nullSymbol = null;
Assert.Throws<ArgumentNullException>(() => { compilation.IsSymbolAccessibleWithin(classA, nullSymbol); });
Assert.Throws<ArgumentNullException>(() => { compilation.IsSymbolAccessibleWithin(nullSymbol, classA); });
Assert.Throws<ArgumentException>(() => { compilation.IsSymbolAccessibleWithin(classA, pubField); });
Assert.True(Symbol.IsSymbolAccessible(classA.GetSymbol(), classB.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(classA, classB));
Assert.True(Symbol.IsSymbolAccessible(aliasA.GetSymbol(), classB.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(aliasA, classB));
Assert.True(Symbol.IsSymbolAccessible(pubField.GetSymbol(), classB.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(pubField, classB));
Assert.False(Symbol.IsSymbolAccessible(privField.GetSymbol(), classB.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(privField, classB));
Assert.False(Symbol.IsSymbolAccessible(karrayType.GetSymbol(), classB.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(karrayType, classB));
Assert.True(Symbol.IsSymbolAccessible(aarrayType.GetSymbol(), classB.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(aarrayType, classB));
Assert.False(Symbol.IsSymbolAccessible(kptrType.GetSymbol(), classB.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(kptrType, classB));
Assert.True(Symbol.IsSymbolAccessible(aptrType.GetSymbol(), classB.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(aptrType, classB));
Assert.False(Symbol.IsSymbolAccessible(kinreturnfuncptrType.GetSymbol(), classB.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(kinreturnfuncptrType, classB));
Assert.False(Symbol.IsSymbolAccessible(kinparamfuncptr1Type.GetSymbol(), classB.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(kinparamfuncptr1Type, classB));
Assert.False(Symbol.IsSymbolAccessible(kinparamfuncptr2Type.GetSymbol(), classB.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(kinparamfuncptr2Type, classB));
Assert.True(Symbol.IsSymbolAccessible(afuncptrType.GetSymbol(), classB.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(afuncptrType, classB));
Assert.False(Symbol.IsSymbolAccessible(kdiscard.GetSymbol(), classB.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(kdiscard, classB));
Assert.True(Symbol.IsSymbolAccessible(adiscard.GetSymbol(), classB.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(adiscard, classB));
Assert.False(Symbol.IsSymbolAccessible(kenumType.GetSymbol(), classB.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(kenumType, classB));
Assert.True(Symbol.IsSymbolAccessible(aenumType.GetSymbol(), classB.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(aenumType, classB));
Assert.True(Symbol.IsSymbolAccessible(unknownType.GetSymbol(), classB.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(unknownType, classB));
Assert.True(Symbol.IsSymbolAccessible(globalNS.GetSymbol(), classB.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(globalNS, classB));
Assert.True(Symbol.IsSymbolAccessible(protField.GetSymbol(), classA.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(protField, classA));
Assert.True(Symbol.IsSymbolAccessible(protField.GetSymbol(), classA.GetSymbol(), classADerived.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(protField, classA, classADerived));
Assert.False(Symbol.IsSymbolAccessible(protField.GetSymbol(), classB.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(protField, classB));
Assert.False(Symbol.IsSymbolAccessible(protField.GetSymbol(), classB.GetSymbol(), classADerived.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(protField, classB, classADerived));
Assert.True(Symbol.IsSymbolAccessible(protField.GetSymbol(), classA.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(protField, classA));
Assert.True(Symbol.IsSymbolAccessible(protField.GetSymbol(), classADerived.GetSymbol(), classADerived.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(protField, classADerived, classADerived));
Assert.False(Symbol.IsSymbolAccessible(protField.GetSymbol(), classADerived.GetSymbol(), classADerived2.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(protField, classADerived, classADerived2));
Assert.True(Symbol.IsSymbolAccessible(classA.GetSymbol(), sourceAssem.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(classA, sourceAssem));
Assert.True(Symbol.IsSymbolAccessible(aliasA.GetSymbol(), sourceAssem.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(aliasA, sourceAssem));
Assert.True(Symbol.IsSymbolAccessible(aarrayType.GetSymbol(), sourceAssem.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(aarrayType, sourceAssem));
Assert.False(Symbol.IsSymbolAccessible(karrayType.GetSymbol(), sourceAssem.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(karrayType, sourceAssem));
Assert.True(Symbol.IsSymbolAccessible(aptrType.GetSymbol(), sourceAssem.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(aptrType, sourceAssem));
Assert.True(Symbol.IsSymbolAccessible(afuncptrType.GetSymbol(), sourceAssem.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(afuncptrType, sourceAssem));
Assert.False(Symbol.IsSymbolAccessible(kptrType.GetSymbol(), sourceAssem.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(kptrType, sourceAssem));
Assert.False(Symbol.IsSymbolAccessible(kinreturnfuncptrType.GetSymbol(), sourceAssem.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(kinreturnfuncptrType, sourceAssem));
Assert.False(Symbol.IsSymbolAccessible(kinparamfuncptr1Type.GetSymbol(), sourceAssem.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(kinparamfuncptr1Type, sourceAssem));
Assert.False(Symbol.IsSymbolAccessible(kinparamfuncptr2Type.GetSymbol(), sourceAssem.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(kinparamfuncptr2Type, sourceAssem));
Assert.True(Symbol.IsSymbolAccessible(adiscard.GetSymbol(), sourceAssem.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(adiscard, sourceAssem));
Assert.False(Symbol.IsSymbolAccessible(kdiscard.GetSymbol(), sourceAssem.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(kdiscard, sourceAssem));
Assert.False(Symbol.IsSymbolAccessible(classA.GetSymbol(), mscorlibAssem.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(classA, mscorlibAssem));
Assert.False(Symbol.IsSymbolAccessible(aliasA.GetSymbol(), mscorlibAssem.GetSymbol()));
Assert.False(compilation.IsSymbolAccessibleWithin(aliasA, mscorlibAssem));
Assert.True(Symbol.IsSymbolAccessible(unknownType.GetSymbol(), sourceAssem.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(unknownType, sourceAssem));
Assert.True(Symbol.IsSymbolAccessible(mscorlibAssem.GetSymbol(), sourceAssem.GetSymbol()));
Assert.True(compilation.IsSymbolAccessibleWithin(mscorlibAssem, sourceAssem));
Compilation otherC = CreateCompilation(@"
class Other
{
}");
INamespaceSymbol otherGlobalNS = otherC.GlobalNamespace;
INamedTypeSymbol classOther = otherGlobalNS.GetMembers("Other").Single() as INamedTypeSymbol;
Assert.Throws<ArgumentException>(() => { compilation.IsSymbolAccessibleWithin(classA, classOther); });
}
[Fact]
public void AccessCheckApi_02()
{
Compilation c1 = CreateCompilation(@"
using SomeAlias = System.Int32;
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""C3"")]
internal class Outer
{
private class Inner
{
public int Field;
}
private Inner* Pointer;
private int Integer = 1 + 2;
protected int Protected;
protected internal int ProtectedInternal;
private protected int PrivateProtected;
}
internal class Other
{
}
private class Private
{
}
internal class Derived : Outer
{
}
");
Compilation compilation1 = c1;
var tree = c1.SyntaxTrees.First();
var model = c1.GetSemanticModel(tree);
IAliasSymbol SomeAlias = model.GetDeclaredSymbol(tree.GetRoot().DescendantNodes().OfType<UsingDirectiveSyntax>().Where(u => u.Alias != null).Single());
INamespaceSymbol globalNS = c1.GlobalNamespace;
IAssemblySymbol sourceAssem = c1.SourceModule.ContainingAssembly;
IAssemblySymbol mscorlibAssem = ((CSharpCompilation)c1).GetReferencedAssemblySymbol(c1.ExternalReferences[0]).GetPublicSymbol();
INamedTypeSymbol Outer = globalNS.GetMembers("Outer").Single() as INamedTypeSymbol;
INamedTypeSymbol Outer_Inner = Outer.GetMembers("Inner").Single() as INamedTypeSymbol;
IFieldSymbol Outer_Inner_Field = Outer_Inner.GetMembers("Field").Single() as IFieldSymbol;
IFieldSymbol Outer_Pointer = Outer.GetMembers("Pointer").Single() as IFieldSymbol;
IFieldSymbol Outer_Protected = Outer.GetMembers("Protected").Single() as IFieldSymbol;
IFieldSymbol Outer_ProtectedInternal = Outer.GetMembers("ProtectedInternal").Single() as IFieldSymbol;
IFieldSymbol Outer_PrivateProtected = Outer.GetMembers("PrivateProtected").Single() as IFieldSymbol;
INamedTypeSymbol Other = globalNS.GetMembers("Other").Single() as INamedTypeSymbol;
INamedTypeSymbol Private = globalNS.GetMembers("Private").Single() as INamedTypeSymbol;
Assert.Equal(Accessibility.Private, Private.DeclaredAccessibility);
IMethodSymbol IntegerPlus = model.GetSymbolInfo(tree.GetRoot().DescendantNodes().OfType<BinaryExpressionSyntax>().Single()).Symbol as IMethodSymbol;
INamedTypeSymbol Derived = globalNS.GetMembers("Derived").Single() as INamedTypeSymbol;
Assert.True(compilation1.IsSymbolAccessibleWithin(SomeAlias, Outer));
Assert.True(compilation1.IsSymbolAccessibleWithin(Outer_Pointer.Type, Outer));
Assert.False(compilation1.IsSymbolAccessibleWithin(Outer_Pointer.Type, Other));
Assert.True(compilation1.IsSymbolAccessibleWithin(IntegerPlus, Other));
Assert.True(compilation1.IsSymbolAccessibleWithin(IntegerPlus, sourceAssem));
Assert.False(compilation1.IsSymbolAccessibleWithin(Private, Other));
Assert.False(compilation1.IsSymbolAccessibleWithin(Private, sourceAssem));
Assert.False(compilation1.IsSymbolAccessibleWithin(Outer_Inner_Field, Other));
Assert.False(compilation1.IsSymbolAccessibleWithin(Outer_Protected, Derived, Outer));
Assert.True(compilation1.IsSymbolAccessibleWithin(Outer_ProtectedInternal, Derived, Outer));
Assert.False(compilation1.IsSymbolAccessibleWithin(Outer_PrivateProtected, Derived, Outer));
Assert.True(compilation1.IsSymbolAccessibleWithin(Outer_Protected, Derived));
Assert.True(compilation1.IsSymbolAccessibleWithin(Outer_ProtectedInternal, Derived));
Assert.True(compilation1.IsSymbolAccessibleWithin(Outer_PrivateProtected, Derived));
Assert.False(compilation1.IsSymbolAccessibleWithin(Outer_Protected, sourceAssem));
Assert.True(compilation1.IsSymbolAccessibleWithin(Outer_Protected, Outer_Inner));
Compilation c2 = CreateCompilation(@"
internal class InOtherCompilation
{
}
");
INamedTypeSymbol InOtherCompilation = c2.GlobalNamespace.GetMember("InOtherCompilation") as INamedTypeSymbol;
Compilation c3 = CreateCompilation(@"
internal class InFriendCompilation
{
}
", assemblyName: "C3");
INamedTypeSymbol InFriendCompilation = c3.GlobalNamespace.GetMember("InFriendCompilation") as INamedTypeSymbol;
Compilation compilation3 = c3;
Assert.Throws<ArgumentException>(() => { compilation3.IsSymbolAccessibleWithin(Outer, InOtherCompilation); });
Assert.Throws<ArgumentException>(() => { compilation3.IsSymbolAccessibleWithin(Outer, InFriendCompilation); });
}
[Fact]
public void AccessCheckApi_03()
{
var r1 = AssemblyMetadata.CreateFromImage(TestResources.General.C1).GetReference(filePath: @"c:\temp\a.dll", display: "R1");
var r2 = AssemblyMetadata.CreateFromImage(TestResources.General.C1).GetReference(filePath: @"c:\temp\a.dll", display: "R2");
var source = @"class Q : C { }";
var c = CreateCompilation(source, new[] { r1 });
Compilation compilation = c;
c.VerifyDiagnostics();
Assert.NotNull(c.GetReferencedAssemblySymbol(r1));
var classC = compilation.GlobalNamespace.GetMembers("C").OfType<INamedTypeSymbol>().Single();
var classQ = compilation.GlobalNamespace.GetMembers("Q").OfType<INamedTypeSymbol>().Single();
Assert.True(compilation.IsSymbolAccessibleWithin(classC, classQ));
c = CreateEmptyCompilation(source, TargetFrameworkUtil.GetReferences(TargetFramework.Standard).AddRange(new[] { r1, r2 }));
c.VerifyDiagnostics();
// duplicate assembly results in no assembly symbol
Assert.Null(c.GetReferencedAssemblySymbol(r1));
// The variable classC represents a symbol from r1, which did not result in any symbols in c
var c2 = ((Compilation)c).GlobalNamespace.GetMembers("C").OfType<INamedTypeSymbol>().Single();
Assert.NotEqual(classC, c2);
Assert.NotNull(c.GetReferencedAssemblySymbol(r2));
classQ = ((Compilation)c).GlobalNamespace.GetMembers("Q").OfType<INamedTypeSymbol>().Single();
// the below should not throw a null reference exception.
Assert.Throws<ArgumentException>(() => compilation.IsSymbolAccessibleWithin(classC, classQ));
}
[Fact]
public void AccessCheckCrossAssemblyParameterProtectedMethodP2P()
{
CSharpCompilation other = CreateCompilation(@"
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""AccessCheckCrossAssemblyParameterProtectedMethod2"")]
internal class C {}",
assemblyName: "AccessCheckCrossAssemblyParameterProtectedMethod1");
Assert.Empty(other.GetDiagnostics());
CSharpCompilation c = CreateCompilation(@"
public class A
{
internal class B
{
protected B(C o) {}
}
}", new MetadataReference[] { new CSharpCompilationReference(other) }, assemblyName: "AccessCheckCrossAssemblyParameterProtectedMethod2");
Assert.Empty(c.GetDiagnostics());
}
[Fact]
public void EnsureAccessCheckWithBadIVTDenies()
{
CSharpCompilation other = CreateCompilation(@"
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""AccessCheckCrossAssemblyParameterProtectedMethod2000000"")]
internal class C {}",
assemblyName: "AccessCheckCrossAssemblyParameterProtectedMethod1");
Assert.Empty(other.GetDiagnostics());
CSharpCompilation c = CreateCompilation(@"
public class A
{
internal class B
{
protected B(C o) {}
}
}", new MetadataReference[] { new CSharpCompilationReference(other) }, assemblyName: "AccessCheckCrossAssemblyParameterProtectedMethod2");
c.VerifyDiagnostics(
// (6,17): error CS0122: 'C' is inaccessible due to its protection level
// protected B(C o) {}
Diagnostic(ErrorCode.ERR_BadAccess, "C").WithArguments("C").WithLocation(6, 17)
);
}
[Fact]
public void AccessCheckCrossAssemblyParameterProtectedMethodMD()
{
var other = CreateCompilation(@"
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""AccessCheckCrossAssemblyParameterProtectedMethod2"")]
internal class C {}",
assemblyName: "AccessCheckCrossAssemblyParameterProtectedMethod1").EmitToArray();
CSharpCompilation c = CreateCompilation(@"
public class A
{
internal class B
{
protected B(C o) {}
}
}", new MetadataReference[] { MetadataReference.CreateFromImage(other) }, assemblyName: "AccessCheckCrossAssemblyParameterProtectedMethod2");
Assert.Empty(c.GetDiagnostics());
}
[WorkItem(543745, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543745")]
[Fact]
public void InternalInaccessibleProperty()
{
var assembly1Compilation = CreateCSharpCompilation("Assembly1",
@"public class InstancePropertyContainer
{
internal protected int PropIntProProSet { get { return 5; } protected set { } }
}",
compilationOptions: TestOptions.ReleaseDll);
var assembly1Verifier = CompileAndVerify(assembly1Compilation);
assembly1Verifier.VerifyDiagnostics();
var assembly2Compilation = CreateCSharpCompilation("Assembly2",
@"public class SubInstancePropertyContainer
{
public static void RunTest()
{
InstancePropertyContainer InstancePropertyContainer = new InstancePropertyContainer();
InstancePropertyContainer.PropIntProProSet = 12;
}
}",
compilationOptions: TestOptions.ReleaseDll,
referencedCompilations: new[] { assembly1Compilation });
assembly2Compilation.VerifyDiagnostics(
// (7,35): error CS0122: 'InstancePropertyContainer.PropIntProProSet' is inaccessible due to its protection level
// InstancePropertyContainer.PropIntProProSet = 12;
Diagnostic(ErrorCode.ERR_BadAccess, "PropIntProProSet").WithArguments("InstancePropertyContainer.PropIntProProSet").WithLocation(7, 35)
);
}
[WorkItem(546209, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546209")]
[Fact]
public void OverriddenMemberFromInternalType()
{
var source1 =
@"[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""B"")]
internal class A
{
public virtual void M() { }
public virtual object P { get { return null; } set { } }
}";
var compilation1 = CreateCompilation(source1, assemblyName: "A");
compilation1.VerifyDiagnostics();
var compilationVerifier = CompileAndVerify(compilation1);
var reference1 = MetadataReference.CreateFromImage(compilationVerifier.EmittedAssemblyData);
var source2 =
@"[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""C"")]
// Override none.
internal abstract class B0 : A
{
}
// Override both accessors.
internal abstract class B1 : A
{
public override void M() { }
public override object P { get { return null; } set { } }
}
// Override get only.
internal abstract class B2 : A
{
public override object P { get { return null; } }
}
// Override get only.
internal abstract class B3 : A
{
public override object P { set { } }
}";
var compilation2 = CreateCompilation(source2, assemblyName: "B", references: new[] { reference1 });
compilation2.VerifyDiagnostics();
compilationVerifier = CompileAndVerify(compilation2);
var reference2 = MetadataReference.CreateFromImage(compilationVerifier.EmittedAssemblyData);
var source3 =
@"class C
{
static void M(B0 b0, B1 b1, B2 b2, B3 b3)
{
object o;
b0.M();
b1.M();
o = b0.P;
b0.P = o;
o = b1.P;
b1.P = o;
o = b2.P;
b2.P = o;
o = b3.P;
b3.P = o;
}
}";
var compilation3 = CreateCompilation(source3, assemblyName: "C", references: new[] { reference1, reference2 });
compilation3.VerifyDiagnostics(
// (6,12): error CS0122: 'A.M()' is inaccessible due to its protection level
Diagnostic(ErrorCode.ERR_BadAccess, "M").WithArguments("A.M()").WithLocation(6, 12),
// (8,16): error CS0122: 'A.P' is inaccessible due to its protection level
Diagnostic(ErrorCode.ERR_BadAccess, "P").WithArguments("A.P").WithLocation(8, 16),
// (9,12): error CS0122: 'A.P' is inaccessible due to its protection level
Diagnostic(ErrorCode.ERR_BadAccess, "P").WithArguments("A.P").WithLocation(9, 12),
// (13,9): error CS0272: The property or indexer 'B2.P' cannot be used in this context because the set accessor is inaccessible
Diagnostic(ErrorCode.ERR_InaccessibleSetter, "b2.P").WithArguments("B2.P").WithLocation(13, 9),
// (14,13): error CS0271: The property or indexer 'B3.P' cannot be used in this context because the get accessor is inaccessible
Diagnostic(ErrorCode.ERR_InaccessibleGetter, "b3.P").WithArguments("B3.P").WithLocation(14, 13));
}
[WorkItem(546209, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546209")]
[Fact]
public void InternalOverriddenMember()
{
var source1 =
@"[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""B"")]
public abstract class A
{
internal abstract void M();
internal abstract object P { get; }
}";
var compilation1 = CreateCompilation(source1, assemblyName: "A");
compilation1.VerifyDiagnostics();
var compilationVerifier = CompileAndVerify(compilation1);
var reference1 = MetadataReference.CreateFromImage(compilationVerifier.EmittedAssemblyData);
var source2 =
@"[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""C"")]
public abstract class B : A
{
internal override abstract void M();
internal override abstract object P { get; }
}";
var compilation2 = CreateCompilation(source2, assemblyName: "B", references: new[] { reference1 });
compilation2.VerifyDiagnostics();
compilationVerifier = CompileAndVerify(compilation2);
var reference2 = MetadataReference.CreateFromImage(compilationVerifier.EmittedAssemblyData);
var source3 =
@"class C
{
static object M(B b)
{
b.M();
return b.P;
}
}";
var compilation3 = CreateCompilation(source3, assemblyName: "C", references: new[] { reference1, reference2 });
compilation3.VerifyDiagnostics();
}
[WorkItem(530360, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530360")]
[Fact]
public void InaccessibleReturnType()
{
var sourceA = @"
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""B"")]
internal class A
{
}
";
var compilationA = CreateCompilation(sourceA, assemblyName: "A");
var compilationVerifier = CompileAndVerify(compilationA);
var referenceA = MetadataReference.CreateFromImage(compilationVerifier.EmittedAssemblyData);
// Dev11 compiler doesn't allow this code, Roslyn does.
var sourceB = @"
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""C"")]
public class B
{
internal A M() { return null; }
}
";
var compilationB = CreateCompilation(sourceB, assemblyName: "B", references: new[] { referenceA });
compilationVerifier = CompileAndVerify(compilationB);
var referenceB = MetadataReference.CreateFromImage(compilationVerifier.EmittedAssemblyData);
var sourceC = @"
class C
{
static void M(B b)
{
b.M();
}
}
";
var compilationC = CreateCompilation(sourceC, assemblyName: "C", references: new[] { referenceA, referenceB });
compilationC.VerifyDiagnostics(
// (5,9): error CS0122: 'B.M()' is inaccessible due to its protection level
// b.M();
Diagnostic(ErrorCode.ERR_BadAccess, "b.M").WithArguments("B.M()"));
}
[WorkItem(530360, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530360")]
[Fact]
public void InaccessibleReturnType_Dynamic()
{
var sourceA = @"
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""B"")]
internal class A
{
}
";
var compilationA = CreateCompilation(sourceA, assemblyName: "A");
var compilationVerifier = CompileAndVerify(compilationA);
var referenceA = MetadataReference.CreateFromImage(compilationVerifier.EmittedAssemblyData);
var sourceB = @"
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""C"")]
public class B
{
internal A M(int a) { return null; }
}
";
var compilationB = CreateCompilation(sourceB, assemblyName: "B", references: new[] { referenceA });
compilationVerifier = CompileAndVerify(compilationB);
var referenceB = MetadataReference.CreateFromImage(compilationVerifier.EmittedAssemblyData);
var sourceC = @"
class C
{
static void M(B b, dynamic d)
{
b.M(d);
}
}
";
var compilationC = CreateCompilation(sourceC, assemblyName: "C", references: new[] { referenceA, referenceB });
compilationC.VerifyDiagnostics(
// (6,9): error CS0122: 'B.M(int)' is inaccessible due to its protection level
// b.M(d);
Diagnostic(ErrorCode.ERR_BadAccess, "b.M(d)").WithArguments("B.M(int)"));
}
[WorkItem(563573, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/563573")]
[Fact]
public void MissingIdentifier01()
{
var source =
@"class /*MyClass*/
{
internal protected class MyInner
{
public int MyMeth(MyInner2 arg)
{
return arg.intI;
}
}
internal protected class MyInner2
{
public int intI = 2;
}
public static int Main()
{
MyInner MI = new MyInner();
return MI.MyMeth(new MyInner2());
}
}";
CreateCompilation(source).GetDiagnostics();
}
[WorkItem(563563, "DevDiv"), WorkItem(563573, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/563573")]
[Fact]
public void MissingIdentifier02()
{
var source =
@"class /*MyClass*/
{
internal protected class MyInner
{
protected int MyMeth(MyInner2 arg)
{
return arg.intI;
}
}
internal protected class MyInner2
{
public int intI = 2;
}
public static int Main()
{
MyInner MI = new MyInner();
return MI.MyMeth(new MyInner2());
}
}";
CreateCompilation(source).GetDiagnostics();
}
[Fact]
[WorkItem(552452, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/552452")]
public void AccessTestInBadCode01()
{
var source =
@"///////////////
using System;
using System.Collections;
public static partial class Extensions
{
public static bool Test(this bool b) { return b; }
public static int Test(this int i) { return i; }
public static System.Object Test(this System.Object o) { return o; }
public static System.String Test(this System.String s) { return s; }
public static E Test(this E e) { return e; }
}
public struct S { }
public enum E { A, B, C }
public class Test { }
//
c class TestClass5 { }
[MyAttribue((object)((new S()).Test()))]
public clas TestClass2 { }
[MyAttribut(object) ((new E()).Test()))]
public class TestClass1 { }
///////////////";
CreateCompilation(source).GetDiagnostics();
}
[Fact, WorkItem(13652, "https://github.com/dotnet/roslyn/issues/13652")]
public void UnusedFieldInAbstractClassShouldTriggerWarning()
{
var text = @"
abstract class Class1
{
private int _UnusedField;
}";
CompileAndVerify(text).VerifyDiagnostics(
// (4,21): warning CS0169: The field 'Class1._UnusedField' is never used
// private int _UnusedField;
Diagnostic(ErrorCode.WRN_UnreferencedField, "_UnusedField").WithArguments("Class1._UnusedField").WithLocation(4, 17));
}
[Fact, WorkItem(13652, "https://github.com/dotnet/roslyn/issues/13652")]
public void AssignedButNotReadFieldInAbstractClassShouldTriggerWarning()
{
var text = @"
abstract class Class1
{
private int _AssignedButNotReadField;
public Class1()
{
_AssignedButNotReadField = 1;
}
}";
CompileAndVerify(text).VerifyDiagnostics(
// (4,21): warning CS0414: The field 'Class1._AssignedButNotReadField' is assigned but its value is never used
// private int _AssignedButNotReadField;
Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "_AssignedButNotReadField").WithArguments("Class1._AssignedButNotReadField").WithLocation(4, 17));
}
[Fact, WorkItem(13652, "https://github.com/dotnet/roslyn/issues/13652")]
public void UsedButNotAssignedFieldInAbstractClassShouldTriggerWarning()
{
var text = @"
internal abstract class Class1
{
protected int _UnAssignedField1;
public Class1()
{
System.Console.WriteLine(_UnAssignedField1);
}
}";
CompileAndVerify(text).VerifyDiagnostics(
// (4,18): warning CS0649: Field 'Class1._UnAssignedField1' is never assigned to, and will always have its default value 0
// internal int _UnAssignedField;
Diagnostic(ErrorCode.WRN_UnassignedInternalField, "_UnAssignedField1").WithArguments("Class1._UnAssignedField1", "0").WithLocation(4, 19));
}
[Fact, WorkItem(13652, "https://github.com/dotnet/roslyn/issues/13652")]
public void UsedButNotAssignedFieldInAbstractInternalClassWithIVTsShouldNotTriggerWarning()
{
var text = @"
[assembly:System.Runtime.CompilerServices.InternalsVisibleTo(""Test2.dll"")]
internal abstract class Class1
{
protected int _UnAssignedField1;
public Class1()
{
System.Console.WriteLine(_UnAssignedField1);
}
}";
CompileAndVerify(text).VerifyDiagnostics();
}
[Fact, WorkItem(13652, "https://github.com/dotnet/roslyn/issues/13652")]
public void UsedButNotAssignedFieldInAbstractPublicClassShouldNotTriggerWarning()
{
var text = @"
public abstract class Class1
{
protected int _UnAssignedField1;
public Class1()
{
System.Console.WriteLine(_UnAssignedField1);
}
}";
CompileAndVerify(text).VerifyDiagnostics();
}
[WorkItem(29253, "https://github.com/dotnet/roslyn/issues/29253")]
[Fact]
public void InaccessibleToUnnamedExe_01()
{
string sourceA =
@"class A { }";
var comp = CreateCompilation(sourceA);
var refA = comp.EmitToImageReference();
string sourceB =
@"class B
{
static void Main()
{
new A();
}
}";
// Unnamed assembly (the default from the command-line compiler).
comp = CreateCompilation(sourceB, references: new[] { refA }, options: TestOptions.ReleaseExe, assemblyName: null);
comp.VerifyDiagnostics(
// (5,13): error CS0122: 'A' is inaccessible due to its protection level
// new A();
Diagnostic(ErrorCode.ERR_BadAccess, "A").WithArguments("A").WithLocation(5, 13));
// Named assembly.
comp = CreateCompilation(sourceB, references: new[] { refA }, options: TestOptions.ReleaseExe, assemblyName: "B");
comp.VerifyDiagnostics(
// (5,13): error CS0122: 'A' is inaccessible due to its protection level
// new A();
Diagnostic(ErrorCode.ERR_BadAccess, "A").WithArguments("A").WithLocation(5, 13));
}
[WorkItem(29253, "https://github.com/dotnet/roslyn/issues/29253")]
[Fact]
public void InaccessibleToUnnamedExe_02()
{
string sourceA =
@"[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""B"")]
class A { }";
var comp = CreateCompilation(sourceA);
var refA = comp.EmitToImageReference();
string sourceB =
@"class B
{
static void Main()
{
new A();
}
}";
// Unnamed assembly (the default from the command-line compiler).
comp = CreateCompilation(sourceB, references: new[] { refA }, options: TestOptions.ReleaseExe, assemblyName: null);
comp.VerifyDiagnostics(
// (5,13): error CS0122: 'A' is inaccessible due to its protection level
// new A();
Diagnostic(ErrorCode.ERR_BadAccess, "A").WithArguments("A").WithLocation(5, 13));
// Named assembly.
comp = CreateCompilation(sourceB, references: new[] { refA }, options: TestOptions.ReleaseExe, assemblyName: "B");
comp.VerifyDiagnostics();
// Named assembly (distinct).
comp = CreateCompilation(sourceB, references: new[] { refA }, options: TestOptions.ReleaseExe, assemblyName: "B2");
comp.VerifyDiagnostics(
// (5,13): error CS0122: 'A' is inaccessible due to its protection level
// new A();
Diagnostic(ErrorCode.ERR_BadAccess, "A").WithArguments("A").WithLocation(5, 13));
}
[Fact]
public void FunctionPointerTypesFromOtherInaccessibleAssembly()
{
var comp = CreateCompilation(@"
unsafe class A
{
internal delegate*<A> ptr1;
internal delegate*<A, object> ptr2;
}", options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular9);
var ptr1 = comp.GetMember<FieldSymbol>("A.ptr1").Type.GetPublicSymbol();
var ptr2 = comp.GetMember<FieldSymbol>("A.ptr2").Type.GetPublicSymbol();
var comp2 = CreateCompilation("class B {}");
var b = comp2.GetMember("B").GetPublicSymbol();
Assert.Throws<ArgumentException>(() => ((Compilation)comp2).IsSymbolAccessibleWithin(ptr1, b));
Assert.Throws<ArgumentException>(() => ((Compilation)comp2).IsSymbolAccessibleWithin(ptr2, b));
}
}
}
|