diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs index 151263831e7fecdd0084ebd5c7a59e81d6e02f56..0fb71e6c345dccc8c0a9afc6c72b7843f459c1ae 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs @@ -239,11 +239,13 @@ private bool IsFixedBuffer(out int fixedSize, out TypeSymbol fixedElementType) if (containingPEModule.Module.HasFixedBufferAttribute(_handle, out elementTypeName, out bufferSize)) { var decoder = new MetadataDecoder(containingPEModule); - var elementType = decoder.GetTypeSymbolForSerializedType(elementTypeName); - if (elementType.FixedBufferElementSizeInBytes() != 0) + var specialTypeName = MetadataHelpers.DecodeTypeName(elementTypeName).TopLevelType; + var specialType = SpecialTypes.GetTypeFromMetadataName(specialTypeName); + if (specialType != SpecialType.None && + specialType.FixedBufferElementSizeInBytes() != 0) { fixedSize = bufferSize; - fixedElementType = elementType; + fixedElementType = decoder.GetSpecialType(specialType); return true; } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs index f2970ac1de8b4f29daf7c42b1c911d15f55643d7..4ba2b09d2fe44d247f390bf59102f9eabd25bd12 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs @@ -36,6 +36,54 @@ private static string GetEscapedNewLine() #region Unsafe regions + [Fact] + public void FixedSizeBuffer() + { + var text1 = @" +using System; +using System.Runtime.InteropServices; + +public static class R +{ + public unsafe struct S + { + public fixed byte Buffer[16]; + } +}"; + var comp1 = CreateCompilation(text1, assemblyName: "assembly1", references: new[] { MscorlibRef_v20 }, + options: TestOptions.UnsafeDebugDll); + + var ref1 = comp1.EmitToImageReference(); + + var text2 = @" +using System; + +class C +{ + unsafe void M(byte* p) + { + R.S* p2 = (R.S*)p; + IntPtr p3 = M2((IntPtr)p2[0].Buffer); + } + + unsafe IntPtr M2(IntPtr p) => p; +}"; + var comp2 = CreateCompilationWithMscorlib45(text2, + references: new[] { ref1 }, + options: TestOptions.UnsafeDebugDll); + comp2.VerifyDiagnostics( + // warning CS1701: Assuming assembly reference 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' used by 'assembly1' matches identity 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' of 'mscorlib', you may need to supply runtime policy + Diagnostic(ErrorCode.WRN_UnifyReferenceMajMin).WithArguments("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "assembly1", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "mscorlib").WithLocation(1, 1), + // warning CS1701: Assuming assembly reference 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' used by 'assembly1' matches identity 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' of 'mscorlib', you may need to supply runtime policy + Diagnostic(ErrorCode.WRN_UnifyReferenceMajMin).WithArguments("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "assembly1", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "mscorlib").WithLocation(1, 1), + // warning CS1701: Assuming assembly reference 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' used by 'assembly1' matches identity 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' of 'mscorlib', you may need to supply runtime policy + Diagnostic(ErrorCode.WRN_UnifyReferenceMajMin).WithArguments("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "assembly1", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "mscorlib").WithLocation(1, 1), + // warning CS1701: Assuming assembly reference 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' used by 'assembly1' matches identity 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' of 'mscorlib', you may need to supply runtime policy + Diagnostic(ErrorCode.WRN_UnifyReferenceMajMin).WithArguments("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "assembly1", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "mscorlib").WithLocation(1, 1), + // warning CS1701: Assuming assembly reference 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' used by 'assembly1' matches identity 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' of 'mscorlib', you may need to supply runtime policy + Diagnostic(ErrorCode.WRN_UnifyReferenceMajMin).WithArguments("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "assembly1", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "mscorlib").WithLocation(1, 1)); + } + [Fact] public void CompilationNotUnsafe1() { diff --git a/src/Compilers/Core/Portable/MetadataReader/TypeNameDecoder.cs b/src/Compilers/Core/Portable/MetadataReader/TypeNameDecoder.cs index 5c4ada00fd2cd140dd4b197c661ce6882b1e6a7a..e4464e1e0a66eb477dbd21b416cb9ee8dbf4b5e0 100644 --- a/src/Compilers/Core/Portable/MetadataReader/TypeNameDecoder.cs +++ b/src/Compilers/Core/Portable/MetadataReader/TypeNameDecoder.cs @@ -70,7 +70,7 @@ protected TypeSymbol MakePointerTypeSymbol(TypeSymbol type, ImmutableArray 1+2;$$ +"; + + var expected = @"using System; +class Class +{ + public int Three => 1 + 2; +"; + + AutoFormatOnSemicolon(code, expected, SyntaxKind.OpenBraceToken); + } + [Fact] [Trait(Traits.Feature, Traits.Features.SmartTokenFormatting)] public void EmbeddedStatement10() diff --git a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/MissingAssemblyTests.cs b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/MissingAssemblyTests.cs index 8528f4f9db316e93bba528f2db31c774cd7642dd..3fccae1f21b529b8eef95b4e67df0ce9ae5dc0e7 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/MissingAssemblyTests.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/MissingAssemblyTests.cs @@ -13,6 +13,7 @@ using System.Runtime.InteropServices; using Xunit; using Roslyn.Test.PdbUtilities; +using Microsoft.CodeAnalysis.CSharp.Symbols; namespace Microsoft.CodeAnalysis.CSharp.UnitTests { @@ -609,8 +610,70 @@ void M() out errorMessage); Assert.Equal(2, numRetries); // Ensure that we actually retried and that we bailed out on the second retry if the same identity was seen in the diagnostics. - Assert.Equal($"error CS0012: The type 'MissingType' is defined in an assembly that is not referenced. You must add a reference to assembly '{missingIdentity}'.", errorMessage); - } + Assert.Equal($"error CS0012: The type 'MissingType' is defined in an assembly that is not referenced. You must add a reference to assembly '{missingIdentity}'.", errorMessage); + } + + [WorkItem(1151888)] + [Fact] + public void SucceedOnRetry() + { + var source = @" +class C +{ + void M() + { + } +}"; + var comp = CreateCompilationWithMscorlib(source); + var runtime = CreateRuntimeInstance(comp); + var context = CreateMethodContext(runtime, "C.M"); + + var missingModule = runtime.Modules.First(); + var missingIdentity = missingModule.MetadataReader.ReadAssemblyIdentityOrThrow(); + + var shouldSucceed = false; + string errorMessage; + var compileResult = ExpressionCompilerTestHelpers.CompileExpressionWithRetry( + runtime.Modules.Select(m => m.MetadataBlock).ToImmutableArray(), + context, + (_, diagnostics) => + { + if (shouldSucceed) + { + return TestCompileResult.Instance; + } + else + { + shouldSucceed = true; + diagnostics.Add(new CSDiagnostic(new CSDiagnosticInfo(ErrorCode.ERR_NoTypeDef, "MissingType", missingIdentity), Location.None)); + return null; + } + }, + (AssemblyIdentity assemblyIdentity, out uint uSize) => + { + uSize = (uint)missingModule.MetadataLength; + return missingModule.MetadataAddress; + }, + out errorMessage); + + Assert.Same(TestCompileResult.Instance, compileResult); + Assert.Null(errorMessage); + } + + private sealed class TestCompileResult : CompileResult + { + public static readonly CompileResult Instance = new TestCompileResult(); + + private TestCompileResult() + : base(null, null, null, null) + { + } + + public override CustomTypeInfo GetCustomTypeInfo() + { + throw new NotImplementedException(); + } + } private EvaluationContext CreateMethodContextWithReferences(Compilation comp, string methodName, params MetadataReference[] references) { diff --git a/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/EvaluationContextBase.cs b/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/EvaluationContextBase.cs index 85a2b5e107b7085202c32fddf0701cb670c2b652..8f018b92dda4affc31b8e70177fc51d21ef80d23 100644 --- a/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/EvaluationContextBase.cs +++ b/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/EvaluationContextBase.cs @@ -21,39 +21,6 @@ internal abstract class EvaluationContextBase internal static readonly AssemblyIdentity SystemXmlLinqIdentity = new AssemblyIdentity("System.Xml.Linq"); internal static readonly AssemblyIdentity MicrosoftVisualBasicIdentity = new AssemblyIdentity("Microsoft.VisualBasic"); - /// - /// Compile C# expression and emit assembly with evaluation method. - /// - /// - /// Result containing generated assembly, type and method names, and any format specifiers. - /// - internal CompileResult CompileExpression( - InspectionContext inspectionContext, - string expr, - DkmEvaluationFlags compilationFlags, - DiagnosticFormatter formatter, - out ResultProperties resultProperties, - out string error, - out ImmutableArray missingAssemblyIdentities, - CultureInfo preferredUICulture, - CompilationTestData testData) - { - var diagnostics = DiagnosticBag.GetInstance(); - var result = this.CompileExpression(inspectionContext, expr, compilationFlags, diagnostics, out resultProperties, testData); - if (diagnostics.HasAnyErrors()) - { - bool useReferencedModulesOnly; - error = GetErrorMessageAndMissingAssemblyIdentities(diagnostics, formatter, preferredUICulture, out useReferencedModulesOnly, out missingAssemblyIdentities); - } - else - { - error = null; - missingAssemblyIdentities = ImmutableArray.Empty; - } - diagnostics.Free(); - return result; - } - internal abstract CompileResult CompileExpression( InspectionContext inspectionContext, string expr, diff --git a/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/ExpressionCompiler.cs b/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/ExpressionCompiler.cs index 96bc15d2b726bbac8213d3ab055ffae602f80921..dede9cdca51addd80c4e5a63b6b9ed1290fb28e9 100644 --- a/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/ExpressionCompiler.cs +++ b/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/ExpressionCompiler.cs @@ -292,13 +292,14 @@ private EvaluationContextBase CreateMethodContext(DkmClrInstructionAddress instr DkmUtilities.GetMetadataBytesPtrFunction getMetaDataBytesPtr, out string errorMessage) { - errorMessage = null; TResult compileResult; PooledHashSet assembliesLoadedInRetryLoop = null; bool tryAgain; do { + errorMessage = null; + var context = createContext(metadataBlocks, useReferencedModulesOnly: false); var diagnostics = DiagnosticBag.GetInstance(); compileResult = compile(context, diagnostics); diff --git a/src/ExpressionEvaluator/Core/Test/ExpressionCompiler/ExpressionCompilerTestHelpers.cs b/src/ExpressionEvaluator/Core/Test/ExpressionCompiler/ExpressionCompilerTestHelpers.cs index 8d94b1f32121f5427b8cf00fb28896cd1c8cbd7b..e93f2b0593d3bc7498ce2b1ac0547bf4bea575cf 100644 --- a/src/ExpressionEvaluator/Core/Test/ExpressionCompiler/ExpressionCompilerTestHelpers.cs +++ b/src/ExpressionEvaluator/Core/Test/ExpressionCompiler/ExpressionCompilerTestHelpers.cs @@ -106,6 +106,40 @@ internal static class ExpressionCompilerTestHelpers return result; } + /// + /// Compile C# expression and emit assembly with evaluation method. + /// + /// + /// Result containing generated assembly, type and method names, and any format specifiers. + /// + static internal CompileResult CompileExpression( + this EvaluationContextBase evaluationContext, + InspectionContext inspectionContext, + string expr, + DkmEvaluationFlags compilationFlags, + DiagnosticFormatter formatter, + out ResultProperties resultProperties, + out string error, + out ImmutableArray missingAssemblyIdentities, + CultureInfo preferredUICulture, + CompilationTestData testData) + { + var diagnostics = DiagnosticBag.GetInstance(); + var result = evaluationContext.CompileExpression(inspectionContext, expr, compilationFlags, diagnostics, out resultProperties, testData); + if (diagnostics.HasAnyErrors()) + { + bool useReferencedModulesOnly; + error = evaluationContext.GetErrorMessageAndMissingAssemblyIdentities(diagnostics, formatter, preferredUICulture, out useReferencedModulesOnly, out missingAssemblyIdentities); + } + else + { + error = null; + missingAssemblyIdentities = ImmutableArray.Empty; + } + diagnostics.Free(); + return result; + } + internal static CompileResult CompileExpressionWithRetry( ImmutableArray metadataBlocks, EvaluationContextBase context, diff --git a/src/Workspaces/CSharp/Portable/Utilities/FormattingRangeHelper.cs b/src/Workspaces/CSharp/Portable/Utilities/FormattingRangeHelper.cs index 30e99f907ff53984ac305cf2699770497d8fe0e7..b61c881133eaf3dfa7dbf25bbbe9a742e5243c03 100644 --- a/src/Workspaces/CSharp/Portable/Utilities/FormattingRangeHelper.cs +++ b/src/Workspaces/CSharp/Portable/Utilities/FormattingRangeHelper.cs @@ -121,7 +121,8 @@ internal static class FormattingRangeHelper (parent is DelegateDeclarationSyntax) || (parent is FieldDeclarationSyntax) || (parent is EventFieldDeclarationSyntax) || - (parent is MethodDeclarationSyntax)) + (parent is MethodDeclarationSyntax) || + (parent is PropertyDeclarationSyntax)) { return ValueTuple.Create(GetAppropriatePreviousToken(parent.GetFirstToken(), canTokenBeFirstInABlock: true), parent.GetLastToken()); }