未验证 提交 348d1629 编写于 作者: N Nat Ayewah 提交者: GitHub

Merge pull request #23064 from dotnet/merges/master-to-dev15.5.x-20171107-Manual

Merges/master to dev15.5.x 20171107 manual
...@@ -187,16 +187,7 @@ private BoundExpression CheckValue(BoundExpression expr, BindValueKind valueKind ...@@ -187,16 +187,7 @@ private BoundExpression CheckValue(BoundExpression expr, BindValueKind valueKind
var indexerAccess = (BoundIndexerAccess)expr; var indexerAccess = (BoundIndexerAccess)expr;
if (valueKind == BindValueKind.Assignable && !indexerAccess.Indexer.ReturnsByRef) if (valueKind == BindValueKind.Assignable && !indexerAccess.Indexer.ReturnsByRef)
{ {
expr = indexerAccess.Update(indexerAccess.ReceiverOpt, expr = indexerAccess.Update(useSetterForDefaultArgumentGeneration: true);
indexerAccess.Indexer,
indexerAccess.Arguments,
indexerAccess.ArgumentNamesOpt,
indexerAccess.ArgumentRefKindsOpt,
indexerAccess.Expanded,
indexerAccess.ArgsToParamsOpt,
indexerAccess.BinderOpt,
useSetterForDefaultArgumentGeneration: true,
type: indexerAccess.Type);
} }
} }
break; break;
......
...@@ -6535,7 +6535,8 @@ private BoundExpression BindPointerElementAccess(ExpressionSyntax node, BoundExp ...@@ -6535,7 +6535,8 @@ private BoundExpression BindPointerElementAccess(ExpressionSyntax node, BoundExp
{ {
Error(diagnostics, ErrorCode.ERR_PtrIndexSingle, node); 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) if (pointedAtType.SpecialType == SpecialType.System_Void)
...@@ -7192,11 +7193,6 @@ private BoundExpression GetReceiverForConditionalBinding(ExpressionSyntax bindin ...@@ -7192,11 +7193,6 @@ private BoundExpression GetReceiverForConditionalBinding(ExpressionSyntax bindin
receiver = BindConditionalAccessReceiver(conditionalAccessNode, diagnostics); receiver = BindConditionalAccessReceiver(conditionalAccessNode, diagnostics);
} }
if (receiver.HasAnyErrors)
{
return receiver;
}
// create surrogate receiver // create surrogate receiver
var receiverType = receiver.Type; var receiverType = receiver.Type;
if (receiverType?.IsNullableType() == true) if (receiverType?.IsNullableType() == true)
...@@ -7204,7 +7200,7 @@ private BoundExpression GetReceiverForConditionalBinding(ExpressionSyntax bindin ...@@ -7204,7 +7200,7 @@ private BoundExpression GetReceiverForConditionalBinding(ExpressionSyntax bindin
receiverType = receiverType.GetNullableUnderlyingType(); 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; return receiver;
} }
......
...@@ -2605,7 +2605,7 @@ private bool IsOperandErrors(CSharpSyntaxNode node, ref BoundExpression operand, ...@@ -2605,7 +2605,7 @@ private bool IsOperandErrors(CSharpSyntaxNode node, ref BoundExpression operand,
if (!operand.HasAnyErrors) if (!operand.HasAnyErrors)
{ {
Error(diagnostics, ErrorCode.ERR_LambdaInIsAs, node); Error(diagnostics, ErrorCode.ERR_LambdaInIsAs, node);
operand = BadExpression(node, operand); operand = BadExpression(node, operand).MakeCompilerGenerated();
} }
return true; return true;
......
...@@ -198,7 +198,7 @@ private BoundStatement BindYieldReturnStatement(YieldStatementSyntax node, Diagn ...@@ -198,7 +198,7 @@ private BoundStatement BindYieldReturnStatement(YieldStatementSyntax node, Diagn
TypeSymbol elementType = binder.GetIteratorElementType(node, diagnostics); TypeSymbol elementType = binder.GetIteratorElementType(node, diagnostics);
BoundExpression argument = (node.Expression == null) BoundExpression argument = (node.Expression == null)
? BadExpression(node) ? BadExpression(node).MakeCompilerGenerated()
: binder.BindValue(node.Expression, diagnostics, BindValueKind.RValue); : binder.BindValue(node.Expression, diagnostics, BindValueKind.RValue);
argument = ValidateEscape(argument, ExternalScope, isByRef: false, diagnostics: diagnostics); argument = ValidateEscape(argument, ExternalScope, isByRef: false, diagnostics: diagnostics);
......
...@@ -167,6 +167,34 @@ public override Symbol ExpressionSymbol ...@@ -167,6 +167,34 @@ public override Symbol ExpressionSymbol
// DevDiv 1087283 tracks deciding whether or not to refactor this into BoundNodes.xml. // DevDiv 1087283 tracks deciding whether or not to refactor this into BoundNodes.xml.
public ImmutableArray<PropertySymbol> OriginalIndexersOpt { get; private set; } 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 public override LookupResultKind ResultKind
{ {
get get
......
...@@ -59,5 +59,11 @@ public static bool IsConstructorInitializer(this BoundCall call) ...@@ -59,5 +59,11 @@ public static bool IsConstructorInitializer(this BoundCall call)
receiverOpt != null && receiverOpt != null &&
(receiverOpt.Kind == BoundKind.ThisReference || receiverOpt.Kind == BoundKind.BaseReference); (receiverOpt.Kind == BoundKind.ThisReference || receiverOpt.Kind == BoundKind.BaseReference);
} }
public static T MakeCompilerGenerated<T>(this T node) where T : BoundNode
{
node.WasCompilerGenerated = true;
return node;
}
} }
} }
...@@ -139,7 +139,7 @@ private bool IsDebugPlus() ...@@ -139,7 +139,7 @@ private bool IsDebugPlus()
private bool EnablePEVerifyCompat() private bool EnablePEVerifyCompat()
{ {
return _module.Compilation.FeaturePEVerifyCompatEnabled; return _module.Compilation.LanguageVersion < LanguageVersion.CSharp7_2 || _module.Compilation.FeaturePEVerifyCompatEnabled;
} }
private LocalDefinition LazyReturnTemp private LocalDefinition LazyReturnTemp
......
...@@ -24,8 +24,14 @@ private enum AddressKind ...@@ -24,8 +24,14 @@ private enum AddressKind
// reference itself will not be written to, nor it will be used to modify fields. // reference itself will not be written to, nor it will be used to modify fields.
ReadOnly, ReadOnly,
// same as ReadOnly, but we are not supposed to get a reference to a clone
// regardless of compat settings.
ReadOnlyStrict,
} }
private static bool IsReadOnly(AddressKind addressKind) => addressKind >= AddressKind.ReadOnly;
/// <summary> /// <summary>
/// Emits address as in &amp; /// Emits address as in &amp;
/// ///
...@@ -70,7 +76,7 @@ private LocalDefinition EmitAddress(BoundExpression expression, AddressKind addr ...@@ -70,7 +76,7 @@ private LocalDefinition EmitAddress(BoundExpression expression, AddressKind addr
case BoundKind.ThisReference: case BoundKind.ThisReference:
Debug.Assert(expression.Type.IsValueType, "only value types may need a ref to this"); Debug.Assert(expression.Type.IsValueType, "only value types may need a ref to this");
Debug.Assert(HasHome(expression, addressKind == AddressKind.Writeable)); Debug.Assert(HasHome(expression, addressKind));
_builder.EmitOpCode(ILOpCode.Ldarg_0); _builder.EmitOpCode(ILOpCode.Ldarg_0);
break; break;
...@@ -101,7 +107,7 @@ private LocalDefinition EmitAddress(BoundExpression expression, AddressKind addr ...@@ -101,7 +107,7 @@ private LocalDefinition EmitAddress(BoundExpression expression, AddressKind addr
var methodRefKind = call.Method.RefKind; var methodRefKind = call.Method.RefKind;
if (methodRefKind == RefKind.Ref || if (methodRefKind == RefKind.Ref ||
(addressKind == AddressKind.ReadOnly && methodRefKind == RefKind.RefReadOnly)) (IsReadOnly(addressKind) && methodRefKind == RefKind.RefReadOnly))
{ {
EmitCallExpression(call, UseKind.UsedAsAddress); EmitCallExpression(call, UseKind.UsedAsAddress);
break; break;
...@@ -121,7 +127,7 @@ private LocalDefinition EmitAddress(BoundExpression expression, AddressKind addr ...@@ -121,7 +127,7 @@ private LocalDefinition EmitAddress(BoundExpression expression, AddressKind addr
case BoundKind.ConditionalOperator: case BoundKind.ConditionalOperator:
var conditional = (BoundConditionalOperator)expression; var conditional = (BoundConditionalOperator)expression;
if (!HasHome(conditional, addressKind != AddressKind.ReadOnly)) if (!HasHome(conditional, addressKind))
{ {
goto default; goto default;
} }
...@@ -144,7 +150,7 @@ private LocalDefinition EmitAddress(BoundExpression expression, AddressKind addr ...@@ -144,7 +150,7 @@ private LocalDefinition EmitAddress(BoundExpression expression, AddressKind addr
return null; return null;
default: default:
Debug.Assert(!HasHome(expression, addressKind != AddressKind.ReadOnly)); Debug.Assert(!HasHome(expression, addressKind));
return EmitAddressOfTempClone(expression); return EmitAddressOfTempClone(expression);
} }
...@@ -218,7 +224,7 @@ private LocalDefinition EmitLocalAddress(BoundLocal localAccess, AddressKind add ...@@ -218,7 +224,7 @@ private LocalDefinition EmitLocalAddress(BoundLocal localAccess, AddressKind add
{ {
var local = localAccess.LocalSymbol; var local = localAccess.LocalSymbol;
if (!HasHome(localAccess, needWriteable: addressKind != AddressKind.ReadOnly)) if (!HasHome(localAccess, addressKind))
{ {
return EmitAddressOfTempClone(localAccess); return EmitAddressOfTempClone(localAccess);
} }
...@@ -249,7 +255,7 @@ private LocalDefinition EmitLocalAddress(BoundLocal localAccess, AddressKind add ...@@ -249,7 +255,7 @@ private LocalDefinition EmitLocalAddress(BoundLocal localAccess, AddressKind add
/// </summary> /// </summary>
private LocalDefinition EmitDupAddress(BoundDup dup, AddressKind addressKind) private LocalDefinition EmitDupAddress(BoundDup dup, AddressKind addressKind)
{ {
if (!HasHome(dup, needWriteable: addressKind != AddressKind.ReadOnly)) if (!HasHome(dup, addressKind))
{ {
return EmitAddressOfTempClone(dup); return EmitAddressOfTempClone(dup);
} }
...@@ -339,7 +345,7 @@ private LocalSymbol DigForValueLocal(BoundSequence topSequence, BoundExpression ...@@ -339,7 +345,7 @@ private LocalSymbol DigForValueLocal(BoundSequence topSequence, BoundExpression
/// Checks if expression directly or indirectly represents a value with its own home. In /// Checks if expression directly or indirectly represents a value with its own home. In
/// such cases it is possible to get a reference without loading into a temporary. /// such cases it is possible to get a reference without loading into a temporary.
/// </summary> /// </summary>
private bool HasHome(BoundExpression expression, bool needWriteable) private bool HasHome(BoundExpression expression, AddressKind addressKind)
{ {
switch (expression.Kind) switch (expression.Kind)
{ {
...@@ -352,10 +358,11 @@ private bool HasHome(BoundExpression expression, bool needWriteable) ...@@ -352,10 +358,11 @@ private bool HasHome(BoundExpression expression, bool needWriteable)
case BoundKind.ThisReference: case BoundKind.ThisReference:
Debug.Assert(expression.Type.IsValueType); Debug.Assert(expression.Type.IsValueType);
if (needWriteable && expression.Type.IsReadOnly) if (!IsReadOnly(addressKind) && expression.Type.IsReadOnly)
{ {
return _method.MethodKind == MethodKind.Constructor; return _method.MethodKind == MethodKind.Constructor;
} }
return true; return true;
case BoundKind.ThrowExpression: case BoundKind.ThrowExpression:
...@@ -363,7 +370,7 @@ private bool HasHome(BoundExpression expression, bool needWriteable) ...@@ -363,7 +370,7 @@ private bool HasHome(BoundExpression expression, bool needWriteable)
return true; return true;
case BoundKind.Parameter: case BoundKind.Parameter:
return !needWriteable || return IsReadOnly(addressKind) ||
((BoundParameter)expression).ParameterSymbol.RefKind != RefKind.In; ((BoundParameter)expression).ParameterSymbol.RefKind != RefKind.In;
case BoundKind.Local: case BoundKind.Local:
...@@ -371,31 +378,31 @@ private bool HasHome(BoundExpression expression, bool needWriteable) ...@@ -371,31 +378,31 @@ private bool HasHome(BoundExpression expression, bool needWriteable)
// locals in a mutating call // locals in a mutating call
var local = ((BoundLocal)expression).LocalSymbol; var local = ((BoundLocal)expression).LocalSymbol;
return !((IsStackLocal(local) && local.RefKind == RefKind.None) || return !((IsStackLocal(local) && local.RefKind == RefKind.None) ||
(needWriteable && local.RefKind == RefKind.RefReadOnly)); (!IsReadOnly(addressKind) && local.RefKind == RefKind.RefReadOnly));
case BoundKind.Call: case BoundKind.Call:
var methodRefKind = ((BoundCall)expression).Method.RefKind; var methodRefKind = ((BoundCall)expression).Method.RefKind;
return methodRefKind == RefKind.Ref || return methodRefKind == RefKind.Ref ||
(!needWriteable && methodRefKind == RefKind.RefReadOnly); (IsReadOnly(addressKind) && methodRefKind == RefKind.RefReadOnly);
case BoundKind.Dup: case BoundKind.Dup:
//NB: Dup represents locals that do not need IL slot //NB: Dup represents locals that do not need IL slot
var dupRefKind = ((BoundDup)expression).RefKind; var dupRefKind = ((BoundDup)expression).RefKind;
return dupRefKind == RefKind.Ref || return dupRefKind == RefKind.Ref ||
(!needWriteable && dupRefKind == RefKind.RefReadOnly); (IsReadOnly(addressKind) && dupRefKind == RefKind.RefReadOnly);
case BoundKind.FieldAccess: case BoundKind.FieldAccess:
return HasHome((BoundFieldAccess)expression, needWriteable); return HasHome((BoundFieldAccess)expression, addressKind);
case BoundKind.Sequence: case BoundKind.Sequence:
return HasHome(((BoundSequence)expression).Value, needWriteable); return HasHome(((BoundSequence)expression).Value, addressKind);
case BoundKind.AssignmentOperator: case BoundKind.AssignmentOperator:
return ((BoundAssignmentOperator)expression).RefKind != RefKind.None; return ((BoundAssignmentOperator)expression).RefKind != RefKind.None;
case BoundKind.ComplexConditionalReceiver: case BoundKind.ComplexConditionalReceiver:
Debug.Assert(HasHome(((BoundComplexConditionalReceiver)expression).ValueTypeReceiver, needWriteable)); Debug.Assert(HasHome(((BoundComplexConditionalReceiver)expression).ValueTypeReceiver, addressKind));
Debug.Assert(HasHome(((BoundComplexConditionalReceiver)expression).ReferenceTypeReceiver, needWriteable)); Debug.Assert(HasHome(((BoundComplexConditionalReceiver)expression).ReferenceTypeReceiver, addressKind));
goto case BoundKind.ConditionalReceiver; goto case BoundKind.ConditionalReceiver;
case BoundKind.ConditionalReceiver: case BoundKind.ConditionalReceiver:
...@@ -415,7 +422,7 @@ private bool HasHome(BoundExpression expression, bool needWriteable) ...@@ -415,7 +422,7 @@ private bool HasHome(BoundExpression expression, bool needWriteable)
// branch that has no home will need a temporary // branch that has no home will need a temporary
// if both have no home, just say whole expression has no home // if both have no home, just say whole expression has no home
// so we could just use one temp for the whole thing // so we could just use one temp for the whole thing
return HasHome(ternary.Consequence, needWriteable) && HasHome(ternary.Alternative, needWriteable); return HasHome(ternary.Consequence, addressKind) && HasHome(ternary.Alternative, addressKind);
default: default:
return false; return false;
...@@ -427,7 +434,7 @@ private bool HasHome(BoundExpression expression, bool needWriteable) ...@@ -427,7 +434,7 @@ private bool HasHome(BoundExpression expression, bool needWriteable)
/// Fields have readable homes when they are not constants. /// Fields have readable homes when they are not constants.
/// Fields have writeable homes unless they are readonly and used outside of the constructor. /// Fields have writeable homes unless they are readonly and used outside of the constructor.
/// </summary> /// </summary>
private bool HasHome(BoundFieldAccess fieldAccess, bool needWriteable) private bool HasHome(BoundFieldAccess fieldAccess, AddressKind addressKind)
{ {
FieldSymbol field = fieldAccess.FieldSymbol; FieldSymbol field = fieldAccess.FieldSymbol;
...@@ -437,7 +444,14 @@ private bool HasHome(BoundFieldAccess fieldAccess, bool needWriteable) ...@@ -437,7 +444,14 @@ private bool HasHome(BoundFieldAccess fieldAccess, bool needWriteable)
return false; return false;
} }
if (!needWriteable && !EnablePEVerifyCompat()) // in readonly situations where ref to a copy is not allowed, consider fields as addressable
if (addressKind == AddressKind.ReadOnlyStrict)
{
return true;
}
// ReadOnly references can always be taken unless we are in peverify compat mode
if (addressKind == AddressKind.ReadOnly && !EnablePEVerifyCompat())
{ {
return true; return true;
} }
...@@ -456,7 +470,7 @@ private bool HasHome(BoundFieldAccess fieldAccess, bool needWriteable) ...@@ -456,7 +470,7 @@ private bool HasHome(BoundFieldAccess fieldAccess, bool needWriteable)
// we would not be able to dig for the inner field using references and the outer struct will have to be copied to a temp anyways. // we would not be able to dig for the inner field using references and the outer struct will have to be copied to a temp anyways.
if (!EnablePEVerifyCompat()) if (!EnablePEVerifyCompat())
{ {
Debug.Assert(needWriteable == true); Debug.Assert(!IsReadOnly(addressKind));
var receiver = fieldAccess.ReceiverOpt; var receiver = fieldAccess.ReceiverOpt;
if (receiver?.Type.IsValueType == true) if (receiver?.Type.IsValueType == true)
...@@ -466,8 +480,8 @@ private bool HasHome(BoundFieldAccess fieldAccess, bool needWriteable) ...@@ -466,8 +480,8 @@ private bool HasHome(BoundFieldAccess fieldAccess, bool needWriteable)
// has readable home -> return false - we need to copy the field // has readable home -> return false - we need to copy the field
// otherwise -> return true - the copy will be made at higher level so the leaf field can have writeable home // otherwise -> return true - the copy will be made at higher level so the leaf field can have writeable home
return HasHome(receiver, needWriteable: true) || return HasHome(receiver, addressKind) ||
!HasHome(receiver, needWriteable: false); !HasHome(receiver, AddressKind.ReadOnly);
} }
} }
...@@ -534,7 +548,7 @@ private LocalDefinition EmitFieldAddress(BoundFieldAccess fieldAccess, AddressKi ...@@ -534,7 +548,7 @@ private LocalDefinition EmitFieldAddress(BoundFieldAccess fieldAccess, AddressKi
{ {
FieldSymbol field = fieldAccess.FieldSymbol; FieldSymbol field = fieldAccess.FieldSymbol;
if (!HasHome(fieldAccess, addressKind != AddressKind.ReadOnly)) if (!HasHome(fieldAccess, addressKind))
{ {
// accessing a field that is not writable (const or readonly) // accessing a field that is not writable (const or readonly)
return EmitAddressOfTempClone(fieldAccess); return EmitAddressOfTempClone(fieldAccess);
...@@ -546,11 +560,7 @@ private LocalDefinition EmitFieldAddress(BoundFieldAccess fieldAccess, AddressKi ...@@ -546,11 +560,7 @@ private LocalDefinition EmitFieldAddress(BoundFieldAccess fieldAccess, AddressKi
} }
else else
{ {
//NOTE: we are not propagating AddressKind here. return EmitInstanceFieldAddress(fieldAccess, addressKind);
// the reason is that while Constrained permits calls, it does not permit
// taking field addresses, so we have to turn Constrained into writeable.
// It is less error prone to just pass a bool "isReadonly"
return EmitInstanceFieldAddress(fieldAccess, isReadonly: addressKind == AddressKind.ReadOnly);
} }
} }
...@@ -564,7 +574,7 @@ private LocalDefinition EmitParameterAddress(BoundParameter parameter, AddressKi ...@@ -564,7 +574,7 @@ private LocalDefinition EmitParameterAddress(BoundParameter parameter, AddressKi
{ {
ParameterSymbol parameterSymbol = parameter.ParameterSymbol; ParameterSymbol parameterSymbol = parameter.ParameterSymbol;
if (!HasHome(parameter, needWriteable: addressKind != AddressKind.ReadOnly)) if (!HasHome(parameter, addressKind))
{ {
// accessing a parameter that is not writable // accessing a parameter that is not writable
return EmitAddressOfTempClone(parameter); return EmitAddressOfTempClone(parameter);
...@@ -634,11 +644,14 @@ private LocalDefinition EmitReceiverRef(BoundExpression receiver, AddressKind ad ...@@ -634,11 +644,14 @@ private LocalDefinition EmitReceiverRef(BoundExpression receiver, AddressKind ad
/// <summary> /// <summary>
/// May introduce a temp which it will return. (otherwise returns null) /// May introduce a temp which it will return. (otherwise returns null)
/// </summary> /// </summary>
private LocalDefinition EmitInstanceFieldAddress(BoundFieldAccess fieldAccess, bool isReadonly) private LocalDefinition EmitInstanceFieldAddress(BoundFieldAccess fieldAccess, AddressKind addressKind)
{ {
var field = fieldAccess.FieldSymbol; var field = fieldAccess.FieldSymbol;
var tempOpt = EmitReceiverRef(fieldAccess.ReceiverOpt, isReadonly? AddressKind.ReadOnly: AddressKind.Writeable); //NOTE: we are not propagating AddressKind.Constrained here.
// the reason is that while Constrained permits calls, it does not permit
// taking field addresses, so we have to turn Constrained into writeable.
var tempOpt = EmitReceiverRef(fieldAccess.ReceiverOpt, addressKind == AddressKind.Constrained ? AddressKind.Writeable : addressKind);
_builder.EmitOpCode(ILOpCode.Ldflda); _builder.EmitOpCode(ILOpCode.Ldflda);
EmitSymbolToken(field, fieldAccess.Syntax); EmitSymbolToken(field, fieldAccess.Syntax);
......
...@@ -426,10 +426,7 @@ private void EmitLoweredConditionalAccessExpression(BoundLoweredConditionalAcces ...@@ -426,10 +426,7 @@ private void EmitLoweredConditionalAccessExpression(BoundLoweredConditionalAcces
{ {
// this does not need to be writeable // this does not need to be writeable
// we may call "HasValue" on this, but it is not mutating // we may call "HasValue" on this, but it is not mutating
// (however verification does not know that and considers all calls mutating) var addressKind = AddressKind.ReadOnly;
var addressKind = EnablePEVerifyCompat()?
AddressKind.Writeable:
AddressKind.ReadOnly;
receiverTemp = EmitReceiverRef(receiver, addressKind); receiverTemp = EmitReceiverRef(receiver, addressKind);
_builder.EmitOpCode(ILOpCode.Dup); _builder.EmitOpCode(ILOpCode.Dup);
...@@ -605,7 +602,9 @@ private void EmitArgument(BoundExpression argument, RefKind refKind) ...@@ -605,7 +602,9 @@ private void EmitArgument(BoundExpression argument, RefKind refKind)
break; break;
default: default:
var unexpectedTemp = EmitAddress(argument, AddressKind.Writeable); // NOTE: passing "ReadOnlyStrict" here.
// we should not get an address of a copy if at all possible
var unexpectedTemp = EmitAddress(argument, refKind == RefKindExtensions.StrictIn? AddressKind.ReadOnlyStrict: AddressKind.Writeable);
if (unexpectedTemp != null) if (unexpectedTemp != null)
{ {
// interestingly enough "ref dynamic" sometimes is passed via a clone // interestingly enough "ref dynamic" sometimes is passed via a clone
...@@ -619,8 +618,11 @@ private void EmitArgument(BoundExpression argument, RefKind refKind) ...@@ -619,8 +618,11 @@ private void EmitArgument(BoundExpression argument, RefKind refKind)
private void EmitAddressOfExpression(BoundAddressOfOperator expression, bool used) private void EmitAddressOfExpression(BoundAddressOfOperator expression, bool used)
{ {
var temp = EmitAddress(expression.Operand, AddressKind.Writeable); // NOTE: passing "ReadOnlyStrict" here.
// we should not get an address of a copy if at all possible
var temp = EmitAddress(expression.Operand, AddressKind.ReadOnlyStrict);
Debug.Assert(temp == null, "If the operand is addressable, then a temp shouldn't be required."); Debug.Assert(temp == null, "If the operand is addressable, then a temp shouldn't be required.");
if (used) if (used)
{ {
// When computing an address to be used to initialize a fixed-statement variable, we have to be careful // When computing an address to be used to initialize a fixed-statement variable, we have to be careful
...@@ -811,15 +813,32 @@ private void EmitSideEffects(BoundSequence sequence) ...@@ -811,15 +813,32 @@ private void EmitSideEffects(BoundSequence sequence)
} }
} }
private void EmitArguments(ImmutableArray<BoundExpression> arguments, ImmutableArray<ParameterSymbol> parameters) private void EmitArguments(ImmutableArray<BoundExpression> arguments, ImmutableArray<ParameterSymbol> parameters, ImmutableArray<RefKind> refKindsOpt)
{ {
// We might have an extra argument for the __arglist() of a varargs method. // We might have an extra argument for the __arglist() of a varargs method.
Debug.Assert(arguments.Length == parameters.Length || arguments.Length == parameters.Length + 1, "argument count must match parameter count"); Debug.Assert(arguments.Length == parameters.Length || arguments.Length == parameters.Length + 1, "argument count must match parameter count");
for (int i = 0; i < arguments.Length; i++) for (int i = 0; i < arguments.Length; i++)
{ {
BoundExpression argument = arguments[i]; RefKind refKind;
RefKind refKind = (i == parameters.Length) ? RefKind.None : parameters[i].RefKind;
EmitArgument(argument, refKind); if (!refKindsOpt.IsDefault && i < refKindsOpt.Length)
{
// if we have an explicit refKind for the given argument, use that
refKind = refKindsOpt[i];
}
else if (i < parameters.Length)
{
// otherwise check the parameter
refKind = parameters[i].RefKind;
}
else
{
// vararg case
Debug.Assert(arguments[i].Kind == BoundKind.ArgListOperator);
refKind = RefKind.None;
}
EmitArgument(arguments[i], refKind);
} }
} }
...@@ -1068,7 +1087,7 @@ private bool FieldLoadPrefersRef(BoundExpression receiver) ...@@ -1068,7 +1087,7 @@ private bool FieldLoadPrefersRef(BoundExpression receiver)
} }
// can we take address at all? // can we take address at all?
if (!HasHome(receiver, needWriteable: false)) if (!HasHome(receiver, AddressKind.ReadOnly))
{ {
return false; return false;
} }
...@@ -1491,13 +1510,8 @@ private void EmitCallExpression(BoundCall call, UseKind useKind) ...@@ -1491,13 +1510,8 @@ private void EmitCallExpression(BoundCall call, UseKind useKind)
if (method.IsMetadataVirtual()) if (method.IsMetadataVirtual())
{ {
// NB: all methods that a struct could inherit from bases are non-mutating // NB: all methods that a struct could inherit from bases are non-mutating
// we are passing here "Writeable" just to keep verifier happy // treat receiver as ReadOnly
// we can pass here "ReadOnly" and avoid unnecessary copy tempOpt = EmitReceiverRef(receiver, AddressKind.ReadOnly);
var addressKind = EnablePEVerifyCompat() ?
AddressKind.Writeable :
AddressKind.ReadOnly;
tempOpt = EmitReceiverRef(receiver, addressKind);
callKind = CallKind.ConstrainedCallVirt; callKind = CallKind.ConstrainedCallVirt;
} }
else else
...@@ -1569,7 +1583,7 @@ private void EmitCallExpression(BoundCall call, UseKind useKind) ...@@ -1569,7 +1583,7 @@ private void EmitCallExpression(BoundCall call, UseKind useKind)
} }
} }
EmitArguments(arguments, method.Parameters); EmitArguments(arguments, method.Parameters, call.ArgumentRefKindsOpt);
int stackBehavior = GetCallStackBehavior(call); int stackBehavior = GetCallStackBehavior(call);
switch (callKind) switch (callKind)
{ {
...@@ -1861,7 +1875,7 @@ private void EmitObjectCreationExpression(BoundObjectCreationExpression expressi ...@@ -1861,7 +1875,7 @@ private void EmitObjectCreationExpression(BoundObjectCreationExpression expressi
} }
else else
{ {
EmitArguments(expression.Arguments, constructor.Parameters); EmitArguments(expression.Arguments, constructor.Parameters, expression.ArgumentRefKindsOpt);
var stackAdjustment = GetObjCreationStackBehavior(expression); var stackAdjustment = GetObjCreationStackBehavior(expression);
_builder.EmitOpCode(ILOpCode.Newobj, stackAdjustment); _builder.EmitOpCode(ILOpCode.Newobj, stackAdjustment);
...@@ -2033,7 +2047,7 @@ private bool TryEmitAssignmentInPlace(BoundAssignmentOperator assignmentOperator ...@@ -2033,7 +2047,7 @@ private bool TryEmitAssignmentInPlace(BoundAssignmentOperator assignmentOperator
private bool SafeToGetWriteableReference(BoundExpression left) private bool SafeToGetWriteableReference(BoundExpression left)
{ {
if (!HasHome(left, needWriteable: true)) if (!HasHome(left, AddressKind.Writeable))
{ {
return false; return false;
} }
...@@ -2079,7 +2093,7 @@ private void InPlaceCtorCall(BoundExpression target, BoundObjectCreationExpressi ...@@ -2079,7 +2093,7 @@ private void InPlaceCtorCall(BoundExpression target, BoundObjectCreationExpressi
Debug.Assert(temp == null, "in-place ctor target should not create temps"); Debug.Assert(temp == null, "in-place ctor target should not create temps");
var constructor = objCreation.Constructor; var constructor = objCreation.Constructor;
EmitArguments(objCreation.Arguments, constructor.Parameters); EmitArguments(objCreation.Arguments, constructor.Parameters, objCreation.ArgumentRefKindsOpt);
// -2 to adjust for consumed target address and not produced value. // -2 to adjust for consumed target address and not produced value.
var stackAdjustment = GetObjCreationStackBehavior(objCreation) - 2; var stackAdjustment = GetObjCreationStackBehavior(objCreation) - 2;
_builder.EmitOpCode(ILOpCode.Call, stackAdjustment); _builder.EmitOpCode(ILOpCode.Call, stackAdjustment);
...@@ -2335,10 +2349,11 @@ private void EmitAssignmentValue(BoundAssignmentOperator assignmentOperator) ...@@ -2335,10 +2349,11 @@ private void EmitAssignmentValue(BoundAssignmentOperator assignmentOperator)
else else
{ {
int exprTempsBefore = _expressionTemps?.Count ?? 0; int exprTempsBefore = _expressionTemps?.Count ?? 0;
var local = ((BoundLocal)assignmentOperator.Left).LocalSymbol;
// NOTE: passing "ReadOnly" here. Assuming we do not have compile errors, // NOTE: passing "ReadOnlyStrict" here.
// We should not get an address of a copy, even if the RHS is readonly // we should not get an address of a copy if at all possible
LocalDefinition temp = EmitAddress(assignmentOperator.Right, AddressKind.ReadOnly); LocalDefinition temp = EmitAddress(assignmentOperator.Right, local.RefKind == RefKind.RefReadOnly ? AddressKind.ReadOnlyStrict : AddressKind.Writeable);
// Generally taking a ref for the purpose of ref assignment should not be done on homeless values // Generally taking a ref for the purpose of ref assignment should not be done on homeless values
// however, there are very rare cases when we need to get a ref off a temp in synthetic code. // however, there are very rare cases when we need to get a ref off a temp in synthetic code.
...@@ -2346,7 +2361,7 @@ private void EmitAssignmentValue(BoundAssignmentOperator assignmentOperator) ...@@ -2346,7 +2361,7 @@ private void EmitAssignmentValue(BoundAssignmentOperator assignmentOperator)
AddExpressionTemp(temp); AddExpressionTemp(temp);
// are we, by the way, ref-assigning to something that lives longer than encompassing expression? // are we, by the way, ref-assigning to something that lives longer than encompassing expression?
if (((BoundLocal)assignmentOperator.Left).LocalSymbol.SynthesizedKind.IsLongLived()) if (local.SynthesizedKind.IsLongLived())
{ {
var exprTempsAfter = _expressionTemps?.Count ?? 0; var exprTempsAfter = _expressionTemps?.Count ?? 0;
......
...@@ -724,7 +724,10 @@ private void EmitReturnStatement(BoundReturnStatement boundReturnStatement) ...@@ -724,7 +724,10 @@ private void EmitReturnStatement(BoundReturnStatement boundReturnStatement)
} }
else else
{ {
this.EmitAddress(expressionOpt, this._method.RefKind == RefKind.RefReadOnly? AddressKind.ReadOnly: AddressKind.Writeable); // NOTE: passing "ReadOnlyStrict" here.
// we should never return an address of a copy
var unexpectedTemp = this.EmitAddress(expressionOpt, this._method.RefKind == RefKind.RefReadOnly ? AddressKind.ReadOnlyStrict : AddressKind.Writeable);
Debug.Assert(unexpectedTemp == null, "ref-returning a temp?");
} }
if (ShouldUseIndirectReturn()) if (ShouldUseIndirectReturn())
......
...@@ -2152,7 +2152,7 @@ internal override SyntaxNode GetDeclaratorSyntax() ...@@ -2152,7 +2152,7 @@ internal override SyntaxNode GetDeclaratorSyntax()
throw new NotImplementedException(); throw new NotImplementedException();
} }
internal override RefKind RefKind public override RefKind RefKind
{ {
get { return RefKind.None; } get { return RefKind.None; }
} }
......
...@@ -163,9 +163,6 @@ internal override Binder GetEnclosingBinderInternal(int position) ...@@ -163,9 +163,6 @@ internal override Binder GetEnclosingBinderInternal(int position)
internal override IOperation GetOperationWorker(CSharpSyntaxNode node, CancellationToken cancellationToken) 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); var model = this.GetMemberModel(node);
if (model != null) if (model != null)
{ {
......
...@@ -211,7 +211,7 @@ protected override ImmutableArray<Declaration> GetDeclarationChildren() ...@@ -211,7 +211,7 @@ protected override ImmutableArray<Declaration> GetDeclarationChildren()
return StaticCast<Declaration>.From(this.Children); return StaticCast<Declaration>.From(this.Children);
} }
public IEnumerable<string> MemberNames public ICollection<string> MemberNames
{ {
get get
{ {
......
...@@ -718,7 +718,6 @@ private static ImmutableArray<RefKind> GetRefKindsOrNull(ArrayBuilder<RefKind> r ...@@ -718,7 +718,6 @@ private static ImmutableArray<RefKind> GetRefKindsOrNull(ArrayBuilder<RefKind> r
if (IsSafeForReordering(argument, argRefKind)) if (IsSafeForReordering(argument, argRefKind))
{ {
arguments[p] = argument; arguments[p] = argument;
refKinds[p] = argRefKind;
} }
else else
{ {
...@@ -727,6 +726,7 @@ private static ImmutableArray<RefKind> GetRefKindsOrNull(ArrayBuilder<RefKind> r ...@@ -727,6 +726,7 @@ private static ImmutableArray<RefKind> GetRefKindsOrNull(ArrayBuilder<RefKind> r
storesToTemps.Add(assignment); storesToTemps.Add(assignment);
arguments[p] = temp; arguments[p] = temp;
} }
refKinds[p] = argRefKind;
} }
} }
......
...@@ -254,8 +254,10 @@ public override BoundNode VisitFixedLocalCollectionInitializer(BoundFixedLocalCo ...@@ -254,8 +254,10 @@ public override BoundNode VisitFixedLocalCollectionInitializer(BoundFixedLocalCo
pinnedTemp = factory.SynthesizedLocal( pinnedTemp = factory.SynthesizedLocal(
initializerType, initializerType,
syntax: declarator, syntax: declarator,
isPinned: true, isPinned: true,
refKind: RefKind.Ref, // different from the array and string cases //NOTE: different from the array and string cases
// RefReadOnly to allow referring to readonly variables. (technically we only "read" through the temp anyways)
refKind: RefKind.RefReadOnly,
kind: SynthesizedLocalKind.FixedReference); kind: SynthesizedLocalKind.FixedReference);
// NOTE: we pin the reference, not the pointer. // NOTE: we pin the reference, not the pointer.
......
...@@ -1269,7 +1269,7 @@ internal static BoundExpression NullOrDefault(TypeSymbol typeSymbol, SyntaxNode ...@@ -1269,7 +1269,7 @@ internal static BoundExpression NullOrDefault(TypeSymbol typeSymbol, SyntaxNode
#endif #endif
) )
{ {
if (refKind == RefKind.Out || refKind == RefKind.In) if (refKind == RefKind.Out)
{ {
refKind = RefKind.Ref; refKind = RefKind.Ref;
} }
......
...@@ -7,8 +7,8 @@ namespace Microsoft.CodeAnalysis.CSharp ...@@ -7,8 +7,8 @@ namespace Microsoft.CodeAnalysis.CSharp
{ {
internal abstract class BaseCSharpArgument : BaseArgument internal abstract class BaseCSharpArgument : BaseArgument
{ {
public BaseCSharpArgument(ArgumentKind argumentKind, IParameterSymbol parameter, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) : public BaseCSharpArgument(ArgumentKind argumentKind, IParameterSymbol parameter, SemanticModel semanticModel, SyntaxNode syntax, Optional<object> constantValue, bool isImplicit) :
base(argumentKind, parameter, semanticModel, syntax, type, constantValue, isImplicit) base(argumentKind, parameter, semanticModel, syntax, constantValue, isImplicit)
{ {
} }
...@@ -19,8 +19,8 @@ internal abstract class BaseCSharpArgument : BaseArgument ...@@ -19,8 +19,8 @@ internal abstract class BaseCSharpArgument : BaseArgument
internal sealed class CSharpArgument : BaseCSharpArgument internal sealed class CSharpArgument : BaseCSharpArgument
{ {
public CSharpArgument(ArgumentKind argumentKind, IParameterSymbol parameter, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) : public CSharpArgument(ArgumentKind argumentKind, IParameterSymbol parameter, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, Optional<object> constantValue, bool isImplicit) :
base(argumentKind, parameter, semanticModel, syntax, type, constantValue, isImplicit) base(argumentKind, parameter, semanticModel, syntax, constantValue, isImplicit)
{ {
ValueImpl = value; ValueImpl = value;
} }
...@@ -32,11 +32,11 @@ internal sealed class LazyCSharpArgument : BaseCSharpArgument ...@@ -32,11 +32,11 @@ internal sealed class LazyCSharpArgument : BaseCSharpArgument
{ {
private readonly Lazy<IOperation> _lazyValue; private readonly Lazy<IOperation> _lazyValue;
public LazyCSharpArgument(ArgumentKind argumentKind, IParameterSymbol parameter, Lazy<IOperation> value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) : public LazyCSharpArgument(ArgumentKind argumentKind, IParameterSymbol parameter, Lazy<IOperation> value, SemanticModel semanticModel, SyntaxNode syntax, Optional<object> constantValue, bool isImplicit) :
base(argumentKind, parameter, semanticModel, syntax, type, constantValue, isImplicit) base(argumentKind, parameter, semanticModel, syntax, constantValue, isImplicit)
{ {
_lazyValue = value ?? throw new ArgumentNullException(nameof(value)); _lazyValue = value ?? throw new ArgumentNullException(nameof(value));
} }
protected override IOperation ValueImpl => _lazyValue.Value; protected override IOperation ValueImpl => _lazyValue.Value;
} }
......
...@@ -10,7 +10,7 @@ internal class CSharpOperationCloner : OperationCloner ...@@ -10,7 +10,7 @@ internal class CSharpOperationCloner : OperationCloner
public override IOperation VisitArgument(IArgumentOperation operation, object argument) public override IOperation VisitArgument(IArgumentOperation operation, object argument)
{ {
return new CSharpArgument(operation.ArgumentKind, operation.Parameter, Visit(operation.Value), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); return new CSharpArgument(operation.ArgumentKind, operation.Parameter, Visit(operation.Value), ((Operation)operation).SemanticModel, operation.Syntax, operation.ConstantValue, operation.IsImplicit);
} }
public override IOperation VisitConversion(IConversionOperation operation, object argument) public override IOperation VisitConversion(IConversionOperation operation, object argument)
......
...@@ -46,19 +46,18 @@ internal IArgumentOperation CreateArgumentOperation(ArgumentKind kind, IParamete ...@@ -46,19 +46,18 @@ internal IArgumentOperation CreateArgumentOperation(ArgumentKind kind, IParamete
value, value,
semanticModel: _semanticModel, semanticModel: _semanticModel,
syntax: argument ?? value.Syntax, syntax: argument ?? value.Syntax,
type: value.Type,
constantValue: default, constantValue: default,
isImplicit: expression.WasCompilerGenerated || argument == null); isImplicit: expression.WasCompilerGenerated || argument == null);
} }
private IVariableDeclarationOperation CreateVariableDeclarationInternal(BoundLocalDeclaration boundLocalDeclaration, SyntaxNode syntax) private IVariableDeclaratorOperation CreateVariableDeclaratorInternal(BoundLocalDeclaration boundLocalDeclaration, SyntaxNode syntax)
{ {
IVariableInitializerOperation initializer = null; IVariableInitializerOperation initializer = null;
if (boundLocalDeclaration.InitializerOpt != null) if (boundLocalDeclaration.InitializerOpt != null)
{ {
IOperation initializerValue = Create(boundLocalDeclaration.InitializerOpt); IOperation initializerValue = Create(boundLocalDeclaration.InitializerOpt);
SyntaxNode initializerSyntax = null; SyntaxNode initializerSyntax = null;
bool isImplicit = false; bool initializerIsImplicit = false;
if (syntax is VariableDeclaratorSyntax variableDeclarator) if (syntax is VariableDeclaratorSyntax variableDeclarator)
{ {
initializerSyntax = variableDeclarator.Initializer; initializerSyntax = variableDeclarator.Initializer;
...@@ -72,18 +71,24 @@ private IVariableDeclarationOperation CreateVariableDeclarationInternal(BoundLoc ...@@ -72,18 +71,24 @@ private IVariableDeclarationOperation CreateVariableDeclarationInternal(BoundLoc
{ {
// There is no explicit syntax for the initializer, so we use the initializerValue's syntax and mark the operation as implicit. // There is no explicit syntax for the initializer, so we use the initializerValue's syntax and mark the operation as implicit.
initializerSyntax = initializerValue.Syntax; initializerSyntax = initializerValue.Syntax;
isImplicit = true; initializerIsImplicit = true;
} }
initializer = OperationFactory.CreateVariableInitializer(initializerSyntax, initializerValue, _semanticModel, isImplicit); initializer = OperationFactory.CreateVariableInitializer(initializerSyntax, initializerValue, _semanticModel, initializerIsImplicit);
} }
return OperationFactory.CreateVariableDeclaration(boundLocalDeclaration.LocalSymbol, initializer, _semanticModel, syntax); ILocalSymbol symbol = boundLocalDeclaration.LocalSymbol;
SyntaxNode syntaxNode = boundLocalDeclaration.Syntax;
ITypeSymbol type = null;
Optional<object> constantValue = default;
bool isImplicit = false;
return new VariableDeclarator(symbol, initializer, _semanticModel, syntax, type, constantValue, isImplicit);
} }
private IVariableDeclarationOperation CreateVariableDeclaration(BoundLocal boundLocal) private IVariableDeclaratorOperation CreateVariableDeclarator(BoundLocal boundLocal)
{ {
return OperationFactory.CreateVariableDeclaration(boundLocal.LocalSymbol, initializer: null, semanticModel: _semanticModel, syntax: boundLocal.Syntax); return new VariableDeclarator(boundLocal.LocalSymbol, initializer: null, semanticModel: _semanticModel, syntax: boundLocal.Syntax, type: null, constantValue: default, isImplicit: false);
} }
private IOperation CreateBoundCallInstanceOperation(BoundCall boundCall) private IOperation CreateBoundCallInstanceOperation(BoundCall boundCall)
...@@ -193,7 +198,8 @@ private ImmutableArray<IOperation> GetAnonymousObjectCreationInitializers(BoundA ...@@ -193,7 +198,8 @@ private ImmutableArray<IOperation> GetAnonymousObjectCreationInitializers(BoundA
SyntaxNode syntax = value.Syntax?.Parent ?? expression.Syntax; SyntaxNode syntax = value.Syntax?.Parent ?? expression.Syntax;
ITypeSymbol type = target.Type; ITypeSymbol type = target.Type;
Optional<object> constantValue = value.ConstantValue; Optional<object> constantValue = value.ConstantValue;
var assignment = new SimpleAssignmentExpression(target, value, _semanticModel, syntax, type, constantValue, isImplicit: value.IsImplicit); bool isRef = false;
var assignment = new SimpleAssignmentExpression(target, isRef, value, _semanticModel, syntax, type, constantValue, isImplicit: expression.WasCompilerGenerated);
builder.Add(assignment); builder.Add(assignment);
} }
......
...@@ -183,6 +183,12 @@ public override void VisitLocal(ILocalSymbol symbol) ...@@ -183,6 +183,12 @@ public override void VisitLocal(ILocalSymbol symbol)
{ {
AddKeyword(SyntaxKind.RefKeyword); AddKeyword(SyntaxKind.RefKeyword);
AddSpace(); AddSpace();
if (symbol.RefKind == RefKind.RefReadOnly)
{
AddKeyword(SyntaxKind.ReadOnlyKeyword);
AddSpace();
}
} }
if (format.LocalOptions.IncludesOption(SymbolDisplayLocalOptions.IncludeType)) if (format.LocalOptions.IncludesOption(SymbolDisplayLocalOptions.IncludeType))
......
...@@ -321,9 +321,9 @@ public object ConstantValue ...@@ -321,9 +321,9 @@ public object ConstantValue
internal abstract ImmutableArray<Diagnostic> GetConstantValueDiagnostics(BoundExpression boundInitValue); internal abstract ImmutableArray<Diagnostic> GetConstantValueDiagnostics(BoundExpression boundInitValue);
public bool IsRef => RefKind == RefKind.Ref; public bool IsRef => RefKind != RefKind.None;
internal abstract RefKind RefKind public abstract RefKind RefKind
{ {
get; get;
} }
......
...@@ -458,7 +458,7 @@ internal override ImmutableArray<Diagnostic> GetConstantValueDiagnostics(BoundEx ...@@ -458,7 +458,7 @@ internal override ImmutableArray<Diagnostic> GetConstantValueDiagnostics(BoundEx
return ImmutableArray<Diagnostic>.Empty; return ImmutableArray<Diagnostic>.Empty;
} }
internal override RefKind RefKind public override RefKind RefKind
{ {
get { return _refKind; } get { return _refKind; }
} }
......
...@@ -1219,7 +1219,7 @@ public sealed override ImmutableArray<Symbol> GetMembers(string name) ...@@ -1219,7 +1219,7 @@ public sealed override ImmutableArray<Symbol> GetMembers(string name)
internal override ImmutableArray<Symbol> GetSimpleNonTypeMembers(string name) internal override ImmutableArray<Symbol> GetSimpleNonTypeMembers(string name)
{ {
if (_lazyMembersDictionary != null || MemberNames.Contains(name)) if (_lazyMembersDictionary != null || declaration.MemberNames.Contains(name))
{ {
return GetMembers(name); return GetMembers(name);
} }
......
...@@ -74,7 +74,7 @@ internal override LocalSymbol WithSynthesizedLocalKindAndSyntax(SynthesizedLocal ...@@ -74,7 +74,7 @@ internal override LocalSymbol WithSynthesizedLocalKindAndSyntax(SynthesizedLocal
_refKind); _refKind);
} }
internal override RefKind RefKind public override RefKind RefKind
{ {
get { return _refKind; } get { return _refKind; }
} }
......
...@@ -88,7 +88,7 @@ internal override bool IsPinned ...@@ -88,7 +88,7 @@ internal override bool IsPinned
get { return _originalVariable.IsPinned; } get { return _originalVariable.IsPinned; }
} }
internal override RefKind RefKind public override RefKind RefKind
{ {
get { return _originalVariable.RefKind; } get { return _originalVariable.RefKind; }
} }
......
...@@ -233,6 +233,64 @@ .locals init (int V_0) ...@@ -233,6 +233,64 @@ .locals init (int V_0)
} }
[Fact]
[CompilerTrait(CompilerFeature.PEVerifyCompat)]
public void InParamPassRoField1()
{
var text = @"
class Program
{
public static readonly int F = 42;
public static void Main()
{
System.Console.WriteLine(M(in F));
}
static ref readonly int M(in int x)
{
return ref x;
}
}
";
var comp = CompileAndVerify(text, parseOptions: TestOptions.Regular, verify: false, expectedOutput: "42");
comp.VerifyIL("Program.Main()", @"
{
// Code size 17 (0x11)
.maxstack 1
IL_0000: ldsflda ""int Program.F""
IL_0005: call ""ref readonly int Program.M(in int)""
IL_000a: ldind.i4
IL_000b: call ""void System.Console.WriteLine(int)""
IL_0010: ret
}");
comp.VerifyIL("Program.M(in int)", @"
{
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldarg.0
IL_0001: ret
}");
comp = CompileAndVerify(text, verify: false, expectedOutput: "42", parseOptions: TestOptions.Regular.WithPEVerifyCompatFeature());
comp.VerifyIL("Program.Main()", @"
{
// Code size 17 (0x11)
.maxstack 1
IL_0000: ldsflda ""int Program.F""
IL_0005: call ""ref readonly int Program.M(in int)""
IL_000a: ldind.i4
IL_000b: call ""void System.Console.WriteLine(int)""
IL_0010: ret
}");
}
[Fact] [Fact]
public void InParamPassRoParamReturn() public void InParamPassRoParamReturn()
{ {
...@@ -798,6 +856,143 @@ public static void M1(in int arg1, in int arg2, in int arg3) ...@@ -798,6 +856,143 @@ public static void M1(in int arg1, in int arg2, in int arg3)
); );
} }
[Fact]
public void ReadonlyParamAsyncSpillInRoField()
{
var text = @"
using System.Threading.Tasks;
class Program
{
public static readonly int F = 5;
static void Main(string[] args)
{
Test().Wait();
}
public static async Task Test()
{
int local = 1;
M1(in F, await GetT(2), 3);
}
public static async Task<T> GetT<T>(T val)
{
await Task.Yield();
MutateReadonlyField();
return val;
}
private static unsafe void MutateReadonlyField()
{
fixed(int* ptr = &F)
{
*ptr = 42;
}
}
public static void M1(in int arg1, in int arg2, in int arg3)
{
System.Console.WriteLine(arg1 + arg2 + arg3);
}
}
";
var comp = CreateCompilationWithMscorlib46(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.UnsafeReleaseExe);
var result = CompileAndVerify(comp, verify: false, expectedOutput: @"47");
var expectedIL = @"
{
// Code size 162 (0xa2)
.maxstack 3
.locals init (int V_0,
int V_1,
System.Runtime.CompilerServices.TaskAwaiter<int> V_2,
int V_3,
System.Exception V_4)
IL_0000: ldarg.0
IL_0001: ldfld ""int Program.<Test>d__2.<>1__state""
IL_0006: stloc.0
.try
{
IL_0007: ldloc.0
IL_0008: brfalse.s IL_003f
IL_000a: ldc.i4.2
IL_000b: call ""System.Threading.Tasks.Task<int> Program.GetT<int>(int)""
IL_0010: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<int> System.Threading.Tasks.Task<int>.GetAwaiter()""
IL_0015: stloc.2
IL_0016: ldloca.s V_2
IL_0018: call ""bool System.Runtime.CompilerServices.TaskAwaiter<int>.IsCompleted.get""
IL_001d: brtrue.s IL_005b
IL_001f: ldarg.0
IL_0020: ldc.i4.0
IL_0021: dup
IL_0022: stloc.0
IL_0023: stfld ""int Program.<Test>d__2.<>1__state""
IL_0028: ldarg.0
IL_0029: ldloc.2
IL_002a: stfld ""System.Runtime.CompilerServices.TaskAwaiter<int> Program.<Test>d__2.<>u__1""
IL_002f: ldarg.0
IL_0030: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<Test>d__2.<>t__builder""
IL_0035: ldloca.s V_2
IL_0037: ldarg.0
IL_0038: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<int>, Program.<Test>d__2>(ref System.Runtime.CompilerServices.TaskAwaiter<int>, ref Program.<Test>d__2)""
IL_003d: leave.s IL_00a1
IL_003f: ldarg.0
IL_0040: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<int> Program.<Test>d__2.<>u__1""
IL_0045: stloc.2
IL_0046: ldarg.0
IL_0047: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<int> Program.<Test>d__2.<>u__1""
IL_004c: initobj ""System.Runtime.CompilerServices.TaskAwaiter<int>""
IL_0052: ldarg.0
IL_0053: ldc.i4.m1
IL_0054: dup
IL_0055: stloc.0
IL_0056: stfld ""int Program.<Test>d__2.<>1__state""
IL_005b: ldloca.s V_2
IL_005d: call ""int System.Runtime.CompilerServices.TaskAwaiter<int>.GetResult()""
IL_0062: stloc.1
IL_0063: ldsflda ""int Program.F""
IL_0068: ldloca.s V_1
IL_006a: ldc.i4.3
IL_006b: stloc.3
IL_006c: ldloca.s V_3
IL_006e: call ""void Program.M1(in int, in int, in int)""
IL_0073: leave.s IL_008e
}
catch System.Exception
{
IL_0075: stloc.s V_4
IL_0077: ldarg.0
IL_0078: ldc.i4.s -2
IL_007a: stfld ""int Program.<Test>d__2.<>1__state""
IL_007f: ldarg.0
IL_0080: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<Test>d__2.<>t__builder""
IL_0085: ldloc.s V_4
IL_0087: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
IL_008c: leave.s IL_00a1
}
IL_008e: ldarg.0
IL_008f: ldc.i4.s -2
IL_0091: stfld ""int Program.<Test>d__2.<>1__state""
IL_0096: ldarg.0
IL_0097: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<Test>d__2.<>t__builder""
IL_009c: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
IL_00a1: ret
}
";
result.VerifyIL("Program.<Test>d__2.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", expectedIL);
comp = CreateCompilationWithMscorlib46(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.UnsafeReleaseExe, parseOptions: TestOptions.Regular.WithPEVerifyCompatFeature());
result = CompileAndVerify(comp, verify: false, expectedOutput: @"47");
result.VerifyIL("Program.<Test>d__2.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", expectedIL);
}
[Fact] [Fact]
public void InParamAsyncSpill2() public void InParamAsyncSpill2()
{ {
......
...@@ -54,35 +54,30 @@ class C ...@@ -54,35 +54,30 @@ class C
} }
}"; }";
var comp = CompileAndVerify(source, parseOptions: TestOptions.Regular.WithPEVerifyCompatFeature()); // WithPEVerifyCompatFeature should not cause us to get a ref of a temp in ref assignments
var comp = CompileAndVerify(source, parseOptions: TestOptions.Regular.WithPEVerifyCompatFeature(), verify: false);
comp.VerifyIL("C.M", @" comp.VerifyIL("C.M", @"
{ {
// Code size 65 (0x41) // Code size 59 (0x3b)
.maxstack 2 .maxstack 2
.locals init (S V_0, .locals init (S V_0)
S V_1,
S2 V_2)
IL_0000: ldsflda ""S C.s1"" IL_0000: ldsflda ""S C.s1""
IL_0005: dup IL_0005: dup
IL_0006: ldobj ""S"" IL_0006: ldobj ""S""
IL_000b: stloc.0 IL_000b: stloc.0
IL_000c: ldloca.s V_0 IL_000c: ldloca.s V_0
IL_000e: call ""void S.AddOne()"" IL_000e: call ""void S.AddOne()""
IL_0013: ldsfld ""S C.s2"" IL_0013: ldsflda ""S C.s2""
IL_0018: stloc.0 IL_0018: ldobj ""S""
IL_0019: ldloca.s V_0 IL_001d: stloc.0
IL_001b: ldobj ""S"" IL_001e: ldloca.s V_0
IL_0020: stloc.1 IL_0020: call ""void S.AddOne()""
IL_0021: ldloca.s V_1 IL_0025: ldsflda ""S2 C.s3""
IL_0023: call ""void S.AddOne()"" IL_002a: call ""void S2.AddOne()""
IL_0028: ldsflda ""S2 C.s3"" IL_002f: ldarg.0
IL_002d: call ""void S2.AddOne()"" IL_0030: ldflda ""S2 C.s4""
IL_0032: ldarg.0 IL_0035: call ""void S2.AddOne()""
IL_0033: ldfld ""S2 C.s4"" IL_003a: ret
IL_0038: stloc.2
IL_0039: ldloca.s V_2
IL_003b: call ""void S2.AddOne()""
IL_0040: ret
}"); }");
comp = CompileAndVerify(source, verify: false); comp = CompileAndVerify(source, verify: false);
...@@ -864,47 +859,36 @@ .maxstack 1 ...@@ -864,47 +859,36 @@ .maxstack 1
IL_0033: ldflda ""int System.ValueTuple<int, int>.Item1"" IL_0033: ldflda ""int System.ValueTuple<int, int>.Item1""
IL_0038: ret IL_0038: ret
}"); }");
comp = CompileAndVerify(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithPEVerifyCompatFeature(), verify: false);
// WithPEVerifyCompatFeature should not cause us to get a ref of a temp in ref returns
comp = CompileAndVerify(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular.WithPEVerifyCompatFeature(), verify: false);
comp.VerifyIL("Program.Test", @" comp.VerifyIL("Program.Test", @"
{ {
// Code size 70 (0x46) // Code size 57 (0x39)
.maxstack 1 .maxstack 1
.locals init (bool V_0, //b .locals init (bool V_0) //b
int V_1,
System.ValueTuple<int, int> V_2,
int V_3,
System.ValueTuple<int, int> V_4)
IL_0000: ldc.i4.1 IL_0000: ldc.i4.1
IL_0001: stloc.0 IL_0001: stloc.0
IL_0002: ldloc.0 IL_0002: ldloc.0
IL_0003: brfalse.s IL_0020 IL_0003: brfalse.s IL_001a
IL_0005: ldloc.0 IL_0005: ldloc.0
IL_0006: brfalse.s IL_0012 IL_0006: brfalse.s IL_000f
IL_0008: ldarg.0 IL_0008: ldarg.0
IL_0009: ldfld ""int Program.F"" IL_0009: ldflda ""int Program.F""
IL_000e: stloc.1 IL_000e: ret
IL_000f: ldloca.s V_1 IL_000f: ldsflda ""(int Alice, int Bob) Program.F1""
IL_0011: ret IL_0014: ldflda ""int System.ValueTuple<int, int>.Item1""
IL_0012: ldsfld ""(int Alice, int Bob) Program.F1"" IL_0019: ret
IL_0017: stloc.2 IL_001a: ldloc.0
IL_0018: ldloca.s V_2 IL_001b: brfalse.s IL_0029
IL_001a: ldflda ""int System.ValueTuple<int, int>.Item1"" IL_001d: ldarg.0
IL_001f: ret IL_001e: ldflda ""Program.S Program.S1""
IL_0020: ldloc.0 IL_0023: ldflda ""int Program.S.F""
IL_0021: brfalse.s IL_0032 IL_0028: ret
IL_0023: ldarg.0 IL_0029: ldsflda ""Program.S Program.S2""
IL_0024: ldfld ""Program.S Program.S1"" IL_002e: ldflda ""(int Alice, int Bob) Program.S.F1""
IL_0029: ldfld ""int Program.S.F"" IL_0033: ldflda ""int System.ValueTuple<int, int>.Item1""
IL_002e: stloc.3 IL_0038: ret
IL_002f: ldloca.s V_3
IL_0031: ret
IL_0032: ldsfld ""Program.S Program.S2""
IL_0037: ldfld ""(int Alice, int Bob) Program.S.F1""
IL_003c: stloc.s V_4
IL_003e: ldloca.s V_4
IL_0040: ldflda ""int System.ValueTuple<int, int>.Item1""
IL_0045: ret
}"); }");
} }
......
...@@ -12025,7 +12025,7 @@ public MyManagedStruct(int x) ...@@ -12025,7 +12025,7 @@ public MyManagedStruct(int x)
n.n.num = x; n.n.num = x;
} }
}"; }";
var comp = CompileAndVerify(source, expectedOutput: @"42", verify: false); var comp = CompileAndVerify(source, expectedOutput: @"42", parseOptions: TestOptions.Regular7_2, verify: false);
comp.VerifyIL("Program.Main", comp.VerifyIL("Program.Main",
@" @"
...@@ -12088,6 +12088,38 @@ .locals init (MyManagedStruct V_0) ...@@ -12088,6 +12088,38 @@ .locals init (MyManagedStruct V_0)
IL_0046: call ""void System.Console.WriteLine(int)"" IL_0046: call ""void System.Console.WriteLine(int)""
IL_004b: ret IL_004b: ret
} }
");
comp = CompileAndVerify(source, expectedOutput: @"42", verify: true, parseOptions: TestOptions.Regular7_1);
comp.VerifyIL("Program.Main",
@"
{
// Code size 76 (0x4c)
.maxstack 3
.locals init (MyManagedStruct V_0)
IL_0000: newobj ""cls1..ctor()""
IL_0005: dup
IL_0006: ldfld ""MyManagedStruct cls1.y""
IL_000b: stloc.0
IL_000c: ldloca.s V_0
IL_000e: ldc.i4.s 123
IL_0010: call ""void MyManagedStruct.mutate(int)""
IL_0015: dup
IL_0016: ldfld ""MyManagedStruct cls1.y""
IL_001b: stloc.0
IL_001c: ldloca.s V_0
IL_001e: ldflda ""MyManagedStruct.Nested MyManagedStruct.n""
IL_0023: ldflda ""MyManagedStruct.Nested.Nested1 MyManagedStruct.Nested.n""
IL_0028: ldc.i4 0x1c8
IL_002d: call ""void MyManagedStruct.Nested.Nested1.mutate(int)""
IL_0032: ldfld ""MyManagedStruct cls1.y""
IL_0037: ldfld ""MyManagedStruct.Nested MyManagedStruct.n""
IL_003c: ldfld ""MyManagedStruct.Nested.Nested1 MyManagedStruct.Nested.n""
IL_0041: ldfld ""int MyManagedStruct.Nested.Nested1.num""
IL_0046: call ""void System.Console.WriteLine(int)""
IL_004b: ret
}
"); ");
} }
......
...@@ -1995,7 +1995,7 @@ void MixMethod() ...@@ -1995,7 +1995,7 @@ void MixMethod()
compilation.VerifyDiagnostics(); compilation.VerifyDiagnostics();
var syntaxKinds = ImmutableArray.Create(SyntaxKind.VariableDeclaration); var syntaxKinds = ImmutableArray.Create(SyntaxKind.VariableDeclaration);
var operationKinds = ImmutableArray.Create(OperationKind.VariableDeclaration); var operationKinds = ImmutableArray.Create(OperationKind.VariableDeclarator);
var analyzers = new DiagnosticAnalyzer[] { new GeneratedCodeSyntaxAndOperationAnalyzer(GeneratedCodeAnalysisFlags.None, syntaxKinds, operationKinds) }; var analyzers = new DiagnosticAnalyzer[] { new GeneratedCodeSyntaxAndOperationAnalyzer(GeneratedCodeAnalysisFlags.None, syntaxKinds, operationKinds) };
compilation.VerifyAnalyzerDiagnostics(analyzers, null, null, true, compilation.VerifyAnalyzerDiagnostics(analyzers, null, null, true,
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
using Roslyn.Test.Utilities; using Roslyn.Test.Utilities;
using Xunit; using Xunit;
using Microsoft.CodeAnalysis.UnitTests.Diagnostics; using Microsoft.CodeAnalysis.UnitTests.Diagnostics;
using static Microsoft.CodeAnalysis.CommonDiagnosticAnalyzers;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{ {
...@@ -1883,5 +1884,33 @@ public void M() ...@@ -1883,5 +1884,33 @@ public void M()
Diagnostic(TrueFalseUnaryOperationTestAnalyzer.UnaryTrueDescriptor.Id, "x && y").WithLocation(29, 13), Diagnostic(TrueFalseUnaryOperationTestAnalyzer.UnaryTrueDescriptor.Id, "x && y").WithLocation(29, 13),
Diagnostic(TrueFalseUnaryOperationTestAnalyzer.UnaryTrueDescriptor.Id, "x").WithLocation(30, 18)); Diagnostic(TrueFalseUnaryOperationTestAnalyzer.UnaryTrueDescriptor.Id, "x").WithLocation(30, 18));
} }
[Fact]
public void TestOperationBlockAnalyzer_EmptyMethodBody()
{
const string source = @"
class C
{
public void M()
{
}
public void M2(int i)
{
}
public void M3(int i = 0)
{
}
}
";
CreateCompilationWithMscorlib45(source)
.VerifyDiagnostics()
.VerifyAnalyzerDiagnostics(new DiagnosticAnalyzer[] { new OperationBlockAnalyzer() }, null, null, false,
Diagnostic("ID", "M2").WithArguments("M2", "Block").WithLocation(8, 17),
Diagnostic("ID", "M").WithArguments("M", "Block").WithLocation(4, 17),
Diagnostic("ID", "M3").WithArguments("M3", "ParameterInitializer").WithLocation(12, 17),
Diagnostic("ID", "M3").WithArguments("M3", "Block").WithLocation(12, 17));
}
} }
} }
...@@ -50,7 +50,7 @@ static void Test2(int y, params int[] x) ...@@ -50,7 +50,7 @@ static void Test2(int y, params int[] x)
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: System.Int32[]) (Syntax: 'null') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: 'null')
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32[], Constant: null, IsImplicit) (Syntax: 'null') IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32[], Constant: null, IsImplicit) (Syntax: 'null')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
Operand: Operand:
...@@ -126,6 +126,27 @@ public void TestClone() ...@@ -126,6 +126,27 @@ public void TestClone()
VerifyClone(model); VerifyClone(model);
} }
[CompilerTrait(CompilerFeature.IOperation)]
[WorkItem(22964, "https://github.com/dotnet/roslyn/issues/22964")]
[Fact]
public void GlobalStatement_Parent()
{
var source =
@"
System.Console.WriteLine();
";
var compilation = CreateStandardCompilation(source, options: TestOptions.ReleaseExe.WithScriptClassName("Script"), parseOptions: TestOptions.Script);
compilation.VerifyDiagnostics();
var tree = compilation.SyntaxTrees.Single();
var statement = tree.GetRoot().DescendantNodes().OfType<StatementSyntax>().Single();
var model = compilation.GetSemanticModel(tree);
var operation = model.GetOperation(statement);
Assert.Equal(OperationKind.ExpressionStatement, operation.Kind);
Assert.Null(operation.Parent);
}
[CompilerTrait(CompilerFeature.IOperation)] [CompilerTrait(CompilerFeature.IOperation)]
[Fact] [Fact]
public void TestParentOperations() public void TestParentOperations()
...@@ -138,5 +159,45 @@ public void TestParentOperations() ...@@ -138,5 +159,45 @@ public void TestParentOperations()
VerifyParentOperations(model); 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);
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));
}
} }
} }
...@@ -303,19 +303,22 @@ public void F(int dimension) ...@@ -303,19 +303,22 @@ public void F(int dimension)
} }
"; ";
string expectedOperationTree = @" string expectedOperationTree = @"
IVariableDeclarationsOperation (1 declarations) (OperationKind.VariableDeclarations, Type: null) (Syntax: 'int[] x = { 1, 2 };') IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'int[] x = { 1, 2 };')
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'x = { 1, 2 }') IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'int[] x = { 1, 2 }')
Variables: Local_1: System.Int32[] x Declarators:
Initializer: IVariableDeclaratorOperation (Symbol: System.Int32[] x) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'x = { 1, 2 }')
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= { 1, 2 }')
IArrayCreationOperation (OperationKind.ArrayCreation, Type: System.Int32[], IsImplicit) (Syntax: '{ 1, 2 }')
Dimension Sizes(1):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsImplicit) (Syntax: '{ 1, 2 }')
Initializer: Initializer:
IArrayInitializerOperation (2 elements) (OperationKind.ArrayInitializer, Type: null) (Syntax: '{ 1, 2 }') IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= { 1, 2 }')
Element Values(2): IArrayCreationOperation (OperationKind.ArrayCreation, Type: System.Int32[], IsImplicit) (Syntax: '{ 1, 2 }')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') Dimension Sizes(1):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2') ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsImplicit) (Syntax: '{ 1, 2 }')
Initializer:
IArrayInitializerOperation (2 elements) (OperationKind.ArrayInitializer, Type: null) (Syntax: '{ 1, 2 }')
Element Values(2):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2')
Initializer:
null
"; ";
var expectedDiagnostics = DiagnosticDescription.None; var expectedDiagnostics = DiagnosticDescription.None;
......
...@@ -200,9 +200,12 @@ static void M(Task<int> t) ...@@ -200,9 +200,12 @@ static void M(Task<int> t)
} }
"; ";
string expectedOperationTree = @" string expectedOperationTree = @"
IVariableDeclarationsOperation (1 declarations) (OperationKind.VariableDeclarations, Type: null, IsInvalid) (Syntax: 'await t;') IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsInvalid) (Syntax: 'await t;')
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null, IsInvalid) (Syntax: 't') IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null, IsInvalid) (Syntax: 'await t')
Variables: Local_1: await t Declarators:
IVariableDeclaratorOperation (Symbol: await t) (OperationKind.VariableDeclarator, Type: null, IsInvalid) (Syntax: 't')
Initializer:
null
Initializer: Initializer:
null null
"; ";
......
...@@ -188,7 +188,7 @@ void M(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int ...@@ -188,7 +188,7 @@ void M(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: System.Int32) (Syntax: '(a >> 10) + ... 0) ? 1 : 0)') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: '(a >> 10) + ... 0) ? 1 : 0)')
IBinaryOperation (BinaryOperatorKind.Or) (OperationKind.BinaryOperator, Type: System.Int32) (Syntax: '(a >> 10) + ... 0) ? 1 : 0)') IBinaryOperation (BinaryOperatorKind.Or) (OperationKind.BinaryOperator, Type: System.Int32) (Syntax: '(a >> 10) + ... 0) ? 1 : 0)')
Left: Left:
IBinaryOperation (BinaryOperatorKind.And) (OperationKind.BinaryOperator, Type: System.Int32) (Syntax: '(a >> 10) + ... / e % f & g') IBinaryOperation (BinaryOperatorKind.And) (OperationKind.BinaryOperator, Type: System.Int32) (Syntax: '(a >> 10) + ... / e % f & g')
...@@ -322,7 +322,7 @@ void M(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int ...@@ -322,7 +322,7 @@ void M(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: System.Int32) (Syntax: '(a >> 10) + ... 0) ? 1 : 0)') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: '(a >> 10) + ... 0) ? 1 : 0)')
IBinaryOperation (BinaryOperatorKind.Or) (OperationKind.BinaryOperator, Type: System.Int32) (Syntax: '(a >> 10) + ... 0) ? 1 : 0)') IBinaryOperation (BinaryOperatorKind.Or) (OperationKind.BinaryOperator, Type: System.Int32) (Syntax: '(a >> 10) + ... 0) ? 1 : 0)')
Left: Left:
IBinaryOperation (BinaryOperatorKind.And) (OperationKind.BinaryOperator, Type: System.Int32) (Syntax: '(a >> 10) + ... / e % f & g') IBinaryOperation (BinaryOperatorKind.And) (OperationKind.BinaryOperator, Type: System.Int32) (Syntax: '(a >> 10) + ... / e % f & g')
......
// 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 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
{
public partial class IOperationTests : SemanticModelTestBase
{
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ConditionalExpression_01()
{
string source = @"
class P
{
private void M()
{
int i = 0;
int j = 2;
var z = (/*<bind>*/true ? i : j/*</bind>*/);
}
}
";
string expectedOperationTree = @"
IConditionalOperation (OperationKind.Conditional, Type: System.Int32) (Syntax: 'true ? i : j')
Condition:
ILiteralOperation (OperationKind.Literal, Type: System.Boolean, Constant: True) (Syntax: 'true')
WhenTrue:
ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i')
WhenFalse:
ILocalReferenceOperation: j (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'j')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<ConditionalExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ConditionalExpression_02()
{
string source = @"
class P
{
private void M()
{
int i = 0;
int j = 2;
(/*<bind>*/true ? ref i : ref j/*</bind>*/) = 4;
}
}
";
string expectedOperationTree = @"
IConditionalOperation (IsRef) (OperationKind.Conditional, Type: System.Int32) (Syntax: 'true ? ref i : ref j')
Condition:
ILiteralOperation (OperationKind.Literal, Type: System.Boolean, Constant: True) (Syntax: 'true')
WhenTrue:
ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i')
WhenFalse:
ILocalReferenceOperation: j (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'j')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<ConditionalExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
}
}
...@@ -35,18 +35,21 @@ void M1() ...@@ -35,18 +35,21 @@ void M1()
string expectedOperationTree = @" string expectedOperationTree = @"
IOperation: (OperationKind.None, Type: null) (Syntax: 'fixed(int * ... }') IOperation: (OperationKind.None, Type: null) (Syntax: 'fixed(int * ... }')
Children(2): Children(2):
IVariableDeclarationsOperation (1 declarations) (OperationKind.VariableDeclarations, Type: null) (Syntax: 'int *p = &i') IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsImplicit) (Syntax: 'int *p = &i')
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'p = &i') IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'int *p = &i')
Variables: Local_1: System.Int32* p Declarators:
IVariableDeclaratorOperation (Symbol: System.Int32* p) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'p = &i')
Initializer:
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= &i')
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: '&i')
Children(1):
IAddressOfOperation (OperationKind.AddressOf, Type: System.Int32*) (Syntax: '&i')
Reference:
IFieldReferenceOperation: System.Int32 C.i (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'i')
Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'i')
Initializer: Initializer:
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= &i') null
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: '&i')
Children(1):
IAddressOfOperation (OperationKind.AddressOf, Type: System.Int32*) (Syntax: '&i')
Reference:
IFieldReferenceOperation: System.Int32 C.i (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'i')
Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'i')
IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'Console.Wri ... is {*p}"");') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'Console.Wri ... is {*p}"");')
Expression: Expression:
...@@ -54,7 +57,7 @@ void M1() ...@@ -54,7 +57,7 @@ void M1()
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: System.String) (Syntax: '$""P is {*p}""') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: '$""P is {*p}""')
IInterpolatedStringOperation (OperationKind.InterpolatedString, Type: System.String) (Syntax: '$""P is {*p}""') IInterpolatedStringOperation (OperationKind.InterpolatedString, Type: System.String) (Syntax: '$""P is {*p}""')
Parts(2): Parts(2):
IInterpolatedStringTextOperation (OperationKind.InterpolatedStringText, Type: null) (Syntax: 'P is ') IInterpolatedStringTextOperation (OperationKind.InterpolatedStringText, Type: null) (Syntax: 'P is ')
...@@ -106,29 +109,31 @@ void M1() ...@@ -106,29 +109,31 @@ void M1()
string expectedOperationTree = @" string expectedOperationTree = @"
IOperation: (OperationKind.None, Type: null) (Syntax: 'fixed (int* ... }') IOperation: (OperationKind.None, Type: null) (Syntax: 'fixed (int* ... }')
Children(2): Children(2):
IVariableDeclarationsOperation (2 declarations) (OperationKind.VariableDeclarations, Type: null) (Syntax: 'int* p1 = &i1, p2 = &i2') IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsImplicit) (Syntax: 'int* p1 = &i1, p2 = &i2')
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'p1 = &i1') IVariableDeclarationOperation (2 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'int* p1 = &i1, p2 = &i2')
Variables: Local_1: System.Int32* p1 Declarators:
Initializer: IVariableDeclaratorOperation (Symbol: System.Int32* p1) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'p1 = &i1')
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= &i1') Initializer:
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: '&i1') IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= &i1')
Children(1): IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: '&i1')
IAddressOfOperation (OperationKind.AddressOf, Type: System.Int32*) (Syntax: '&i1') Children(1):
Reference: IAddressOfOperation (OperationKind.AddressOf, Type: System.Int32*) (Syntax: '&i1')
IFieldReferenceOperation: System.Int32 C.i1 (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'i1') Reference:
Instance Receiver: IFieldReferenceOperation: System.Int32 C.i1 (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'i1')
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'i1') Instance Receiver:
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'p2 = &i2') IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'i1')
Variables: Local_1: System.Int32* p2 IVariableDeclaratorOperation (Symbol: System.Int32* p2) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'p2 = &i2')
Initializer:
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= &i2')
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: '&i2')
Children(1):
IAddressOfOperation (OperationKind.AddressOf, Type: System.Int32*) (Syntax: '&i2')
Reference:
IFieldReferenceOperation: System.Int32 C.i2 (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'i2')
Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'i2')
Initializer: Initializer:
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= &i2') null
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: '&i2')
Children(1):
IAddressOfOperation (OperationKind.AddressOf, Type: System.Int32*) (Syntax: '&i2')
Reference:
IFieldReferenceOperation: System.Int32 C.i2 (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'i2')
Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'i2')
IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i3 = *p1 + *p2;') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i3 = *p1 + *p2;')
Expression: Expression:
...@@ -183,32 +188,38 @@ void M1() ...@@ -183,32 +188,38 @@ void M1()
string expectedOperationTree = @" string expectedOperationTree = @"
IOperation: (OperationKind.None, Type: null) (Syntax: 'fixed (int* ... }') IOperation: (OperationKind.None, Type: null) (Syntax: 'fixed (int* ... }')
Children(2): Children(2):
IVariableDeclarationsOperation (1 declarations) (OperationKind.VariableDeclarations, Type: null) (Syntax: 'int* p1 = &i1') IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsImplicit) (Syntax: 'int* p1 = &i1')
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'p1 = &i1') IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'int* p1 = &i1')
Variables: Local_1: System.Int32* p1 Declarators:
Initializer: IVariableDeclaratorOperation (Symbol: System.Int32* p1) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'p1 = &i1')
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= &i1')
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: '&i1')
Children(1):
IAddressOfOperation (OperationKind.AddressOf, Type: System.Int32*) (Syntax: '&i1')
Reference:
IFieldReferenceOperation: System.Int32 C.i1 (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'i1')
Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'i1')
IOperation: (OperationKind.None, Type: null) (Syntax: 'fixed (int* ... }')
Children(2):
IVariableDeclarationsOperation (1 declarations) (OperationKind.VariableDeclarations, Type: null) (Syntax: 'int* p2 = &i2')
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'p2 = &i2')
Variables: Local_1: System.Int32* p2
Initializer: Initializer:
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= &i2') IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= &i1')
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: '&i2') IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: '&i1')
Children(1): Children(1):
IAddressOfOperation (OperationKind.AddressOf, Type: System.Int32*) (Syntax: '&i2') IAddressOfOperation (OperationKind.AddressOf, Type: System.Int32*) (Syntax: '&i1')
Reference: Reference:
IFieldReferenceOperation: System.Int32 C.i2 (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'i2') IFieldReferenceOperation: System.Int32 C.i1 (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'i1')
Instance Receiver: Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'i2') IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'i1')
Initializer:
null
IOperation: (OperationKind.None, Type: null) (Syntax: 'fixed (int* ... }')
Children(2):
IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsImplicit) (Syntax: 'int* p2 = &i2')
IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'int* p2 = &i2')
Declarators:
IVariableDeclaratorOperation (Symbol: System.Int32* p2) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'p2 = &i2')
Initializer:
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= &i2')
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: '&i2')
Children(1):
IAddressOfOperation (OperationKind.AddressOf, Type: System.Int32*) (Syntax: '&i2')
Reference:
IFieldReferenceOperation: System.Int32 C.i2 (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'i2')
Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'i2')
Initializer:
null
IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i3 = *p1 + *p2;') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i3 = *p1 + *p2;')
Expression: Expression:
...@@ -258,13 +269,16 @@ void M1() ...@@ -258,13 +269,16 @@ void M1()
string expectedOperationTree = @" string expectedOperationTree = @"
IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'fixed (int* ... }') IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'fixed (int* ... }')
Children(2): Children(2):
IVariableDeclarationsOperation (1 declarations) (OperationKind.VariableDeclarations, Type: null, IsInvalid) (Syntax: 'int* p1 =') IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsInvalid, IsImplicit) (Syntax: 'int* p1 =')
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null, IsInvalid) (Syntax: 'p1 =') IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null, IsInvalid) (Syntax: 'int* p1 =')
Variables: Local_1: System.Int32* p1 Declarators:
IVariableDeclaratorOperation (Symbol: System.Int32* p1) (OperationKind.VariableDeclarator, Type: null, IsInvalid) (Syntax: 'p1 =')
Initializer:
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null, IsInvalid) (Syntax: '=')
IInvalidOperation (OperationKind.Invalid, Type: null, IsInvalid) (Syntax: '')
Children(0)
Initializer: Initializer:
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null, IsInvalid) (Syntax: '=') null
IInvalidOperation (OperationKind.Invalid, Type: null, IsInvalid) (Syntax: '')
Children(0)
IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i3 = *p1;') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i3 = *p1;')
Expression: Expression:
...@@ -313,18 +327,21 @@ void M1() ...@@ -313,18 +327,21 @@ void M1()
string expectedOperationTree = @" string expectedOperationTree = @"
IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'fixed (int* ... }') IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'fixed (int* ... }')
Children(2): Children(2):
IVariableDeclarationsOperation (1 declarations) (OperationKind.VariableDeclarations, Type: null) (Syntax: 'int* p1 = &i1') IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsImplicit) (Syntax: 'int* p1 = &i1')
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'p1 = &i1') IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'int* p1 = &i1')
Variables: Local_1: System.Int32* p1 Declarators:
IVariableDeclaratorOperation (Symbol: System.Int32* p1) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'p1 = &i1')
Initializer:
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= &i1')
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: '&i1')
Children(1):
IAddressOfOperation (OperationKind.AddressOf, Type: System.Int32*) (Syntax: '&i1')
Reference:
IFieldReferenceOperation: System.Int32 C.i1 (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'i1')
Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'i1')
Initializer: Initializer:
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= &i1') null
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: '&i1')
Children(1):
IAddressOfOperation (OperationKind.AddressOf, Type: System.Int32*) (Syntax: '&i1')
Reference:
IFieldReferenceOperation: System.Int32 C.i1 (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'i1')
Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'i1')
IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{ ... }') IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{ ... }')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: 'i3 = &p1;') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: 'i3 = &p1;')
Expression: Expression:
......
...@@ -205,7 +205,7 @@ private void M() ...@@ -205,7 +205,7 @@ private void M()
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: System.Int32) (Syntax: 'm') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: 'm')
ILocalReferenceOperation: m (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'm') ILocalReferenceOperation: m (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'm')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
...@@ -219,7 +219,7 @@ private void M() ...@@ -219,7 +219,7 @@ private void M()
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: System.Int32) (Syntax: 'n') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: 'n')
ILocalReferenceOperation: n (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'n') ILocalReferenceOperation: n (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'n')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
...@@ -277,7 +277,7 @@ private void M() ...@@ -277,7 +277,7 @@ private void M()
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: System.Int32) (Syntax: 'm') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: 'm')
ILocalReferenceOperation: m (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'm') ILocalReferenceOperation: m (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'm')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
...@@ -289,7 +289,7 @@ private void M() ...@@ -289,7 +289,7 @@ private void M()
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: System.Int32) (Syntax: 'n') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: 'n')
ILocalReferenceOperation: n (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'n') ILocalReferenceOperation: n (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'n')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
...@@ -345,7 +345,7 @@ private void M() ...@@ -345,7 +345,7 @@ private void M()
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: System.String) (Syntax: '""Nothing is ... er than m.""') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: '""Nothing is ... er than m.""')
ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""Nothing is larger than m."") (Syntax: '""Nothing is ... er than m.""') ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""Nothing is larger than m."") (Syntax: '""Nothing is ... er than m.""')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
...@@ -401,7 +401,7 @@ private void M() ...@@ -401,7 +401,7 @@ private void M()
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: System.String) (Syntax: '""Result1""') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: '""Result1""')
ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""Result1"") (Syntax: '""Result1""') ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""Result1"") (Syntax: '""Result1""')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
...@@ -421,7 +421,7 @@ private void M() ...@@ -421,7 +421,7 @@ private void M()
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: System.String) (Syntax: '""Result2""') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: '""Result2""')
ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""Result2"") (Syntax: '""Result2""') ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""Result2"") (Syntax: '""Result2""')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
...@@ -433,7 +433,7 @@ private void M() ...@@ -433,7 +433,7 @@ private void M()
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: System.String) (Syntax: '""Result3""') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: '""Result3""')
ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""Result3"") (Syntax: '""Result3""') ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""Result3"") (Syntax: '""Result3""')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
...@@ -467,11 +467,11 @@ private void M() ...@@ -467,11 +467,11 @@ private void M()
Instance Receiver: Instance Receiver:
null null
Arguments(2): Arguments(2):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: s) (OperationKind.Argument, Type: System.String) (Syntax: 's') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: s) (OperationKind.Argument, Type: null) (Syntax: 's')
ILocalReferenceOperation: s (OperationKind.LocalReference, Type: System.String) (Syntax: 's') ILocalReferenceOperation: s (OperationKind.LocalReference, Type: System.String) (Syntax: 's')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: result) (OperationKind.Argument, Type: System.Int32) (Syntax: 'out var i') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: result) (OperationKind.Argument, Type: null) (Syntax: 'out var i')
IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32) (Syntax: 'var i') IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32) (Syntax: 'var i')
ILocalReferenceOperation: i (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i') ILocalReferenceOperation: i (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
...@@ -483,7 +483,7 @@ private void M() ...@@ -483,7 +483,7 @@ private void M()
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: System.String) (Syntax: '$""i ={i}, s ={s}""') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: '$""i ={i}, s ={s}""')
IInterpolatedStringOperation (OperationKind.InterpolatedString, Type: System.String) (Syntax: '$""i ={i}, s ={s}""') IInterpolatedStringOperation (OperationKind.InterpolatedString, Type: System.String) (Syntax: '$""i ={i}, s ={s}""')
Parts(4): Parts(4):
IInterpolatedStringTextOperation (OperationKind.InterpolatedStringText, Type: null) (Syntax: 'i =') IInterpolatedStringTextOperation (OperationKind.InterpolatedStringText, Type: null) (Syntax: 'i =')
...@@ -515,7 +515,7 @@ private void M() ...@@ -515,7 +515,7 @@ private void M()
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: System.String) (Syntax: '$""i ={i}, s ={s}""') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: '$""i ={i}, s ={s}""')
IInterpolatedStringOperation (OperationKind.InterpolatedString, Type: System.String) (Syntax: '$""i ={i}, s ={s}""') IInterpolatedStringOperation (OperationKind.InterpolatedString, Type: System.String) (Syntax: '$""i ={i}, s ={s}""')
Parts(4): Parts(4):
IInterpolatedStringTextOperation (OperationKind.InterpolatedStringText, Type: null) (Syntax: 'i =') IInterpolatedStringTextOperation (OperationKind.InterpolatedStringText, Type: null) (Syntax: 'i =')
...@@ -584,7 +584,7 @@ private int A() ...@@ -584,7 +584,7 @@ private int A()
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: System.Int32) (Syntax: 'A()') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: 'A()')
IInvocationOperation ( System.Int32 P.A()) (OperationKind.Invocation, Type: System.Int32) (Syntax: 'A()') IInvocationOperation ( System.Int32 P.A()) (OperationKind.Invocation, Type: System.Int32) (Syntax: 'A()')
Instance Receiver: Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: P, IsImplicit) (Syntax: 'A') IInstanceReferenceOperation (OperationKind.InstanceReference, Type: P, IsImplicit) (Syntax: 'A')
...@@ -636,16 +636,16 @@ private void A(bool flag) ...@@ -636,16 +636,16 @@ private void A(bool flag)
Instance Receiver: Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: P, IsImplicit) (Syntax: 'A') IInstanceReferenceOperation (OperationKind.InstanceReference, Type: P, IsImplicit) (Syntax: 'A')
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: flag) (OperationKind.Argument, Type: System.Boolean) (Syntax: 'int.TryPars ... out var i)') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: flag) (OperationKind.Argument, Type: null) (Syntax: 'int.TryPars ... out var i)')
IInvocationOperation (System.Boolean System.Int32.TryParse(System.String s, out System.Int32 result)) (OperationKind.Invocation, Type: System.Boolean) (Syntax: 'int.TryPars ... out var i)') IInvocationOperation (System.Boolean System.Int32.TryParse(System.String s, out System.Int32 result)) (OperationKind.Invocation, Type: System.Boolean) (Syntax: 'int.TryPars ... out var i)')
Instance Receiver: Instance Receiver:
null null
Arguments(2): Arguments(2):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: s) (OperationKind.Argument, Type: System.String) (Syntax: 's') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: s) (OperationKind.Argument, Type: null) (Syntax: 's')
ILocalReferenceOperation: s (OperationKind.LocalReference, Type: System.String) (Syntax: 's') ILocalReferenceOperation: s (OperationKind.LocalReference, Type: System.String) (Syntax: 's')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: result) (OperationKind.Argument, Type: System.Int32) (Syntax: 'out var i') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: result) (OperationKind.Argument, Type: null) (Syntax: 'out var i')
IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32) (Syntax: 'var i') IDeclarationExpressionOperation (OperationKind.DeclarationExpression, Type: System.Int32) (Syntax: 'var i')
ILocalReferenceOperation: i (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i') ILocalReferenceOperation: i (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
...@@ -696,7 +696,7 @@ private static void A(bool flag, int number) ...@@ -696,7 +696,7 @@ private static void A(bool flag, int number)
Instance Receiver: Instance Receiver:
null null
Arguments(2): Arguments(2):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: flag) (OperationKind.Argument, Type: System.Boolean) (Syntax: 'o is int i') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: flag) (OperationKind.Argument, Type: null) (Syntax: 'o is int i')
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean) (Syntax: 'o is int i') IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean) (Syntax: 'o is int i')
Expression: Expression:
ILocalReferenceOperation: o (OperationKind.LocalReference, Type: System.Object) (Syntax: 'o') ILocalReferenceOperation: o (OperationKind.LocalReference, Type: System.Object) (Syntax: 'o')
...@@ -704,7 +704,7 @@ private static void A(bool flag, int number) ...@@ -704,7 +704,7 @@ private static void A(bool flag, int number)
IDeclarationPatternOperation (Declared Symbol: System.Int32 i) (OperationKind.DeclarationPattern, Type: null) (Syntax: 'int i') IDeclarationPatternOperation (Declared Symbol: System.Int32 i) (OperationKind.DeclarationPattern, Type: null) (Syntax: 'int i')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: number) (OperationKind.Argument, Type: System.Int32) (Syntax: '1') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: number) (OperationKind.Argument, Type: null) (Syntax: '1')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
...@@ -752,7 +752,7 @@ private void M() ...@@ -752,7 +752,7 @@ private void M()
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: System.String) (Syntax: 'str') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: 'str')
ILocalReferenceOperation: str (OperationKind.LocalReference, Type: System.String) (Syntax: 'str') ILocalReferenceOperation: str (OperationKind.LocalReference, Type: System.String) (Syntax: 'str')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
...@@ -796,7 +796,7 @@ private static void A(object o) ...@@ -796,7 +796,7 @@ private static void A(object o)
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: o) (OperationKind.Argument, Type: System.Object) (Syntax: '25') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: o) (OperationKind.Argument, Type: null) (Syntax: '25')
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Object, IsImplicit) (Syntax: '25') IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Object, IsImplicit) (Syntax: '25')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand: Operand:
...@@ -849,7 +849,7 @@ private static void A(bool flag, int number) ...@@ -849,7 +849,7 @@ private static void A(bool flag, int number)
Instance Receiver: Instance Receiver:
null null
Arguments(2): Arguments(2):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: flag) (OperationKind.Argument, Type: System.Boolean) (Syntax: 'o is int i') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: flag) (OperationKind.Argument, Type: null) (Syntax: 'o is int i')
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean) (Syntax: 'o is int i') IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean) (Syntax: 'o is int i')
Expression: Expression:
ILocalReferenceOperation: o (OperationKind.LocalReference, Type: System.Object) (Syntax: 'o') ILocalReferenceOperation: o (OperationKind.LocalReference, Type: System.Object) (Syntax: 'o')
...@@ -857,7 +857,7 @@ private static void A(bool flag, int number) ...@@ -857,7 +857,7 @@ private static void A(bool flag, int number)
IDeclarationPatternOperation (Declared Symbol: System.Int32 i) (OperationKind.DeclarationPattern, Type: null) (Syntax: 'int i') IDeclarationPatternOperation (Declared Symbol: System.Int32 i) (OperationKind.DeclarationPattern, Type: null) (Syntax: 'int i')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: number) (OperationKind.Argument, Type: System.Int32) (Syntax: '1') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: number) (OperationKind.Argument, Type: null) (Syntax: '1')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
...@@ -906,7 +906,7 @@ private void M() ...@@ -906,7 +906,7 @@ private void M()
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: System.String) (Syntax: 'str') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: 'str')
ILocalReferenceOperation: str (OperationKind.LocalReference, Type: System.String) (Syntax: 'str') ILocalReferenceOperation: str (OperationKind.LocalReference, Type: System.String) (Syntax: 'str')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
...@@ -1145,7 +1145,7 @@ Type Arguments(0) ...@@ -1145,7 +1145,7 @@ Type Arguments(0)
Operand: Operand:
IParameterReferenceOperation: d (OperationKind.ParameterReference, Type: dynamic) (Syntax: 'd') IParameterReferenceOperation: d (OperationKind.ParameterReference, Type: dynamic) (Syntax: 'd')
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: System.Object) (Syntax: 'x') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: obj) (OperationKind.Argument, Type: null) (Syntax: 'x')
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Object, IsImplicit) (Syntax: 'x') IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Object, IsImplicit) (Syntax: 'x')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand: Operand:
......
...@@ -314,7 +314,7 @@ public void M() ...@@ -314,7 +314,7 @@ public void M()
Instance Receiver: Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: Class, IsImplicit) (Syntax: 'M2') IInstanceReferenceOperation (OperationKind.InstanceReference, Type: Class, IsImplicit) (Syntax: 'M2')
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: z) (OperationKind.Argument, Type: System.Int32) (Syntax: 'y') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: z) (OperationKind.Argument, Type: null) (Syntax: 'y')
ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y') ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
...@@ -369,7 +369,7 @@ public void M() ...@@ -369,7 +369,7 @@ public void M()
Instance Receiver: Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: Class, IsImplicit) (Syntax: 'M2') IInstanceReferenceOperation (OperationKind.InstanceReference, Type: Class, IsImplicit) (Syntax: 'M2')
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: z) (OperationKind.Argument, Type: System.String) (Syntax: '$""{y}""') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: z) (OperationKind.Argument, Type: null) (Syntax: '$""{y}""')
IInterpolatedStringOperation (OperationKind.InterpolatedString, Type: System.String) (Syntax: '$""{y}""') IInterpolatedStringOperation (OperationKind.InterpolatedString, Type: System.String) (Syntax: '$""{y}""')
Parts(1): Parts(1):
IInterpolationOperation (OperationKind.Interpolation, Type: null) (Syntax: '{y}') IInterpolationOperation (OperationKind.Interpolation, Type: null) (Syntax: '{y}')
......
...@@ -162,7 +162,7 @@ public void M() ...@@ -162,7 +162,7 @@ public void M()
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: p1) (OperationKind.Argument, Type: System.Int32) (Syntax: 'p1') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: p1) (OperationKind.Argument, Type: null) (Syntax: 'p1')
IParameterReferenceOperation: p1 (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'p1') IParameterReferenceOperation: p1 (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'p1')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
...@@ -194,7 +194,7 @@ public void M(int x) ...@@ -194,7 +194,7 @@ public void M(int x)
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: p1) (OperationKind.Argument, Type: System.Int32) (Syntax: 'x + p1') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: p1) (OperationKind.Argument, Type: null) (Syntax: 'x + p1')
IBinaryOperation (BinaryOperatorKind.Add) (OperationKind.BinaryOperator, Type: System.Int32) (Syntax: 'x + p1') IBinaryOperation (BinaryOperatorKind.Add) (OperationKind.BinaryOperator, Type: System.Int32) (Syntax: 'x + p1')
Left: Left:
IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'x') IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'x')
...@@ -240,7 +240,7 @@ public void M(int x) ...@@ -240,7 +240,7 @@ public void M(int x)
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: millisecondsDelay) (OperationKind.Argument, Type: System.Int32) (Syntax: '0') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: millisecondsDelay) (OperationKind.Argument, Type: null) (Syntax: '0')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0') ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
......
...@@ -364,7 +364,7 @@ public void M() ...@@ -364,7 +364,7 @@ public void M()
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: System.String) (Syntax: '""Hello World!""') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: '""Hello World!""')
ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""Hello World!"") (Syntax: '""Hello World!""') ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""Hello World!"") (Syntax: '""Hello World!""')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
......
...@@ -335,7 +335,7 @@ class C ...@@ -335,7 +335,7 @@ class C
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: System.Int32) (Syntax: '1') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: '1')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
...@@ -363,7 +363,7 @@ class C ...@@ -363,7 +363,7 @@ class C
Instance Receiver: Instance Receiver:
null null
Arguments(1): Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: System.Int32) (Syntax: '2') IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: '2')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2') ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) 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) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
......
...@@ -27,13 +27,15 @@ static void Main(string[] args) ...@@ -27,13 +27,15 @@ static void Main(string[] args)
} }
"; ";
string expectedOperationTree = @" string expectedOperationTree = @"
IVariableDeclarationsOperation (2 declarations) (OperationKind.VariableDeclarations, Type: null, IsInvalid) (Syntax: 'int x, ( 1 );') IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsInvalid) (Syntax: 'int x, ( 1 );')
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'x') IVariableDeclarationOperation (2 declarators) (OperationKind.VariableDeclaration, Type: null, IsInvalid) (Syntax: 'int x, ( 1 ')
Variables: Local_1: System.Int32 x Declarators:
Initializer: IVariableDeclaratorOperation (Symbol: System.Int32 x) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'x')
null Initializer:
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null, IsInvalid) (Syntax: '( 1 ') null
Variables: Local_1: System.Int32 IVariableDeclaratorOperation (Symbol: System.Int32 ) (OperationKind.VariableDeclarator, Type: null, IsInvalid) (Syntax: '( 1 ')
Initializer:
null
Initializer: Initializer:
null null
"; ";
......
...@@ -78,7 +78,7 @@ public IOperation GetOperation(SyntaxNode node, CancellationToken cancellationTo ...@@ -78,7 +78,7 @@ public IOperation GetOperation(SyntaxNode node, CancellationToken cancellationTo
catch (Exception e) when (FatalError.ReportWithoutCrashUnlessCanceled(e)) catch (Exception e) when (FatalError.ReportWithoutCrashUnlessCanceled(e))
{ {
// Log a Non-fatal-watson and then ignore the crash in the attempt of getting operation // 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; return null;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
namespace Microsoft.CodeAnalysis.Operations namespace Microsoft.CodeAnalysis.Operations
{ {
/// <summary> /// <summary>
/// Represents a declaration expression operation. Unlike a regular variable declaration <see cref="IVariableDeclarationOperation"/>, this operation represents an "expression" declaring a variable. /// Represents a declaration expression operation. Unlike a regular variable declaration <see cref="IVariableDeclaratorOperation"/> and <see cref="IVariableDeclarationOperation"/>, this operation represents an "expression" declaring a variable.
/// <para> /// <para>
/// Current usage: /// Current usage:
/// (1) C# declaration expression. For example, /// (1) C# declaration expression. For example,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册