提交 e6b31c1f 编写于 作者: O Omar Tawfik 提交者: Omar Tawfik

Adding IsConst modreq on ref readonly signatures

上级 ea0afa37
......@@ -57,6 +57,11 @@ internal override bool IsVolatileModifierType(PEModuleSymbol moduleSymbol, TypeS
return type.SpecialType == SpecialType.System_Runtime_CompilerServices_IsVolatile;
}
internal override bool IsConstModifierType(PEModuleSymbol moduleSymbol, TypeSymbol type)
{
return type.ToDisplayString() == WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsConst);
}
internal override TypeSymbol GetSZArrayTypeSymbol(PEModuleSymbol moduleSymbol, TypeSymbol elementType, ImmutableArray<ModifierInfo<TypeSymbol>> customModifiers)
{
if (elementType is UnsupportedMetadataTypeSymbol)
......
......@@ -63,7 +63,7 @@ public static bool HasRefOrOutParameter(this PropertySymbol property)
{
foreach (ParameterSymbol param in property.Parameters)
{
if (param.RefKind != RefKind.None)
if (param.RefKind == RefKind.Ref || param.RefKind == RefKind.Out)
{
return true;
}
......
......@@ -35,8 +35,7 @@ internal static class CustomModifierUtils
// have already been compared.
MethodSymbol constructedSourceMethod = sourceMethod.ConstructIfGeneric(destinationMethod.TypeArguments);
customModifiers = CustomModifiersTuple.Create(constructedSourceMethod.ReturnTypeCustomModifiers,
destinationMethod.ReturnsByRef ? constructedSourceMethod.RefCustomModifiers : ImmutableArray<CustomModifier>.Empty);
customModifiers = CustomModifiersTuple.Create(constructedSourceMethod.ReturnTypeCustomModifiers, constructedSourceMethod.RefCustomModifiers);
parameters = CopyParameterCustomModifiers(constructedSourceMethod.Parameters, destinationMethod.Parameters, alsoCopyParamsModifier);
......
......@@ -160,6 +160,7 @@ private void ComputeParameters()
arglistToken: out arglistToken,
allowRefOrOut: true,
allowThis: true,
shouldPlaceIsConstModifier: false,
diagnostics: diagnostics);
ParameterHelpers.EnsureIsReadOnlyAttributeExists(parameters, diagnostics, modifyCompilationForRefReadOnly: false);
......
......@@ -20,7 +20,8 @@ internal static class ParameterHelpers
out SyntaxToken arglistToken,
DiagnosticBag diagnostics,
bool allowRefOrOut,
bool allowThis)
bool allowThis,
bool shouldPlaceIsConstModifier)
{
arglistToken = default(SyntaxToken);
......@@ -90,6 +91,7 @@ internal static class ParameterHelpers
parameterIndex,
(paramsKeyword.Kind() != SyntaxKind.None),
parameterIndex == 0 && thisKeyword.Kind() != SyntaxKind.None,
shouldPlaceIsConstModifier,
diagnostics);
ReportParameterErrors(owner, parameterSyntax, parameter, firstDefault, diagnostics);
......
......@@ -83,6 +83,7 @@ protected override void MethodChecks(DiagnosticBag diagnostics)
bodyBinder, this, parameterList, out arglistToken,
allowRefOrOut: true,
allowThis: false,
shouldPlaceIsConstModifier: false,
diagnostics: diagnostics);
_lazyIsVararg = (arglistToken.Kind() == SyntaxKind.ArgListKeyword);
......
......@@ -249,6 +249,7 @@ private sealed class InvokeMethod : SourceDelegateMethodSymbol
binder, this, syntax.ParameterList, out arglistToken,
allowRefOrOut: true,
allowThis: false,
shouldPlaceIsConstModifier: false,
diagnostics: diagnostics);
if (arglistToken.Kind() == SyntaxKind.ArgListKeyword)
......
......@@ -167,6 +167,7 @@ private void MethodChecks(MethodDeclarationSyntax syntax, Binder withTypeParamsB
signatureBinder, this, syntax.ParameterList, out arglistToken,
allowRefOrOut: true,
allowThis: true,
shouldPlaceIsConstModifier: true,
diagnostics: diagnostics);
_lazyIsVararg = (arglistToken.Kind() == SyntaxKind.ArgListKeyword);
......@@ -320,11 +321,19 @@ private void MethodChecks(MethodDeclarationSyntax syntax, Binder withTypeParamsB
if ((object)overriddenMethod != null)
{
CustomModifierUtils.CopyMethodCustomModifiers(overriddenMethod, this, out _lazyReturnType,
out _lazyCustomModifiers,
CustomModifierUtils.CopyMethodCustomModifiers(overriddenMethod, this, out _lazyReturnType,
out _lazyCustomModifiers,
out _lazyParameters, alsoCopyParamsModifier: true);
}
}
else if (_refKind == RefKind.RefReadOnly && (this.IsVirtual || this.IsAbstract))
{
var isConst = withTypeParamsBinder.GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_IsConst, diagnostics, syntax);
_lazyCustomModifiers = CustomModifiersTuple.Create(
typeCustomModifiers: ImmutableArray<CustomModifier>.Empty,
refCustomModifiers: ImmutableArray.Create(CSharpCustomModifier.CreateRequired(isConst)));
}
}
else if ((object)_explicitInterfaceType != null)
{
......
......@@ -34,10 +34,12 @@ internal abstract class SourceParameterSymbol : SourceParameterSymbolBase
int ordinal,
bool isParams,
bool isExtensionMethodThis,
bool shouldPlaceIsConstModifier,
DiagnosticBag declarationDiagnostics)
{
var name = identifier.ValueText;
var locations = ImmutableArray.Create<Location>(new SourceLocation(identifier));
var location = new SourceLocation(identifier);
var locations = ImmutableArray.Create<Location>(location);
if (isParams)
{
......@@ -48,6 +50,25 @@ internal abstract class SourceParameterSymbol : SourceParameterSymbolBase
identifier.Parent.GetLocation());
}
if (shouldPlaceIsConstModifier && refKind == RefKind.RefReadOnly && (owner.IsVirtual || owner.IsAbstract))
{
var isConst = context.GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_IsConst, declarationDiagnostics, syntax);
return new SourceComplexParameterSymbolWithCustomModifiers(
owner,
ordinal,
parameterType,
refKind,
ImmutableArray<CustomModifier>.Empty,
ImmutableArray.Create(CSharpCustomModifier.CreateRequired(isConst)),
name,
locations,
syntax.GetReference(),
ConstantValue.Unset,
isParams,
isExtensionMethodThis);
}
if (!isParams &&
!isExtensionMethodThis &&
(syntax.Default == null) &&
......
......@@ -273,6 +273,14 @@ internal sealed class SourcePropertySymbol : PropertySymbol, IAttributeTargetSym
_lazyParameters = CustomModifierUtils.CopyParameterCustomModifiers(overriddenOrImplementedProperty.Parameters, _lazyParameters, alsoCopyParamsModifier: isOverride);
}
}
else if (_refKind == RefKind.RefReadOnly && (this.IsVirtual || this.IsAbstract))
{
var isConst = bodyBinder.GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_IsConst, diagnostics, syntax);
_customModifiers = CustomModifiersTuple.Create(
ImmutableArray<CustomModifier>.Empty,
ImmutableArray.Create(CSharpCustomModifier.CreateRequired(isConst)));
}
if (!hasAccessorList)
{
......@@ -792,6 +800,7 @@ private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, bool isExp
binder, owner, parameterSyntaxOpt, out arglistToken,
allowRefOrOut: false,
allowThis: false,
shouldPlaceIsConstModifier: true,
diagnostics: diagnostics);
if (arglistToken.Kind() != SyntaxKind.None)
......
......@@ -131,6 +131,7 @@ protected override void MethodChecks(DiagnosticBag diagnostics)
out arglistToken,
allowRefOrOut: true,
allowThis: false,
shouldPlaceIsConstModifier: false,
diagnostics: diagnostics);
if (arglistToken.Kind() == SyntaxKind.ArgListKeyword)
......
......@@ -158,6 +158,7 @@
<Compile Include="Emit\EntryPointTests.cs" />
<Compile Include="Emit\NoPiaEmbedTypes.cs" />
<Compile Include="Emit\OptionalArgumentsTests.cs" />
<Compile Include="Emit\IsConstModifierTests.cs" />
<Compile Include="Emit\ResourceTests.cs" />
<Compile Include="CodeGen\CodeGenScriptTests.cs" />
<Compile Include="PDB\CheckSumTest.cs" />
......
......@@ -672,33 +672,47 @@ private TypeSymbol GetTypeOfTypeDef(TypeDefinitionHandle typeDef, out bool isNoP
/// <exception cref="UnsupportedSignatureContent">If the encoded type is invalid.</exception>
/// <exception cref="BadImageFormatException">An exception from metadata reader.</exception>
private ImmutableArray<ModifierInfo<TypeSymbol>> DecodeModifiersOrThrow(ref BlobReader signatureReader, out SignatureTypeCode typeCode)
private ImmutableArray<ModifierInfo<TypeSymbol>> DecodeModifiersOrThrow(
ref BlobReader signatureReader,
out SignatureTypeCode typeCode,
Func<TypeSymbol, bool> acceptRequiredModifier = null)
{
ArrayBuilder<ModifierInfo<TypeSymbol>> modifiers = null;
for (;;)
{
typeCode = signatureReader.ReadSignatureTypeCode();
bool isOptional;
if (typeCode == SignatureTypeCode.RequiredModifier)
{
throw new UnsupportedSignatureContent();
isOptional = false;
}
else if (typeCode == SignatureTypeCode.OptionalModifier)
{
isOptional = true;
}
else
{
break;
}
TypeSymbol type = DecodeModifierTypeOrThrow(ref signatureReader);
if (typeCode == SignatureTypeCode.OptionalModifier)
// if it is a required modifier, make sure the compiler supports this modifier type
if (!isOptional && (acceptRequiredModifier == null || !acceptRequiredModifier(type)))
{
ModifierInfo<TypeSymbol> modifier = new ModifierInfo<TypeSymbol>(true, DecodeModifierTypeOrThrow(ref signatureReader));
throw new UnsupportedSignatureContent();
}
if (modifiers == null)
{
modifiers = ArrayBuilder<ModifierInfo<TypeSymbol>>.GetInstance();
}
ModifierInfo<TypeSymbol> modifier = new ModifierInfo<TypeSymbol>(isOptional, type);
modifiers.Add(modifier);
continue;
if (modifiers == null)
{
modifiers = ArrayBuilder<ModifierInfo<TypeSymbol>>.GetInstance();
}
break;
modifiers.Add(modifier);
}
return modifiers?.ToImmutableAndFree() ?? default(ImmutableArray<ModifierInfo<TypeSymbol>>);
......@@ -1095,15 +1109,26 @@ private void DecodeParameterOrThrow(ref BlobReader signatureReader, /*out*/ ref
{
bool refersToNoPiaLocalType;
var isConstFound = false;
SignatureTypeCode typeCode;
info.CustomModifiers = DecodeModifiersOrThrow(ref signatureReader, out typeCode);
info.CustomModifiers = DecodeModifiersOrThrow(ref signatureReader, out typeCode, acceptRequiredModifier: type =>
{
var isConst = IsConstModifierType(type);
isConstFound |= isConst;
return isConst;
});
if (typeCode == SignatureTypeCode.ByReference)
{
info.IsByRef = true;
info.RefCustomModifiers = info.CustomModifiers;
info.RefCustomModifiers = info.CustomModifiers;
info.CustomModifiers = DecodeModifiersOrThrow(ref signatureReader, out typeCode);
}
else if (isConstFound)
{
// This cannot be placed on CustomModifiers, just RefCustomModifiers
throw new UnsupportedSignatureContent();
}
info.Type = DecodeTypeOrThrow(ref signatureReader, typeCode, out refersToNoPiaLocalType);
}
......@@ -1844,60 +1869,17 @@ protected TypeSymbol DecodeFieldSignature(ref BlobReader signatureReader, out bo
try
{
// See if there is a Volatile modifier.
var isVolatileFound = false;
SignatureTypeCode typeCode;
ArrayBuilder<ModifierInfo<TypeSymbol>> customModifierBuilder = null;
for (;;)
customModifiers = DecodeModifiersOrThrow(ref signatureReader, out typeCode, acceptRequiredModifier: type =>
{
typeCode = signatureReader.ReadSignatureTypeCode();
var isTypeVolatile = this.IsVolatileModifierType(type);
isVolatileFound |= isTypeVolatile;
return isTypeVolatile;
});
if (typeCode == SignatureTypeCode.OptionalModifier ||
typeCode == SignatureTypeCode.RequiredModifier)
{
TypeSymbol type;
try
{
type = DecodeModifierTypeOrThrow(ref signatureReader);
}
catch (BadImageFormatException mrEx)
{
return GetUnsupportedMetadataTypeSymbol(mrEx); // an exception from metadata reader.
}
catch (UnsupportedSignatureContent)
{
return GetUnsupportedMetadataTypeSymbol(); // unsupported signature content
}
ModifierInfo<TypeSymbol> modifier = new ModifierInfo<TypeSymbol>((typeCode == SignatureTypeCode.OptionalModifier), type);
if (IsVolatileModifierType(modifier.Modifier))
{
isVolatile = true;
}
else if (!modifier.IsOptional)
{
return GetUnsupportedMetadataTypeSymbol(); // unsupported signature content
}
if (customModifierBuilder == null)
{
customModifierBuilder = ArrayBuilder<ModifierInfo<TypeSymbol>>.GetInstance();
}
customModifierBuilder.Add(modifier);
continue;
}
break;
}
if (customModifierBuilder != null)
{
customModifiers = customModifierBuilder.ToImmutableAndFree();
}
isVolatile = isVolatileFound;
// get the type
bool refersToNoPiaLocalType;
......
......@@ -41,6 +41,7 @@ internal abstract class SymbolFactory<ModuleSymbol, TypeSymbol>
internal abstract TypeSymbol GetEnumUnderlyingType(ModuleSymbol moduleSymbol, TypeSymbol type);
internal abstract bool IsVolatileModifierType(ModuleSymbol moduleSymbol, TypeSymbol type);
internal abstract bool IsConstModifierType(ModuleSymbol moduleSymbol, TypeSymbol type);
internal abstract Cci.PrimitiveTypeCode GetPrimitiveTypeCode(ModuleSymbol moduleSymbol, TypeSymbol type);
}
}
......@@ -92,6 +92,11 @@ protected bool IsVolatileModifierType(TypeSymbol type)
return _factory.IsVolatileModifierType(this.moduleSymbol, type);
}
protected bool IsConstModifierType(TypeSymbol type)
{
return _factory.IsConstModifierType(this.moduleSymbol, type);
}
protected Microsoft.Cci.PrimitiveTypeCode GetPrimitiveTypeCode(TypeSymbol type)
{
return _factory.GetPrimitiveTypeCode(this.moduleSymbol, type);
......
......@@ -273,6 +273,7 @@ public virtual void Visit(IMethodDefinition method)
{
this.Visit(method.GetReturnValueAttributes(Context));
this.Visit(method.ReturnValueCustomModifiers);
this.Visit(method.RefCustomModifiers);
if (method.HasDeclarativeSecurity)
{
......@@ -412,6 +413,7 @@ public virtual void Visit(IParameterDefinition parameterDefinition)
Debug.Assert((marshalling != null || !parameterDefinition.MarshallingDescriptor.IsDefaultOrEmpty) == parameterDefinition.IsMarshalledExplicitly);
this.Visit(parameterDefinition.GetAttributes(Context));
this.Visit(parameterDefinition.RefCustomModifiers);
this.Visit(parameterDefinition.CustomModifiers);
MetadataConstant defaultValue = parameterDefinition.GetDefaultValue(Context);
......
......@@ -267,6 +267,7 @@ internal enum WellKnownType
System_Runtime_CompilerServices_IsReadOnlyAttribute,
System_Runtime_CompilerServices_IsByRefLikeAttribute,
System_Runtime_CompilerServices_IsConst,
NextAvailable,
}
......@@ -529,6 +530,7 @@ internal static class WellKnownTypes
"System.Runtime.CompilerServices.IsReadOnlyAttribute",
"System.Runtime.CompilerServices.IsByRefLikeAttribute",
"System.Runtime.CompilerServices.IsConst",
};
private readonly static Dictionary<string, WellKnownType> s_nameToTypeIdMap = new Dictionary<string, WellKnownType>((int)Count);
......
......@@ -49,6 +49,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Return False
End Function
Friend Overrides Function IsConstModifierType(moduleSymbol As PEModuleSymbol, type As TypeSymbol) As Boolean
' VB doesn't deal with ref-readonly parameters or return-types.
Return False
End Function
Friend Overrides Function GetSZArrayTypeSymbol(moduleSymbol As PEModuleSymbol, elementType As TypeSymbol, customModifiers As ImmutableArray(Of ModifierInfo(Of TypeSymbol))) As TypeSymbol
If TypeOf elementType Is UnsupportedMetadataTypeSymbol Then
Return elementType
......
......@@ -4,6 +4,7 @@ Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports Microsoft.CodeAnalysis.CSharp
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
......@@ -107,5 +108,188 @@ End Class
CompileAndVerify(comp, expectedOutput:=<![CDATA[2]]>)
End Sub
<Fact>
Public Sub NonExtensibleReadOnlySignaturesAreRead()
Dim reference = CreateCSharpCompilation("
public class TestRef
{
public void M(ref readonly int x)
{
System.Console.WriteLine(x);
}
}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference()
Dim source =
<compilation>
<file>
Class Test
Shared Sub Main()
Dim x = 5
Dim obj = New TestRef()
obj.M(x)
End Sub
End Class
</file>
</compilation>
CompileAndVerify(source, additionalRefs:={reference}, expectedOutput:="5")
End Sub
<Fact>
Public Sub ExtensibleReadOnlySignaturesAreNotSupported_Methods_ReturnTypes()
Dim reference = CreateCSharpCompilation("
public class TestRef
{
private int value = 0;
public virtual ref readonly int M()
{
return ref value;
}
}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference()
Dim source =
<compilation>
<file>
Class Test
Shared Sub Main()
Dim obj = New TestRef()
Dim value = obj.M()
End Sub
End Class
</file>
</compilation>
Dim compilation = CreateCompilationWithMscorlib(source, references:={reference})
AssertTheseDiagnostics(compilation, <expected>
BC30657: 'M' has a return type that is not supported or parameter types that are not supported.
Dim value = obj.M()
~
</expected>)
End Sub
<Fact>
Public Sub ExtensibleReadOnlySignaturesAreNotSupported_Methods_Parameters()
Dim reference = CreateCSharpCompilation("
public class TestRef
{
public virtual void M(ref readonly int x)
{
System.Console.WriteLine(x);
}
}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference()
Dim source =
<compilation>
<file>
Class Test
Shared Sub Main()
Dim x = 5
Dim obj = New TestRef()
obj.M(x)
End Sub
End Class
</file>
</compilation>
Dim compilation = CreateCompilationWithMscorlib(source, references:={reference})
AssertTheseDiagnostics(compilation, <expected>
BC30657: 'M' has a return type that is not supported or parameter types that are not supported.
obj.M(x)
~
</expected>)
End Sub
<Fact>
Public Sub ExtensibleReadOnlySignaturesAreNotSupported_Properties()
Dim reference = CreateCSharpCompilation("
public class TestRef
{
private int value = 0;
public virtual ref readonly int P => ref value;
}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference()
Dim source =
<compilation>
<file>
Class Test
Shared Sub Main()
Dim obj = New TestRef()
Dim value = obj.P
End Sub
End Class
</file>
</compilation>
Dim compilation = CreateCompilationWithMscorlib(source, references:={reference})
AssertTheseDiagnostics(compilation, <expected>
BC30643: Property 'P' is of an unsupported type.
Dim value = obj.P
~
</expected>)
End Sub
<Fact>
Public Sub ExtensibleReadOnlySignaturesAreNotSupported_Indexers_ReturnTypes()
Dim reference = CreateCSharpCompilation("
public class TestRef
{
private int value = 0;
public virtual ref readonly int this[int p] => ref value;
}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference()
Dim source =
<compilation>
<file>
Class Test
Shared Sub Main()
Dim obj = New TestRef()
Dim value = obj(0)
End Sub
End Class
</file>
</compilation>
Dim compilation = CreateCompilationWithMscorlib(source, references:={reference})
AssertTheseDiagnostics(compilation, <expected>
BC30643: Property 'TestRef.Item(p As )' is of an unsupported type.
Dim value = obj(0)
~~~
</expected>)
End Sub
<Fact>
Public Sub ExtensibleReadOnlySignaturesAreNotSupported_Indexers_Parameters()
Dim reference = CreateCSharpCompilation("
public class TestRef
{
public virtual int this[ref readonly int p] => 0;
}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference()
Dim source =
<compilation>
<file>
Class Test
Shared Sub Main()
Dim p = 0
Dim obj = New TestRef()
Dim value = obj(p)
End Sub
End Class
</file>
</compilation>
Dim compilation = CreateCompilationWithMscorlib(source, references:={reference})
AssertTheseDiagnostics(compilation, <expected>
BC30643: Property 'TestRef.Item(p As )' is of an unsupported type.
Dim value = obj(p)
~~~
</expected>)
End Sub
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册