提交 06fbf5a5 编写于 作者: M Manish Vasani

Merge remote-tracking branch 'upstream/master' into RemoveIOpFlag

......@@ -187,16 +187,7 @@ private BoundExpression CheckValue(BoundExpression expr, BindValueKind valueKind
var indexerAccess = (BoundIndexerAccess)expr;
if (valueKind == BindValueKind.Assignable && !indexerAccess.Indexer.ReturnsByRef)
{
expr = indexerAccess.Update(indexerAccess.ReceiverOpt,
indexerAccess.Indexer,
indexerAccess.Arguments,
indexerAccess.ArgumentNamesOpt,
indexerAccess.ArgumentRefKindsOpt,
indexerAccess.Expanded,
indexerAccess.ArgsToParamsOpt,
indexerAccess.BinderOpt,
useSetterForDefaultArgumentGeneration: true,
type: indexerAccess.Type);
expr = indexerAccess.Update(useSetterForDefaultArgumentGeneration: true);
}
}
break;
......
......@@ -6535,7 +6535,8 @@ private BoundExpression BindPointerElementAccess(ExpressionSyntax node, BoundExp
{
Error(diagnostics, ErrorCode.ERR_PtrIndexSingle, node);
}
return new BoundPointerElementAccess(node, expr, BadExpression(node, BuildArgumentsForErrorRecovery(analyzedArguments)), CheckOverflowAtRuntime, pointedAtType, hasErrors: true);
return new BoundPointerElementAccess(node, expr, BadExpression(node, BuildArgumentsForErrorRecovery(analyzedArguments)).MakeCompilerGenerated(),
CheckOverflowAtRuntime, pointedAtType, hasErrors: true);
}
if (pointedAtType.SpecialType == SpecialType.System_Void)
......@@ -7192,11 +7193,6 @@ private BoundExpression GetReceiverForConditionalBinding(ExpressionSyntax bindin
receiver = BindConditionalAccessReceiver(conditionalAccessNode, diagnostics);
}
if (receiver.HasAnyErrors)
{
return receiver;
}
// create surrogate receiver
var receiverType = receiver.Type;
if (receiverType?.IsNullableType() == true)
......@@ -7204,7 +7200,7 @@ private BoundExpression GetReceiverForConditionalBinding(ExpressionSyntax bindin
receiverType = receiverType.GetNullableUnderlyingType();
}
receiver = new BoundConditionalReceiver(receiver.Syntax, 0, receiverType) { WasCompilerGenerated = true };
receiver = new BoundConditionalReceiver(receiver.Syntax, 0, receiverType ?? CreateErrorType(), hasErrors: receiver.HasErrors) { WasCompilerGenerated = true };
return receiver;
}
......
......@@ -2605,7 +2605,7 @@ private bool IsOperandErrors(CSharpSyntaxNode node, ref BoundExpression operand,
if (!operand.HasAnyErrors)
{
Error(diagnostics, ErrorCode.ERR_LambdaInIsAs, node);
operand = BadExpression(node, operand);
operand = BadExpression(node, operand).MakeCompilerGenerated();
}
return true;
......
......@@ -198,7 +198,7 @@ private BoundStatement BindYieldReturnStatement(YieldStatementSyntax node, Diagn
TypeSymbol elementType = binder.GetIteratorElementType(node, diagnostics);
BoundExpression argument = (node.Expression == null)
? BadExpression(node)
? BadExpression(node).MakeCompilerGenerated()
: binder.BindValue(node.Expression, diagnostics, BindValueKind.RValue);
argument = ValidateEscape(argument, ExternalScope, isByRef: false, diagnostics: diagnostics);
......
......@@ -167,6 +167,34 @@ public override Symbol ExpressionSymbol
// DevDiv 1087283 tracks deciding whether or not to refactor this into BoundNodes.xml.
public ImmutableArray<PropertySymbol> OriginalIndexersOpt { get; private set; }
public BoundIndexerAccess Update(bool useSetterForDefaultArgumentGeneration)
{
if (useSetterForDefaultArgumentGeneration != this.UseSetterForDefaultArgumentGeneration)
{
var result = new BoundIndexerAccess(
this.Syntax,
this.ReceiverOpt,
this.Indexer,
this.Arguments,
this.ArgumentNamesOpt,
this.ArgumentRefKindsOpt,
this.Expanded,
this.ArgsToParamsOpt,
this.BinderOpt,
useSetterForDefaultArgumentGeneration,
this.Type,
this.HasErrors)
{
WasCompilerGenerated = this.WasCompilerGenerated,
OriginalIndexersOpt = this.OriginalIndexersOpt
};
return result;
}
return this;
}
public override LookupResultKind ResultKind
{
get
......
......@@ -59,5 +59,11 @@ public static bool IsConstructorInitializer(this BoundCall call)
receiverOpt != null &&
(receiverOpt.Kind == BoundKind.ThisReference || receiverOpt.Kind == BoundKind.BaseReference);
}
public static T MakeCompilerGenerated<T>(this T node) where T : BoundNode
{
node.WasCompilerGenerated = true;
return node;
}
}
}
......@@ -163,9 +163,6 @@ internal override Binder GetEnclosingBinderInternal(int position)
internal override IOperation GetOperationWorker(CSharpSyntaxNode node, CancellationToken cancellationToken)
{
// in case this is right side of a qualified name or member access (or part of a cref)
node = SyntaxFactory.GetStandaloneNode(node);
var model = this.GetMemberModel(node);
if (model != null)
{
......
......@@ -773,7 +773,9 @@ private IOperation CreateBoundConversionOperation(BoundConversion boundConversio
// Semantic model has a special case here that we match: if the underlying syntax is missing, don't create a conversion expression,
// and instead directly return the operand, which will be a BoundBadExpression. When we generate a node for the BoundBadExpression,
// the resulting IOperation will also have a null Type.
Debug.Assert(boundConversion.Operand.Kind == BoundKind.BadExpression);
Debug.Assert(boundConversion.Operand.Kind == BoundKind.BadExpression ||
((boundConversion.Operand as BoundLambda)?.Body.Statements.SingleOrDefault() as BoundReturnStatement)?.
ExpressionOpt?.Kind == BoundKind.BadExpression);
return Create(boundConversion.Operand);
}
......
......@@ -159,5 +159,45 @@ public void TestParentOperations()
VerifyParentOperations(model);
}
[CompilerTrait(CompilerFeature.IOperation)]
[WorkItem(23001, "https://github.com/dotnet/roslyn/issues/23001")]
[Fact]
public void TestGetOperationForQualifiedName()
{
var text = @"using System;
public class Test
{
class A
{
public B b;
}
class B
{
}
void M(A a)
{
int x2 = /*<bind>*/a.b/*</bind>*/;
}
}
";
var comp = CreateStandardCompilation(text, parseOptions: TestOptions.RegularWithIOperationFeature);
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
// Verify we return non-null operation only for topmost member access expression.
var expr = (MemberAccessExpressionSyntax)GetExprSyntaxForBinding(GetExprSyntaxList(tree));
Assert.Equal("a.b", expr.ToString());
var operation = model.GetOperation(expr);
Assert.NotNull(operation);
Assert.Equal(OperationKind.FieldReference, operation.Kind);
var fieldOperation = (IFieldReferenceOperation)operation;
Assert.Equal("b", fieldOperation.Field.Name);
// Verify we return null operation for child nodes of member access expression.
Assert.Null(model.GetOperation(expr.Name));
}
}
}
......@@ -7,6 +7,7 @@
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.Test.Utilities;
using System.Linq;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics
......@@ -408,6 +409,7 @@ protected override IEnumerable<int> M()
comp.Compilation.VerifyDiagnostics();
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
[WorkItem(261047, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=261047&_a=edit")]
public void MissingExpression()
......@@ -428,6 +430,19 @@ IEnumerable<int> I()
// yield return;
Diagnostic(ErrorCode.ERR_EmptyYield, "return").WithLocation(7, 15)
);
var tree = comp.SyntaxTrees.Single();
var node = tree.GetRoot().DescendantNodes().OfType<YieldStatementSyntax>().First();
Assert.Equal("yield return;", node.ToString());
comp.VerifyOperationTree(node, expectedOperationTree:
@"
IReturnOperation (OperationKind.YieldReturn, Type: null, IsInvalid) (Syntax: 'yield return;')
ReturnedValue:
IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid, IsImplicit) (Syntax: 'yield return;')
Children(0)
");
}
[Fact]
......
......@@ -3598,6 +3598,7 @@ static void M(object o)
);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact, WorkItem(13383, "https://github.com/dotnet/roslyn/issues/13383")]
public void MethodGroupAsExpressionInIsPatternBrokenCode()
{
......@@ -3613,7 +3614,7 @@ static void M(object o)
}
}
}";
CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
var compilation = CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
// (7,29): error CS1525: Invalid expression term ')'
// if (o.Equals is()) {}
Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(7, 29),
......@@ -3627,6 +3628,27 @@ static void M(object o)
// if (object.Equals is()) {}
Diagnostic(ErrorCode.ERR_LambdaInIsAs, "object.Equals is()").WithLocation(8, 17)
);
var tree = compilation.SyntaxTrees.Single();
var node = tree.GetRoot().DescendantNodes().OfType<IsPatternExpressionSyntax>().First();
Assert.Equal("o.Equals is()", node.ToString());
compilation.VerifyOperationTree(node, expectedOperationTree:
@"
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean, IsInvalid) (Syntax: 'o.Equals is()')
Expression:
IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid, IsImplicit) (Syntax: 'o.Equals is()')
Children(1):
IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'o.Equals')
Children(1):
IParameterReferenceOperation: o (OperationKind.ParameterReference, Type: System.Object, IsInvalid) (Syntax: 'o')
Pattern:
IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsInvalid) (Syntax: '()')
Value:
IInvalidOperation (OperationKind.Invalid, Type: null, IsInvalid) (Syntax: '')
Children(0)
");
}
[Fact, WorkItem(13383, "https://github.com/dotnet/roslyn/issues/13383")]
......
......@@ -6872,6 +6872,7 @@ public static void Main()
new ErrorDescription[] { new ErrorDescription { Code = (int)ErrorCode.ERR_PtrExpected, Line = 15, Column = 7 } });
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void CS0196ERR_PtrIndexSingle()
{
......@@ -6887,10 +6888,27 @@ public static void Main ()
// j = i[1];
}
}";
CreateStandardCompilation(text, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
var compilation = CreateStandardCompilation(text, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (8,11): error CS0196: A pointer must be indexed by only one value
// j = i[1,2]; // CS0196
Diagnostic(ErrorCode.ERR_PtrIndexSingle, "i[1,2]"));
var tree = compilation.SyntaxTrees.Single();
var node = tree.GetRoot().DescendantNodes().OfType<ElementAccessExpressionSyntax>().First();
Assert.Equal("i[1,2]", node.ToString());
compilation.VerifyOperationTree(node, expectedOperationTree:
@"
IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'i[1,2]')
Children(2):
ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32*, IsInvalid) (Syntax: 'i')
IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid, IsImplicit) (Syntax: 'i[1,2]')
Children(2):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsInvalid) (Syntax: '2')
");
}
[Fact]
......@@ -12484,6 +12502,8 @@ static void M(I i)
}
[Fact]
[CompilerTrait(CompilerFeature.IOperation)]
[WorkItem(23004, "https://github.com/dotnet/roslyn/issues/23004")]
public void CS0856ERR_IndexedPropertyRequiresParams01()
{
var source1 =
......@@ -12522,6 +12542,19 @@ static void M(I i)
Diagnostic(ErrorCode.ERR_IndexedPropertyRequiresParams, "i.R").WithArguments("I.R").WithLocation(8, 9),
// (9,9): error CS7036: There is no argument given that corresponds to the required formal parameter 'y' of 'I.R[int, int, int]'
Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "i.R[1]").WithArguments("y", "I.R[int, int, int]").WithLocation(9, 9));
var tree = compilation2.SyntaxTrees.Single();
var node = tree.GetRoot().DescendantNodes().OfType<ElementAccessExpressionSyntax>().First();
Assert.Equal("i.R[1]", node.ToString());
compilation2.VerifyOperationTree(node, expectedOperationTree:
@"
IInvalidOperation (OperationKind.Invalid, Type: System.Object, IsInvalid) (Syntax: 'i.R[1]')
Children(2):
IParameterReferenceOperation: i (OperationKind.ParameterReference, Type: I, IsInvalid) (Syntax: 'i')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
");
}
[Fact]
......@@ -22918,6 +22951,8 @@ static void Main(string[] args)
[Fact]
[CompilerTrait(CompilerFeature.IOperation)]
[WorkItem(23009, "https://github.com/dotnet/roslyn/issues/23009")]
public void ConditionalElementAccess001()
{
var text = @"
......@@ -22947,7 +22982,7 @@ static void Main(string[] args)
}
}
";
CreateCompilationWithMscorlib45(text).VerifyDiagnostics(
var compilation = CreateCompilationWithMscorlib45(text).VerifyDiagnostics(
// (11,18): error CS0175: Use of keyword 'base' is not valid in this context
// var x6 = base?.ToString();
Diagnostic(ErrorCode.ERR_BaseIllegal, "base").WithLocation(11, 18),
......@@ -22970,8 +23005,23 @@ static void Main(string[] args)
// var x5 = null?.ToString();
Diagnostic(ErrorCode.ERR_BadUnaryOp, "?").WithArguments("?", "<null>").WithLocation(24, 22)
);
}
var tree = compilation.SyntaxTrees.Single();
var node = tree.GetRoot().DescendantNodes().OfType<ConditionalAccessExpressionSyntax>().First();
Assert.Equal("base?.ToString()", node.ToString());
compilation.VerifyOperationTree(node, expectedOperationTree:
@"
IConditionalAccessOperation (OperationKind.ConditionalAccess, Type: ?, IsInvalid) (Syntax: 'base?.ToString()')
Operation:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: System.Object, IsInvalid) (Syntax: 'base')
WhenNotNull:
IInvocationOperation (virtual System.String System.Object.ToString()) (OperationKind.Invocation, Type: System.String) (Syntax: '.ToString()')
Instance Receiver:
IConditionalAccessInstanceOperation (OperationKind.ConditionalAccessInstance, Type: System.Object, IsInvalid, IsImplicit) (Syntax: 'base')
Arguments(0)
");
}
[Fact]
[WorkItem(976765, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/976765")]
......
......@@ -78,7 +78,7 @@ public IOperation GetOperation(SyntaxNode node, CancellationToken cancellationTo
catch (Exception e) when (FatalError.ReportWithoutCrashUnlessCanceled(e))
{
// Log a Non-fatal-watson and then ignore the crash in the attempt of getting operation
Debug.Assert(false);
Debug.Assert(false, e.ToString());
}
return null;
......
......@@ -834,5 +834,39 @@ IAnonymousFunctionOperation (Symbol: Sub ()) (OperationKind.AnonymousFunction, T
VerifyOperationTreeAndDiagnosticsForTest(Of MultiLineLambdaExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact, WorkItem(23001, "https://github.com/dotnet/roslyn/issues/23001")>
Public Sub TestGetOperationForQualifiedName()
Dim source = <![CDATA[
Public Class Test
Private Class A
Public b As B
End Class
Private Class B
End Class
Private Sub M(a As A)
Dim x2 As Integer = a.b'BIND:"a.b"
End Sub
End Class
]]>.Value
Dim comp = CreateVisualBasicCompilation(source, parseOptions:=TestOptions.RegularWithIOperationFeature)
Dim tree = comp.SyntaxTrees.Single()
Dim model = comp.GetSemanticModel(tree)
' Verify we return non-null operation only for topmost member access expression.
Dim expr = CompilationUtils.FindBindingText(Of MemberAccessExpressionSyntax)(comp, tree.FilePath)
Assert.Equal("a.b", expr.ToString())
Dim operation = model.GetOperation(expr)
Assert.NotNull(operation)
Assert.Equal(OperationKind.FieldReference, operation.Kind)
Dim fieldOperation = DirectCast(operation, IFieldReferenceOperation)
Assert.Equal("b", fieldOperation.Field.Name)
' Verify we return null operation for child nodes of member access expression.
Assert.Null(model.GetOperation(expr.Name))
End Sub
End Class
End Namespace
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Roslyn.Test.Utilities
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics
......@@ -67,5 +68,39 @@ IConditionalAccessOperation (OperationKind.ConditionalAccess, Type: System.Nulla
VerifyOperationTreeAndDiagnosticsForTest(Of ConditionalAccessExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
<WorkItem(23009, "https://github.com/dotnet/roslyn/issues/23009")>
Public Sub IConditionalAccessExpression_ErrorReceiver()
Dim source = <![CDATA[
Option Strict On
Public Class C1
Public Sub M1()
MyBase?.ToString()'BIND:"MyBase?.ToString()"
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
IConditionalAccessOperation (OperationKind.ConditionalAccess, Type: System.Void, IsInvalid) (Syntax: 'MyBase?.ToString()')
Operation:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: System.Object, IsInvalid) (Syntax: 'MyBase')
WhenNotNull:
IInvocationOperation (virtual Function System.Object.ToString() As System.String) (OperationKind.Invocation, Type: System.String) (Syntax: '.ToString()')
Instance Receiver:
IPlaceholderOperation (OperationKind.None, Type: System.Object, IsInvalid, IsImplicit) (Syntax: 'MyBase?.ToString()')
Arguments(0)
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC32027: 'MyBase' must be followed by '.' and an identifier.
MyBase?.ToString()'BIND:"MyBase?.ToString()"
~~~~~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of ConditionalAccessExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
End Class
End Namespace
......@@ -12,6 +12,8 @@
using System.Threading;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Test.Extensions;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
......@@ -255,6 +257,7 @@ public static void ValidateIOperations(Func<Compilation> createCompilation)
{
#if TEST_IOPERATION_INTERFACE
var compilation = createCompilation();
var roots = ArrayBuilder<IOperation>.GetInstance();
foreach (var tree in compilation.SyntaxTrees)
{
......@@ -270,9 +273,46 @@ public static void ValidateIOperations(Func<Compilation> createCompilation)
Assert.True(node == operation.Syntax, $"Expected : {node} - Actual : {operation.Syntax}");
Assert.True(operation.Type == null || !operation.MustHaveNullType(), $"Unexpected non-null type: {operation.Type}");
if (operation.Parent == null)
{
roots.Add(operation);
}
}
}
}
var explictNodeMap = new Dictionary<SyntaxNode, IOperation>();
foreach (var root in roots)
{
foreach (var operation in root.DescendantsAndSelf())
{
if (!operation.IsImplicit)
{
try
{
explictNodeMap.Add(operation.Syntax, operation);
}
catch (ArgumentException)
{
Assert.False(true, $"Duplicate explicit node for syntax ({operation.Syntax.RawKind}): {operation.Syntax.ToString()}");
}
}
if (operation.Kind == OperationKind.Argument)
{
var argument = (IArgumentOperation)operation;
if (argument.ArgumentKind == ArgumentKind.DefaultValue)
{
Assert.True(argument.Descendants().All(n => n.IsImplicit), $"Explicit node in default argument value ({argument.Syntax.RawKind}): {argument.Syntax.ToString()}");
}
}
}
}
roots.Free();
#endif
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册