未验证 提交 b4cad279 编写于 作者: N Neal Gafter 提交者: GitHub

Bind some syntax nodes even in error recovery scenarios. (#38348)

Fixes #27060
上级 007022c3
......@@ -2857,6 +2857,7 @@ internal static bool CheckValEscape(SyntaxNode node, BoundExpression expr, uint
// returning "false" seems safer than throwing.
// we will still assert to make sure that all nodes are accounted for.
Debug.Assert(false, $"{expr.Kind} expression of {expr.Type} type");
diagnostics.Add(ErrorCode.ERR_InternalError, node.Location);
return false;
#region "cannot produce ref-like values"
......
......@@ -660,6 +660,7 @@ private BoundExpression BindExpressionInternal(ExpressionSyntax node, Diagnostic
// that a non-parser syntax tree could reach this point with an unexpected
// SyntaxKind and we don't want to throw if that occurs.
Debug.Assert(false, "Unexpected SyntaxKind " + node.Kind());
diagnostics.Add(ErrorCode.ERR_InternalError, node.Location);
return BadExpression(node);
}
}
......@@ -5083,12 +5084,8 @@ private BoundExpression BindInterfaceCreationExpression(ObjectCreationExpression
private BoundExpression BindBadInterfaceCreationExpression(ObjectCreationExpressionSyntax node, NamedTypeSymbol type, DiagnosticBag diagnostics)
{
AnalyzedArguments analyzedArguments = AnalyzedArguments.GetInstance();
BindArgumentsAndNames(node.ArgumentList, diagnostics, analyzedArguments);
ImmutableArray<BoundExpression> childNodes = BuildArgumentsForErrorRecovery(analyzedArguments);
BoundExpression result = new BoundBadExpression(node, LookupResultKind.NotCreatable, ImmutableArray.Create<Symbol>(type), childNodes, type);
analyzedArguments.Free();
return result;
return MakeBadExpressionForObjectCreation(node, type, analyzedArguments, diagnostics);
}
private BoundExpression BindComImportCoClassCreationExpression(ObjectCreationExpressionSyntax node, NamedTypeSymbol interfaceType, NamedTypeSymbol coClassType, DiagnosticBag diagnostics)
......
......@@ -1967,6 +1967,7 @@ internal BoundExpression GenerateConversionForAssignment(TypeSymbol targetType,
// UNDONE: LambdaConversionResult.VoidExpressionLambdaMustBeStatementExpression:
Debug.Assert(false, "Missing case in lambda conversion error reporting");
diagnostics.Add(ErrorCode.ERR_InternalError, syntax.Location);
}
protected static void GenerateImplicitConversionError(DiagnosticBag diagnostics, Compilation compilation, SyntaxNode syntax,
......
......@@ -34,6 +34,7 @@ internal CSharpAttributeData GetAttribute(AttributeSyntax node, NamedTypeSymbol
internal new CSharpAttributeData GetAttribute(AttributeSyntax node, NamedTypeSymbol boundAttributeType, DiagnosticBag diagnostics)
{
Debug.Assert(false, "Don't call this overload.");
diagnostics.Add(ErrorCode.ERR_InternalError, node.Location);
return base.GetAttribute(node, boundAttributeType, diagnostics);
}
......
......@@ -327,6 +327,7 @@ private static bool ReportConflictWithParameter(Symbol parameter, Symbol newSymb
}
Debug.Assert(false, "what else could be defined in a method?");
diagnostics.Add(ErrorCode.ERR_InternalError, newLocation);
return true;
}
......
......@@ -509,6 +509,7 @@ private bool ReportConflictWithLocal(Symbol local, Symbol newSymbol, string name
}
Debug.Assert(false, "what else can be declared inside a local scope?");
diagnostics.Add(ErrorCode.ERR_InternalError, newLocation);
return false;
}
......
......@@ -148,6 +148,7 @@ private static bool ReportConflictWithParameter(ParameterSymbol parameter, Symbo
}
Debug.Assert(false, "what else could be defined in a lambda?");
diagnostics.Add(ErrorCode.ERR_InternalError, newLocation);
return false;
}
......
......@@ -5973,6 +5973,15 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to Internal error in the C# compiler..
/// </summary>
internal static string ERR_InternalError {
get {
return ResourceManager.GetString("ERR_InternalError", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Embedded interop method &apos;{0}&apos; contains a body..
/// </summary>
......
......@@ -5930,4 +5930,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_ReAbstractionInNoPIAType" xml:space="preserve">
<value>Type '{0}' cannot be embedded because it has a re-abstraction of a member from base interface. Consider setting the 'Embed Interop Types' property to false.</value>
</data>
<data name="ERR_InternalError" xml:space="preserve">
<value>Internal error in the C# compiler.</value>
</data>
</root>
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Roslyn.Utilities;
using System;
using System.Diagnostics;
namespace Microsoft.CodeAnalysis.CSharp
{
......@@ -32,6 +32,8 @@ internal CSDiagnosticInfo(ErrorCode code, ImmutableArray<Symbol> symbols, object
internal CSDiagnosticInfo(ErrorCode code, object[] args, ImmutableArray<Symbol> symbols, ImmutableArray<Location> additionalLocations)
: base(code, args, symbols)
{
// Internal errors are abnormal and should not occur except where there are bugs in the compiler.
Debug.Assert(code != ErrorCode.ERR_InternalError);
_additionalLocations = additionalLocations;
}
......
......@@ -1732,6 +1732,8 @@ internal enum ErrorCode
#endregion diagnostics introduced for C# 8.0
ERR_InternalError = 8751,
// Note: you will need to re-generate compiler code after adding warnings (eng\generate-compiler-code.cmd)
}
}
......@@ -890,6 +890,7 @@ protected void RestorePending(SavedPending oldPending)
public override BoundNode DefaultVisit(BoundNode node)
{
Debug.Assert(false, $"Should Visit{node.Kind} be overridden in {this.GetType().Name}?");
Diagnostics.Add(ErrorCode.ERR_InternalError, node.Syntax.Location);
return null;
}
......
......@@ -227,6 +227,11 @@
<target state="translated">{0} nemůže implementovat člen rozhraní {1} v typu {2}, protože má parametr __arglist.</target>
<note />
</trans-unit>
<trans-unit id="ERR_InternalError">
<source>Internal error in the C# compiler.</source>
<target state="new">Internal error in the C# compiler.</target>
<note />
</trans-unit>
<trans-unit id="ERR_InvalidHashAlgorithmName">
<source>Invalid hash algorithm name: '{0}'</source>
<target state="translated">Neplatný název algoritmu hash: {0}</target>
......
......@@ -227,6 +227,11 @@
<target state="translated">"{0}" kann den Schnittstellenmember "{1}" in Typ "{2}" nicht implementieren, weil er einen __arglist-Parameter umfasst.</target>
<note />
</trans-unit>
<trans-unit id="ERR_InternalError">
<source>Internal error in the C# compiler.</source>
<target state="new">Internal error in the C# compiler.</target>
<note />
</trans-unit>
<trans-unit id="ERR_InvalidHashAlgorithmName">
<source>Invalid hash algorithm name: '{0}'</source>
<target state="translated">Ungültiger Name für Hashalgorithmus: "{0}"</target>
......
......@@ -227,6 +227,11 @@
<target state="translated">“{0}” no puede implementar el miembro de interfaz “{1}” en el tipo “{2}” porque tiene un parámetro __arglist</target>
<note />
</trans-unit>
<trans-unit id="ERR_InternalError">
<source>Internal error in the C# compiler.</source>
<target state="new">Internal error in the C# compiler.</target>
<note />
</trans-unit>
<trans-unit id="ERR_InvalidHashAlgorithmName">
<source>Invalid hash algorithm name: '{0}'</source>
<target state="translated">Nombre de algoritmo hash no válido: "{0}"</target>
......
......@@ -227,6 +227,11 @@
<target state="translated">'{0}' ne peut pas implémenter le membre d'interface '{1}' dans le type '{2}', car il a un paramètre __arglist</target>
<note />
</trans-unit>
<trans-unit id="ERR_InternalError">
<source>Internal error in the C# compiler.</source>
<target state="new">Internal error in the C# compiler.</target>
<note />
</trans-unit>
<trans-unit id="ERR_InvalidHashAlgorithmName">
<source>Invalid hash algorithm name: '{0}'</source>
<target state="translated">Nom d'algorithme de hachage non valide : '{0}'</target>
......
......@@ -227,6 +227,11 @@
<target state="translated">'{0}' non può implementare il membro di interfaccia '{1}' nel tipo '{2}' perché contiene un parametro __arglist</target>
<note />
</trans-unit>
<trans-unit id="ERR_InternalError">
<source>Internal error in the C# compiler.</source>
<target state="new">Internal error in the C# compiler.</target>
<note />
</trans-unit>
<trans-unit id="ERR_InvalidHashAlgorithmName">
<source>Invalid hash algorithm name: '{0}'</source>
<target state="translated">Il nome dell'algoritmo hash non è valido: '{0}'</target>
......
......@@ -227,6 +227,11 @@
<target state="translated">'{0}' は、__arglist パラメーターが指定されているため、型 '{2}' のインターフェイス メンバー '{1}' を実装できません</target>
<note />
</trans-unit>
<trans-unit id="ERR_InternalError">
<source>Internal error in the C# compiler.</source>
<target state="new">Internal error in the C# compiler.</target>
<note />
</trans-unit>
<trans-unit id="ERR_InvalidHashAlgorithmName">
<source>Invalid hash algorithm name: '{0}'</source>
<target state="translated">無効なハッシュ アルゴリズム名: '{0}'</target>
......
......@@ -227,6 +227,11 @@
<target state="translated">'{0}'은(는) __arglist 매개 변수가 있으므로 '{2}' 형식의 인터페이스 멤버 '{1}'을(를) 구현할 수 없습니다.</target>
<note />
</trans-unit>
<trans-unit id="ERR_InternalError">
<source>Internal error in the C# compiler.</source>
<target state="new">Internal error in the C# compiler.</target>
<note />
</trans-unit>
<trans-unit id="ERR_InvalidHashAlgorithmName">
<source>Invalid hash algorithm name: '{0}'</source>
<target state="translated">잘못된 해시 알고리즘 이름: '{0}'</target>
......
......@@ -227,6 +227,11 @@
<target state="translated">Obiekt „{0}” nie może implementować elementu członkowskiego interfejsu „{1}” w ramach typu „{2}”, ponieważ zawiera on parametr __arglist</target>
<note />
</trans-unit>
<trans-unit id="ERR_InternalError">
<source>Internal error in the C# compiler.</source>
<target state="new">Internal error in the C# compiler.</target>
<note />
</trans-unit>
<trans-unit id="ERR_InvalidHashAlgorithmName">
<source>Invalid hash algorithm name: '{0}'</source>
<target state="translated">Nieprawidłowa nazwa algorytmu wyznaczania wartości skrótu: „{0}”</target>
......
......@@ -227,6 +227,11 @@
<target state="translated">'{0}' não pode implementar o membro de interface '{1}' no tipo '{2}' porque tem um parâmetro __arglist</target>
<note />
</trans-unit>
<trans-unit id="ERR_InternalError">
<source>Internal error in the C# compiler.</source>
<target state="new">Internal error in the C# compiler.</target>
<note />
</trans-unit>
<trans-unit id="ERR_InvalidHashAlgorithmName">
<source>Invalid hash algorithm name: '{0}'</source>
<target state="translated">Nome de algoritmo de hash inválido: '{0}'</target>
......
......@@ -227,6 +227,11 @@
<target state="translated">"{0}" не может реализовать член интерфейса "{1}" в типе "{2}" из-за наличия параметра __arglist</target>
<note />
</trans-unit>
<trans-unit id="ERR_InternalError">
<source>Internal error in the C# compiler.</source>
<target state="new">Internal error in the C# compiler.</target>
<note />
</trans-unit>
<trans-unit id="ERR_InvalidHashAlgorithmName">
<source>Invalid hash algorithm name: '{0}'</source>
<target state="translated">Недопустимое имя хэш-алгоритма: "{0}"</target>
......
......@@ -227,6 +227,11 @@
<target state="translated">'{0}' bir __arglist parametresine sahip olduğundan '{2}' türünde '{1}' arabirim üyesini uygulayamıyor.</target>
<note />
</trans-unit>
<trans-unit id="ERR_InternalError">
<source>Internal error in the C# compiler.</source>
<target state="new">Internal error in the C# compiler.</target>
<note />
</trans-unit>
<trans-unit id="ERR_InvalidHashAlgorithmName">
<source>Invalid hash algorithm name: '{0}'</source>
<target state="translated">Geçersiz karma algoritması adı: '{0}'</target>
......
......@@ -232,6 +232,11 @@
<target state="translated">“{0}”无法在类型“{2}”中实现接口成员“{1}”,因为它具有 __arglist 参数</target>
<note />
</trans-unit>
<trans-unit id="ERR_InternalError">
<source>Internal error in the C# compiler.</source>
<target state="new">Internal error in the C# compiler.</target>
<note />
</trans-unit>
<trans-unit id="ERR_InvalidHashAlgorithmName">
<source>Invalid hash algorithm name: '{0}'</source>
<target state="translated">无效的哈希算法名称:“{0}”</target>
......
......@@ -227,6 +227,11 @@
<target state="translated">因為介面成員 '{1}' 包含 __arglist 參數,所以 '{0}' 無法在類型 '{2}' 中實作此介面成員</target>
<note />
</trans-unit>
<trans-unit id="ERR_InternalError">
<source>Internal error in the C# compiler.</source>
<target state="new">Internal error in the C# compiler.</target>
<note />
</trans-unit>
<trans-unit id="ERR_InvalidHashAlgorithmName">
<source>Invalid hash algorithm name: '{0}'</source>
<target state="translated">雜湊演算法名稱無效: '{0}'</target>
......
......@@ -1194,8 +1194,10 @@ public static void Main()
}
";
string expectedOperationTree = @"
IInvalidOperation (OperationKind.Invalid, Type: I, IsInvalid) (Syntax: 'new I() { }')
Children(0)
IInvalidOperation (OperationKind.Invalid, Type: I, IsInvalid) (Syntax: 'new I() { }')
Children(1):
IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: I, IsInvalid) (Syntax: '{ }')
Initializers(0)
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0144: Cannot create an instance of the abstract class or interface 'I'
......@@ -3934,5 +3936,152 @@ public static void Main()
Assert.Null(semanticModel.GetTypeInfo(name).Type);
}
}
[WorkItem(27060, "https://github.com/dotnet/roslyn/issues/27060")]
[Fact]
public void GetTypeInfoForBadExpression_01()
{
var source = @"
using System.Collections.Generic;
class C
{
void M()
{
I i = new I() { 1, 2 }
}
}
interface I : IEnumerable<int>
{
void Add(int i);
}";
var compilation = CreateCompilation(source);
compilation.VerifyDiagnostics(
// (8,15): error CS0144: Cannot create an instance of the abstract class or interface 'I'
// I i = new I() { 1, 2 }
Diagnostic(ErrorCode.ERR_NoNewAbstract, "new I() { 1, 2 }").WithArguments("I").WithLocation(8, 15),
// (8,31): error CS1002: ; expected
// I i = new I() { 1, 2 }
Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(8, 31)
);
var tree = compilation.SyntaxTrees.Single();
var semanticModel = compilation.GetSemanticModel(tree);
var node1 = tree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().First();
compilation.VerifyOperationTree(node1, expectedOperationTree:
@"
IMethodBodyOperation (OperationKind.MethodBody, Type: null, IsInvalid) (Syntax: 'void M() ... }')
BlockBody:
IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{ ... }')
Locals: Local_1: I i
IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsInvalid) (Syntax: 'I i = new I() { 1, 2 }')
IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null, IsInvalid) (Syntax: 'I i = new I() { 1, 2 }')
Declarators:
IVariableDeclaratorOperation (Symbol: I i) (OperationKind.VariableDeclarator, Type: null, IsInvalid) (Syntax: 'i = new I() { 1, 2 }')
Initializer:
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null, IsInvalid) (Syntax: '= new I() { 1, 2 }')
IInvalidOperation (OperationKind.Invalid, Type: I, IsInvalid) (Syntax: 'new I() { 1, 2 }')
Children(1):
IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: I, IsInvalid) (Syntax: '{ 1, 2 }')
Initializers(2):
IInvocationOperation (virtual void I.Add(System.Int32 i)) (OperationKind.Invocation, Type: System.Void, IsInvalid, IsImplicit) (Syntax: '1')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: I, IsInvalid, IsImplicit) (Syntax: 'I')
Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i) (OperationKind.Argument, Type: null, IsInvalid, IsImplicit) (Syntax: '1')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
IInvocationOperation (virtual void I.Add(System.Int32 i)) (OperationKind.Invocation, Type: System.Void, IsInvalid, IsImplicit) (Syntax: '2')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: I, IsInvalid, IsImplicit) (Syntax: 'I')
Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i) (OperationKind.Argument, Type: null, IsInvalid, IsImplicit) (Syntax: '2')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsInvalid) (Syntax: '2')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Initializer:
null
ExpressionBody:
null
");
var nodes = tree.GetRoot().DescendantNodes().OfType<LiteralExpressionSyntax>().Where(n => n.ToString() == "2");
var node = nodes.First();
var typeInfo = semanticModel.GetTypeInfo(node);
Assert.Equal(SpecialType.System_Int32, typeInfo.Type.SpecialType);
Assert.Equal(SpecialType.System_Int32, typeInfo.ConvertedType.SpecialType);
}
[WorkItem(27060, "https://github.com/dotnet/roslyn/issues/27060")]
[Fact]
public void GetTypeInfoForBadExpression_02()
{
var source = @"
using System.Collections.Generic;
class C
{
void M()
{
var x = new I[] { 1, 2 }
}
}
interface I : IEnumerable<int>
{
void Add(int i);
}";
var compilation = CreateCompilation(source);
compilation.VerifyDiagnostics(
// (8,27): error CS0029: Cannot implicitly convert type 'int' to 'I'
// var x = new I[] { 1, 2 }
Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "I").WithLocation(8, 27),
// (8,30): error CS0029: Cannot implicitly convert type 'int' to 'I'
// var x = new I[] { 1, 2 }
Diagnostic(ErrorCode.ERR_NoImplicitConv, "2").WithArguments("int", "I").WithLocation(8, 30),
// (8,33): error CS1002: ; expected
// var x = new I[] { 1, 2 }
Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(8, 33)
);
var tree = compilation.SyntaxTrees.Single();
var semanticModel = compilation.GetSemanticModel(tree);
var node1 = tree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().First();
compilation.VerifyOperationTree(node1, expectedOperationTree:
@"
IMethodBodyOperation (OperationKind.MethodBody, Type: null, IsInvalid) (Syntax: 'void M() ... }')
BlockBody:
IBlockOperation (1 statements, 1 locals) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{ ... }')
Locals: Local_1: I[] x
IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsInvalid) (Syntax: 'var x = new I[] { 1, 2 }')
IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null, IsInvalid) (Syntax: 'var x = new I[] { 1, 2 }')
Declarators:
IVariableDeclaratorOperation (Symbol: I[] x) (OperationKind.VariableDeclarator, Type: null, IsInvalid) (Syntax: 'x = new I[] { 1, 2 }')
Initializer:
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null, IsInvalid) (Syntax: '= new I[] { 1, 2 }')
IArrayCreationOperation (OperationKind.ArrayCreation, Type: I[], IsInvalid) (Syntax: 'new I[] { 1, 2 }')
Dimension Sizes(1):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsInvalid, IsImplicit) (Syntax: 'new I[] { 1, 2 }')
Initializer:
IArrayInitializerOperation (2 elements) (OperationKind.ArrayInitializer, Type: null, IsInvalid) (Syntax: '{ 1, 2 }')
Element Values(2):
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: I, IsInvalid, IsImplicit) (Syntax: '1')
Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: I, IsInvalid, IsImplicit) (Syntax: '2')
Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsInvalid) (Syntax: '2')
Initializer:
null
ExpressionBody:
null
");
var nodes = tree.GetRoot().DescendantNodes().OfType<LiteralExpressionSyntax>().Where(n => n.ToString() == "2");
var node = nodes.First();
var typeInfo = semanticModel.GetTypeInfo(node);
Assert.Equal(SpecialType.System_Int32, typeInfo.Type.SpecialType);
Assert.Equal("I", typeInfo.ConvertedType.ToDisplayString());
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册