未验证 提交 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
var indexerAccess = (BoundIndexerAccess)expr;
if (valueKind == BindValueKind.Assignable && !indexerAccess.Indexer.ReturnsByRef)
{
expr = indexerAccess.Update(indexerAccess.ReceiverOpt,
indexerAccess.Indexer,
indexerAccess.Arguments,
indexerAccess.ArgumentNamesOpt,
indexerAccess.ArgumentRefKindsOpt,
indexerAccess.Expanded,
indexerAccess.ArgsToParamsOpt,
indexerAccess.BinderOpt,
useSetterForDefaultArgumentGeneration: true,
type: indexerAccess.Type);
expr = indexerAccess.Update(useSetterForDefaultArgumentGeneration: true);
}
}
break;
......
......@@ -6535,7 +6535,8 @@ private BoundExpression BindPointerElementAccess(ExpressionSyntax node, BoundExp
{
Error(diagnostics, ErrorCode.ERR_PtrIndexSingle, node);
}
return new BoundPointerElementAccess(node, expr, BadExpression(node, BuildArgumentsForErrorRecovery(analyzedArguments)), CheckOverflowAtRuntime, pointedAtType, hasErrors: true);
return new BoundPointerElementAccess(node, expr, BadExpression(node, BuildArgumentsForErrorRecovery(analyzedArguments)).MakeCompilerGenerated(),
CheckOverflowAtRuntime, pointedAtType, hasErrors: true);
}
if (pointedAtType.SpecialType == SpecialType.System_Void)
......@@ -7192,11 +7193,6 @@ private BoundExpression GetReceiverForConditionalBinding(ExpressionSyntax bindin
receiver = BindConditionalAccessReceiver(conditionalAccessNode, diagnostics);
}
if (receiver.HasAnyErrors)
{
return receiver;
}
// create surrogate receiver
var receiverType = receiver.Type;
if (receiverType?.IsNullableType() == true)
......@@ -7204,7 +7200,7 @@ private BoundExpression GetReceiverForConditionalBinding(ExpressionSyntax bindin
receiverType = receiverType.GetNullableUnderlyingType();
}
receiver = new BoundConditionalReceiver(receiver.Syntax, 0, receiverType) { WasCompilerGenerated = true };
receiver = new BoundConditionalReceiver(receiver.Syntax, 0, receiverType ?? CreateErrorType(), hasErrors: receiver.HasErrors) { WasCompilerGenerated = true };
return receiver;
}
......
......@@ -2605,7 +2605,7 @@ private bool IsOperandErrors(CSharpSyntaxNode node, ref BoundExpression operand,
if (!operand.HasAnyErrors)
{
Error(diagnostics, ErrorCode.ERR_LambdaInIsAs, node);
operand = BadExpression(node, operand);
operand = BadExpression(node, operand).MakeCompilerGenerated();
}
return true;
......
......@@ -198,7 +198,7 @@ private BoundStatement BindYieldReturnStatement(YieldStatementSyntax node, Diagn
TypeSymbol elementType = binder.GetIteratorElementType(node, diagnostics);
BoundExpression argument = (node.Expression == null)
? BadExpression(node)
? BadExpression(node).MakeCompilerGenerated()
: binder.BindValue(node.Expression, diagnostics, BindValueKind.RValue);
argument = ValidateEscape(argument, ExternalScope, isByRef: false, diagnostics: diagnostics);
......
......@@ -167,6 +167,34 @@ public override Symbol ExpressionSymbol
// DevDiv 1087283 tracks deciding whether or not to refactor this into BoundNodes.xml.
public ImmutableArray<PropertySymbol> OriginalIndexersOpt { get; private set; }
public BoundIndexerAccess Update(bool useSetterForDefaultArgumentGeneration)
{
if (useSetterForDefaultArgumentGeneration != this.UseSetterForDefaultArgumentGeneration)
{
var result = new BoundIndexerAccess(
this.Syntax,
this.ReceiverOpt,
this.Indexer,
this.Arguments,
this.ArgumentNamesOpt,
this.ArgumentRefKindsOpt,
this.Expanded,
this.ArgsToParamsOpt,
this.BinderOpt,
useSetterForDefaultArgumentGeneration,
this.Type,
this.HasErrors)
{
WasCompilerGenerated = this.WasCompilerGenerated,
OriginalIndexersOpt = this.OriginalIndexersOpt
};
return result;
}
return this;
}
public override LookupResultKind ResultKind
{
get
......
......@@ -59,5 +59,11 @@ public static bool IsConstructorInitializer(this BoundCall call)
receiverOpt != null &&
(receiverOpt.Kind == BoundKind.ThisReference || receiverOpt.Kind == BoundKind.BaseReference);
}
public static T MakeCompilerGenerated<T>(this T node) where T : BoundNode
{
node.WasCompilerGenerated = true;
return node;
}
}
}
......@@ -139,7 +139,7 @@ private bool IsDebugPlus()
private bool EnablePEVerifyCompat()
{
return _module.Compilation.FeaturePEVerifyCompatEnabled;
return _module.Compilation.LanguageVersion < LanguageVersion.CSharp7_2 || _module.Compilation.FeaturePEVerifyCompatEnabled;
}
private LocalDefinition LazyReturnTemp
......
......@@ -24,8 +24,14 @@ private enum AddressKind
// reference itself will not be written to, nor it will be used to modify fields.
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>
/// Emits address as in &amp;
///
......@@ -70,7 +76,7 @@ private LocalDefinition EmitAddress(BoundExpression expression, AddressKind addr
case BoundKind.ThisReference:
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);
break;
......@@ -101,7 +107,7 @@ private LocalDefinition EmitAddress(BoundExpression expression, AddressKind addr
var methodRefKind = call.Method.RefKind;
if (methodRefKind == RefKind.Ref ||
(addressKind == AddressKind.ReadOnly && methodRefKind == RefKind.RefReadOnly))
(IsReadOnly(addressKind) && methodRefKind == RefKind.RefReadOnly))
{
EmitCallExpression(call, UseKind.UsedAsAddress);
break;
......@@ -121,7 +127,7 @@ private LocalDefinition EmitAddress(BoundExpression expression, AddressKind addr
case BoundKind.ConditionalOperator:
var conditional = (BoundConditionalOperator)expression;
if (!HasHome(conditional, addressKind != AddressKind.ReadOnly))
if (!HasHome(conditional, addressKind))
{
goto default;
}
......@@ -144,7 +150,7 @@ private LocalDefinition EmitAddress(BoundExpression expression, AddressKind addr
return null;
default:
Debug.Assert(!HasHome(expression, addressKind != AddressKind.ReadOnly));
Debug.Assert(!HasHome(expression, addressKind));
return EmitAddressOfTempClone(expression);
}
......@@ -218,7 +224,7 @@ private LocalDefinition EmitLocalAddress(BoundLocal localAccess, AddressKind add
{
var local = localAccess.LocalSymbol;
if (!HasHome(localAccess, needWriteable: addressKind != AddressKind.ReadOnly))
if (!HasHome(localAccess, addressKind))
{
return EmitAddressOfTempClone(localAccess);
}
......@@ -249,7 +255,7 @@ private LocalDefinition EmitLocalAddress(BoundLocal localAccess, AddressKind add
/// </summary>
private LocalDefinition EmitDupAddress(BoundDup dup, AddressKind addressKind)
{
if (!HasHome(dup, needWriteable: addressKind != AddressKind.ReadOnly))
if (!HasHome(dup, addressKind))
{
return EmitAddressOfTempClone(dup);
}
......@@ -339,7 +345,7 @@ private LocalSymbol DigForValueLocal(BoundSequence topSequence, BoundExpression
/// 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.
/// </summary>
private bool HasHome(BoundExpression expression, bool needWriteable)
private bool HasHome(BoundExpression expression, AddressKind addressKind)
{
switch (expression.Kind)
{
......@@ -352,10 +358,11 @@ private bool HasHome(BoundExpression expression, bool needWriteable)
case BoundKind.ThisReference:
Debug.Assert(expression.Type.IsValueType);
if (needWriteable && expression.Type.IsReadOnly)
if (!IsReadOnly(addressKind) && expression.Type.IsReadOnly)
{
return _method.MethodKind == MethodKind.Constructor;
}
return true;
case BoundKind.ThrowExpression:
......@@ -363,7 +370,7 @@ private bool HasHome(BoundExpression expression, bool needWriteable)
return true;
case BoundKind.Parameter:
return !needWriteable ||
return IsReadOnly(addressKind) ||
((BoundParameter)expression).ParameterSymbol.RefKind != RefKind.In;
case BoundKind.Local:
......@@ -371,31 +378,31 @@ private bool HasHome(BoundExpression expression, bool needWriteable)
// locals in a mutating call
var local = ((BoundLocal)expression).LocalSymbol;
return !((IsStackLocal(local) && local.RefKind == RefKind.None) ||
(needWriteable && local.RefKind == RefKind.RefReadOnly));
(!IsReadOnly(addressKind) && local.RefKind == RefKind.RefReadOnly));
case BoundKind.Call:
var methodRefKind = ((BoundCall)expression).Method.RefKind;
return methodRefKind == RefKind.Ref ||
(!needWriteable && methodRefKind == RefKind.RefReadOnly);
(IsReadOnly(addressKind) && methodRefKind == RefKind.RefReadOnly);
case BoundKind.Dup:
//NB: Dup represents locals that do not need IL slot
var dupRefKind = ((BoundDup)expression).RefKind;
return dupRefKind == RefKind.Ref ||
(!needWriteable && dupRefKind == RefKind.RefReadOnly);
(IsReadOnly(addressKind) && dupRefKind == RefKind.RefReadOnly);
case BoundKind.FieldAccess:
return HasHome((BoundFieldAccess)expression, needWriteable);
return HasHome((BoundFieldAccess)expression, addressKind);
case BoundKind.Sequence:
return HasHome(((BoundSequence)expression).Value, needWriteable);
return HasHome(((BoundSequence)expression).Value, addressKind);
case BoundKind.AssignmentOperator:
return ((BoundAssignmentOperator)expression).RefKind != RefKind.None;
case BoundKind.ComplexConditionalReceiver:
Debug.Assert(HasHome(((BoundComplexConditionalReceiver)expression).ValueTypeReceiver, needWriteable));
Debug.Assert(HasHome(((BoundComplexConditionalReceiver)expression).ReferenceTypeReceiver, needWriteable));
Debug.Assert(HasHome(((BoundComplexConditionalReceiver)expression).ValueTypeReceiver, addressKind));
Debug.Assert(HasHome(((BoundComplexConditionalReceiver)expression).ReferenceTypeReceiver, addressKind));
goto case BoundKind.ConditionalReceiver;
case BoundKind.ConditionalReceiver:
......@@ -415,7 +422,7 @@ private bool HasHome(BoundExpression expression, bool needWriteable)
// branch that has no home will need a temporary
// if both have no home, just say whole expression has no home
// 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:
return false;
......@@ -427,7 +434,7 @@ private bool HasHome(BoundExpression expression, bool needWriteable)
/// Fields have readable homes when they are not constants.
/// Fields have writeable homes unless they are readonly and used outside of the constructor.
/// </summary>
private bool HasHome(BoundFieldAccess fieldAccess, bool needWriteable)
private bool HasHome(BoundFieldAccess fieldAccess, AddressKind addressKind)
{
FieldSymbol field = fieldAccess.FieldSymbol;
......@@ -437,7 +444,14 @@ private bool HasHome(BoundFieldAccess fieldAccess, bool needWriteable)
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;
}
......@@ -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.
if (!EnablePEVerifyCompat())
{
Debug.Assert(needWriteable == true);
Debug.Assert(!IsReadOnly(addressKind));
var receiver = fieldAccess.ReceiverOpt;
if (receiver?.Type.IsValueType == true)
......@@ -466,8 +480,8 @@ private bool HasHome(BoundFieldAccess fieldAccess, bool needWriteable)
// 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
return HasHome(receiver, needWriteable: true) ||
!HasHome(receiver, needWriteable: false);
return HasHome(receiver, addressKind) ||
!HasHome(receiver, AddressKind.ReadOnly);
}
}
......@@ -534,7 +548,7 @@ private LocalDefinition EmitFieldAddress(BoundFieldAccess fieldAccess, AddressKi
{
FieldSymbol field = fieldAccess.FieldSymbol;
if (!HasHome(fieldAccess, addressKind != AddressKind.ReadOnly))
if (!HasHome(fieldAccess, addressKind))
{
// accessing a field that is not writable (const or readonly)
return EmitAddressOfTempClone(fieldAccess);
......@@ -546,11 +560,7 @@ private LocalDefinition EmitFieldAddress(BoundFieldAccess fieldAccess, AddressKi
}
else
{
//NOTE: we are not propagating AddressKind here.
// 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);
return EmitInstanceFieldAddress(fieldAccess, addressKind);
}
}
......@@ -564,7 +574,7 @@ private LocalDefinition EmitParameterAddress(BoundParameter parameter, AddressKi
{
ParameterSymbol parameterSymbol = parameter.ParameterSymbol;
if (!HasHome(parameter, needWriteable: addressKind != AddressKind.ReadOnly))
if (!HasHome(parameter, addressKind))
{
// accessing a parameter that is not writable
return EmitAddressOfTempClone(parameter);
......@@ -634,11 +644,14 @@ private LocalDefinition EmitReceiverRef(BoundExpression receiver, AddressKind ad
/// <summary>
/// May introduce a temp which it will return. (otherwise returns null)
/// </summary>
private LocalDefinition EmitInstanceFieldAddress(BoundFieldAccess fieldAccess, bool isReadonly)
private LocalDefinition EmitInstanceFieldAddress(BoundFieldAccess fieldAccess, AddressKind addressKind)
{
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);
EmitSymbolToken(field, fieldAccess.Syntax);
......
......@@ -426,10 +426,7 @@ private void EmitLoweredConditionalAccessExpression(BoundLoweredConditionalAcces
{
// this does not need to be writeable
// we may call "HasValue" on this, but it is not mutating
// (however verification does not know that and considers all calls mutating)
var addressKind = EnablePEVerifyCompat()?
AddressKind.Writeable:
AddressKind.ReadOnly;
var addressKind = AddressKind.ReadOnly;
receiverTemp = EmitReceiverRef(receiver, addressKind);
_builder.EmitOpCode(ILOpCode.Dup);
......@@ -605,7 +602,9 @@ private void EmitArgument(BoundExpression argument, RefKind refKind)
break;
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)
{
// interestingly enough "ref dynamic" sometimes is passed via a clone
......@@ -619,8 +618,11 @@ private void EmitArgument(BoundExpression argument, RefKind refKind)
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.");
if (used)
{
// 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)
}
}
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.
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++)
{
BoundExpression argument = arguments[i];
RefKind refKind = (i == parameters.Length) ? RefKind.None : parameters[i].RefKind;
EmitArgument(argument, refKind);
RefKind 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)
}
// can we take address at all?
if (!HasHome(receiver, needWriteable: false))
if (!HasHome(receiver, AddressKind.ReadOnly))
{
return false;
}
......@@ -1491,13 +1510,8 @@ private void EmitCallExpression(BoundCall call, UseKind useKind)
if (method.IsMetadataVirtual())
{
// NB: all methods that a struct could inherit from bases are non-mutating
// we are passing here "Writeable" just to keep verifier happy
// we can pass here "ReadOnly" and avoid unnecessary copy
var addressKind = EnablePEVerifyCompat() ?
AddressKind.Writeable :
AddressKind.ReadOnly;
tempOpt = EmitReceiverRef(receiver, addressKind);
// treat receiver as ReadOnly
tempOpt = EmitReceiverRef(receiver, AddressKind.ReadOnly);
callKind = CallKind.ConstrainedCallVirt;
}
else
......@@ -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);
switch (callKind)
{
......@@ -1861,7 +1875,7 @@ private void EmitObjectCreationExpression(BoundObjectCreationExpression expressi
}
else
{
EmitArguments(expression.Arguments, constructor.Parameters);
EmitArguments(expression.Arguments, constructor.Parameters, expression.ArgumentRefKindsOpt);
var stackAdjustment = GetObjCreationStackBehavior(expression);
_builder.EmitOpCode(ILOpCode.Newobj, stackAdjustment);
......@@ -2033,7 +2047,7 @@ private bool TryEmitAssignmentInPlace(BoundAssignmentOperator assignmentOperator
private bool SafeToGetWriteableReference(BoundExpression left)
{
if (!HasHome(left, needWriteable: true))
if (!HasHome(left, AddressKind.Writeable))
{
return false;
}
......@@ -2079,7 +2093,7 @@ private void InPlaceCtorCall(BoundExpression target, BoundObjectCreationExpressi
Debug.Assert(temp == null, "in-place ctor target should not create temps");
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.
var stackAdjustment = GetObjCreationStackBehavior(objCreation) - 2;
_builder.EmitOpCode(ILOpCode.Call, stackAdjustment);
......@@ -2335,10 +2349,11 @@ private void EmitAssignmentValue(BoundAssignmentOperator assignmentOperator)
else
{
int exprTempsBefore = _expressionTemps?.Count ?? 0;
var local = ((BoundLocal)assignmentOperator.Left).LocalSymbol;
// NOTE: passing "ReadOnly" here. Assuming we do not have compile errors,
// We should not get an address of a copy, even if the RHS is readonly
LocalDefinition temp = EmitAddress(assignmentOperator.Right, AddressKind.ReadOnly);
// NOTE: passing "ReadOnlyStrict" here.
// we should not get an address of a copy if at all possible
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
// 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)
AddExpressionTemp(temp);
// 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;
......
......@@ -724,7 +724,10 @@ private void EmitReturnStatement(BoundReturnStatement boundReturnStatement)
}
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())
......
......@@ -2152,7 +2152,7 @@ internal override SyntaxNode GetDeclaratorSyntax()
throw new NotImplementedException();
}
internal override RefKind RefKind
public override RefKind RefKind
{
get { return RefKind.None; }
}
......
......@@ -163,9 +163,6 @@ internal override Binder GetEnclosingBinderInternal(int position)
internal override IOperation GetOperationWorker(CSharpSyntaxNode node, CancellationToken cancellationToken)
{
// in case this is right side of a qualified name or member access (or part of a cref)
node = SyntaxFactory.GetStandaloneNode(node);
var model = this.GetMemberModel(node);
if (model != null)
{
......
......@@ -211,7 +211,7 @@ protected override ImmutableArray<Declaration> GetDeclarationChildren()
return StaticCast<Declaration>.From(this.Children);
}
public IEnumerable<string> MemberNames
public ICollection<string> MemberNames
{
get
{
......
......@@ -718,7 +718,6 @@ private static ImmutableArray<RefKind> GetRefKindsOrNull(ArrayBuilder<RefKind> r
if (IsSafeForReordering(argument, argRefKind))
{
arguments[p] = argument;
refKinds[p] = argRefKind;
}
else
{
......@@ -727,6 +726,7 @@ private static ImmutableArray<RefKind> GetRefKindsOrNull(ArrayBuilder<RefKind> r
storesToTemps.Add(assignment);
arguments[p] = temp;
}
refKinds[p] = argRefKind;
}
}
......
......@@ -254,8 +254,10 @@ public override BoundNode VisitFixedLocalCollectionInitializer(BoundFixedLocalCo
pinnedTemp = factory.SynthesizedLocal(
initializerType,
syntax: declarator,
isPinned: true,
refKind: RefKind.Ref, // different from the array and string cases
isPinned: true,
//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);
// NOTE: we pin the reference, not the pointer.
......
......@@ -1269,7 +1269,7 @@ internal static BoundExpression NullOrDefault(TypeSymbol typeSymbol, SyntaxNode
#endif
)
{
if (refKind == RefKind.Out || refKind == RefKind.In)
if (refKind == RefKind.Out)
{
refKind = RefKind.Ref;
}
......
......@@ -7,8 +7,8 @@ namespace Microsoft.CodeAnalysis.CSharp
{
internal abstract class BaseCSharpArgument : BaseArgument
{
public BaseCSharpArgument(ArgumentKind argumentKind, IParameterSymbol parameter, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) :
base(argumentKind, parameter, semanticModel, syntax, type, constantValue, isImplicit)
public BaseCSharpArgument(ArgumentKind argumentKind, IParameterSymbol parameter, SemanticModel semanticModel, SyntaxNode syntax, Optional<object> constantValue, bool isImplicit) :
base(argumentKind, parameter, semanticModel, syntax, constantValue, isImplicit)
{
}
......@@ -19,8 +19,8 @@ internal abstract class BaseCSharpArgument : BaseArgument
internal sealed class CSharpArgument : BaseCSharpArgument
{
public CSharpArgument(ArgumentKind argumentKind, IParameterSymbol parameter, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) :
base(argumentKind, parameter, semanticModel, syntax, type, constantValue, isImplicit)
public CSharpArgument(ArgumentKind argumentKind, IParameterSymbol parameter, IOperation value, SemanticModel semanticModel, SyntaxNode syntax, Optional<object> constantValue, bool isImplicit) :
base(argumentKind, parameter, semanticModel, syntax, constantValue, isImplicit)
{
ValueImpl = value;
}
......@@ -32,11 +32,11 @@ internal sealed class LazyCSharpArgument : BaseCSharpArgument
{
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) :
base(argumentKind, parameter, semanticModel, syntax, type, constantValue, isImplicit)
public LazyCSharpArgument(ArgumentKind argumentKind, IParameterSymbol parameter, Lazy<IOperation> value, SemanticModel semanticModel, SyntaxNode syntax, Optional<object> constantValue, bool isImplicit) :
base(argumentKind, parameter, semanticModel, syntax, constantValue, isImplicit)
{
_lazyValue = value ?? throw new ArgumentNullException(nameof(value));
}
}
protected override IOperation ValueImpl => _lazyValue.Value;
}
......
......@@ -10,7 +10,7 @@ internal class CSharpOperationCloner : OperationCloner
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)
......
......@@ -46,19 +46,18 @@ internal IArgumentOperation CreateArgumentOperation(ArgumentKind kind, IParamete
value,
semanticModel: _semanticModel,
syntax: argument ?? value.Syntax,
type: value.Type,
constantValue: default,
isImplicit: expression.WasCompilerGenerated || argument == null);
}
private IVariableDeclarationOperation CreateVariableDeclarationInternal(BoundLocalDeclaration boundLocalDeclaration, SyntaxNode syntax)
private IVariableDeclaratorOperation CreateVariableDeclaratorInternal(BoundLocalDeclaration boundLocalDeclaration, SyntaxNode syntax)
{
IVariableInitializerOperation initializer = null;
if (boundLocalDeclaration.InitializerOpt != null)
{
IOperation initializerValue = Create(boundLocalDeclaration.InitializerOpt);
SyntaxNode initializerSyntax = null;
bool isImplicit = false;
bool initializerIsImplicit = false;
if (syntax is VariableDeclaratorSyntax variableDeclarator)
{
initializerSyntax = variableDeclarator.Initializer;
......@@ -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.
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)
......@@ -193,7 +198,8 @@ private ImmutableArray<IOperation> GetAnonymousObjectCreationInitializers(BoundA
SyntaxNode syntax = value.Syntax?.Parent ?? expression.Syntax;
ITypeSymbol type = target.Type;
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);
}
......
......@@ -183,6 +183,12 @@ public override void VisitLocal(ILocalSymbol symbol)
{
AddKeyword(SyntaxKind.RefKeyword);
AddSpace();
if (symbol.RefKind == RefKind.RefReadOnly)
{
AddKeyword(SyntaxKind.ReadOnlyKeyword);
AddSpace();
}
}
if (format.LocalOptions.IncludesOption(SymbolDisplayLocalOptions.IncludeType))
......
......@@ -321,9 +321,9 @@ public object ConstantValue
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;
}
......
......@@ -458,7 +458,7 @@ internal override ImmutableArray<Diagnostic> GetConstantValueDiagnostics(BoundEx
return ImmutableArray<Diagnostic>.Empty;
}
internal override RefKind RefKind
public override RefKind RefKind
{
get { return _refKind; }
}
......
......@@ -1219,7 +1219,7 @@ public sealed override ImmutableArray<Symbol> GetMembers(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);
}
......
......@@ -74,7 +74,7 @@ internal override LocalSymbol WithSynthesizedLocalKindAndSyntax(SynthesizedLocal
_refKind);
}
internal override RefKind RefKind
public override RefKind RefKind
{
get { return _refKind; }
}
......
......@@ -88,7 +88,7 @@ internal override bool IsPinned
get { return _originalVariable.IsPinned; }
}
internal override RefKind RefKind
public override RefKind RefKind
{
get { return _originalVariable.RefKind; }
}
......
......@@ -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]
public void InParamPassRoParamReturn()
{
......@@ -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]
public void InParamAsyncSpill2()
{
......
......@@ -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", @"
{
// Code size 65 (0x41)
// Code size 59 (0x3b)
.maxstack 2
.locals init (S V_0,
S V_1,
S2 V_2)
.locals init (S V_0)
IL_0000: ldsflda ""S C.s1""
IL_0005: dup
IL_0006: ldobj ""S""
IL_000b: stloc.0
IL_000c: ldloca.s V_0
IL_000e: call ""void S.AddOne()""
IL_0013: ldsfld ""S C.s2""
IL_0018: stloc.0
IL_0019: ldloca.s V_0
IL_001b: ldobj ""S""
IL_0020: stloc.1
IL_0021: ldloca.s V_1
IL_0023: call ""void S.AddOne()""
IL_0028: ldsflda ""S2 C.s3""
IL_002d: call ""void S2.AddOne()""
IL_0032: ldarg.0
IL_0033: ldfld ""S2 C.s4""
IL_0038: stloc.2
IL_0039: ldloca.s V_2
IL_003b: call ""void S2.AddOne()""
IL_0040: ret
IL_0013: ldsflda ""S C.s2""
IL_0018: ldobj ""S""
IL_001d: stloc.0
IL_001e: ldloca.s V_0
IL_0020: call ""void S.AddOne()""
IL_0025: ldsflda ""S2 C.s3""
IL_002a: call ""void S2.AddOne()""
IL_002f: ldarg.0
IL_0030: ldflda ""S2 C.s4""
IL_0035: call ""void S2.AddOne()""
IL_003a: ret
}");
comp = CompileAndVerify(source, verify: false);
......@@ -864,47 +859,36 @@ .maxstack 1
IL_0033: ldflda ""int System.ValueTuple<int, int>.Item1""
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", @"
{
// Code size 70 (0x46)
// Code size 57 (0x39)
.maxstack 1
.locals init (bool V_0, //b
int V_1,
System.ValueTuple<int, int> V_2,
int V_3,
System.ValueTuple<int, int> V_4)
.locals init (bool V_0) //b
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: brfalse.s IL_0020
IL_0003: brfalse.s IL_001a
IL_0005: ldloc.0
IL_0006: brfalse.s IL_0012
IL_0006: brfalse.s IL_000f
IL_0008: ldarg.0
IL_0009: ldfld ""int Program.F""
IL_000e: stloc.1
IL_000f: ldloca.s V_1
IL_0011: ret
IL_0012: ldsfld ""(int Alice, int Bob) Program.F1""
IL_0017: stloc.2
IL_0018: ldloca.s V_2
IL_001a: ldflda ""int System.ValueTuple<int, int>.Item1""
IL_001f: ret
IL_0020: ldloc.0
IL_0021: brfalse.s IL_0032
IL_0023: ldarg.0
IL_0024: ldfld ""Program.S Program.S1""
IL_0029: ldfld ""int Program.S.F""
IL_002e: stloc.3
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
IL_0009: ldflda ""int Program.F""
IL_000e: ret
IL_000f: ldsflda ""(int Alice, int Bob) Program.F1""
IL_0014: ldflda ""int System.ValueTuple<int, int>.Item1""
IL_0019: ret
IL_001a: ldloc.0
IL_001b: brfalse.s IL_0029
IL_001d: ldarg.0
IL_001e: ldflda ""Program.S Program.S1""
IL_0023: ldflda ""int Program.S.F""
IL_0028: ret
IL_0029: ldsflda ""Program.S Program.S2""
IL_002e: ldflda ""(int Alice, int Bob) Program.S.F1""
IL_0033: ldflda ""int System.ValueTuple<int, int>.Item1""
IL_0038: ret
}");
}
......
......@@ -12025,7 +12025,7 @@ public MyManagedStruct(int 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",
@"
......@@ -12088,6 +12088,38 @@ .locals init (MyManagedStruct V_0)
IL_0046: call ""void System.Console.WriteLine(int)""
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()
compilation.VerifyDiagnostics();
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) };
compilation.VerifyAnalyzerDiagnostics(analyzers, null, null, true,
......
......@@ -8,6 +8,7 @@
using Roslyn.Test.Utilities;
using Xunit;
using Microsoft.CodeAnalysis.UnitTests.Diagnostics;
using static Microsoft.CodeAnalysis.CommonDiagnosticAnalyzers;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
......@@ -1883,5 +1884,33 @@ public void M()
Diagnostic(TrueFalseUnaryOperationTestAnalyzer.UnaryTrueDescriptor.Id, "x && y").WithLocation(29, 13),
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)
Instance Receiver:
null
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')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
Operand:
......@@ -126,6 +126,27 @@ public void TestClone()
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)]
[Fact]
public void TestParentOperations()
......@@ -138,5 +159,45 @@ public void TestParentOperations()
VerifyParentOperations(model);
}
[CompilerTrait(CompilerFeature.IOperation)]
[WorkItem(23001, "https://github.com/dotnet/roslyn/issues/23001")]
[Fact]
public void TestGetOperationForQualifiedName()
{
var text = @"using System;
public class Test
{
class A
{
public B b;
}
class B
{
}
void M(A a)
{
int x2 = /*<bind>*/a.b/*</bind>*/;
}
}
";
var comp = CreateStandardCompilation(text);
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)
}
";
string expectedOperationTree = @"
IVariableDeclarationsOperation (1 declarations) (OperationKind.VariableDeclarations, Type: null) (Syntax: 'int[] x = { 1, 2 };')
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'x = { 1, 2 }')
Variables: Local_1: System.Int32[] x
Initializer:
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 }')
IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'int[] x = { 1, 2 };')
IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'int[] x = { 1, 2 }')
Declarators:
IVariableDeclaratorOperation (Symbol: System.Int32[] x) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'x = { 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')
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:
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;
......
......@@ -200,9 +200,12 @@ static void M(Task<int> t)
}
";
string expectedOperationTree = @"
IVariableDeclarationsOperation (1 declarations) (OperationKind.VariableDeclarations, Type: null, IsInvalid) (Syntax: 'await t;')
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null, IsInvalid) (Syntax: 't')
Variables: Local_1: await t
IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsInvalid) (Syntax: 'await t;')
IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null, IsInvalid) (Syntax: 'await t')
Declarators:
IVariableDeclaratorOperation (Symbol: await t) (OperationKind.VariableDeclarator, Type: null, IsInvalid) (Syntax: 't')
Initializer:
null
Initializer:
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
Instance Receiver:
null
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)')
Left:
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
Instance Receiver:
null
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)')
Left:
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()
string expectedOperationTree = @"
IOperation: (OperationKind.None, Type: null) (Syntax: 'fixed(int * ... }')
Children(2):
IVariableDeclarationsOperation (1 declarations) (OperationKind.VariableDeclarations, Type: null) (Syntax: 'int *p = &i')
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'p = &i')
Variables: Local_1: System.Int32* p
IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsImplicit) (Syntax: 'int *p = &i')
IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'int *p = &i')
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:
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')
null
IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'Console.Wri ... is {*p}"");')
Expression:
......@@ -54,7 +57,7 @@ void M1()
Instance Receiver:
null
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}""')
Parts(2):
IInterpolatedStringTextOperation (OperationKind.InterpolatedStringText, Type: null) (Syntax: 'P is ')
......@@ -106,29 +109,31 @@ void M1()
string expectedOperationTree = @"
IOperation: (OperationKind.None, Type: null) (Syntax: 'fixed (int* ... }')
Children(2):
IVariableDeclarationsOperation (2 declarations) (OperationKind.VariableDeclarations, Type: null) (Syntax: 'int* p1 = &i1, p2 = &i2')
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'p1 = &i1')
Variables: Local_1: System.Int32* p1
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')
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'p2 = &i2')
Variables: Local_1: System.Int32* p2
IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsImplicit) (Syntax: 'int* p1 = &i1, p2 = &i2')
IVariableDeclarationOperation (2 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'int* p1 = &i1, p2 = &i2')
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')
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:
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')
null
IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i3 = *p1 + *p2;')
Expression:
......@@ -183,32 +188,38 @@ void M1()
string expectedOperationTree = @"
IOperation: (OperationKind.None, Type: null) (Syntax: 'fixed (int* ... }')
Children(2):
IVariableDeclarationsOperation (1 declarations) (OperationKind.VariableDeclarations, Type: null) (Syntax: 'int* p1 = &i1')
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'p1 = &i1')
Variables: Local_1: System.Int32* p1
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')
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
IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsImplicit) (Syntax: 'int* p1 = &i1')
IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'int* p1 = &i1')
Declarators:
IVariableDeclaratorOperation (Symbol: System.Int32* p1) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'p1 = &i1')
Initializer:
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= &i2')
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: '&i2')
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= &i1')
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: '&i1')
Children(1):
IAddressOfOperation (OperationKind.AddressOf, Type: System.Int32*) (Syntax: '&i2')
IAddressOfOperation (OperationKind.AddressOf, Type: System.Int32*) (Syntax: '&i1')
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:
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: '{ ... }')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i3 = *p1 + *p2;')
Expression:
......@@ -258,13 +269,16 @@ void M1()
string expectedOperationTree = @"
IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'fixed (int* ... }')
Children(2):
IVariableDeclarationsOperation (1 declarations) (OperationKind.VariableDeclarations, Type: null, IsInvalid) (Syntax: 'int* p1 =')
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null, IsInvalid) (Syntax: 'p1 =')
Variables: Local_1: System.Int32* p1
IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsInvalid, IsImplicit) (Syntax: 'int* p1 =')
IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null, IsInvalid) (Syntax: 'int* 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:
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null, IsInvalid) (Syntax: '=')
IInvalidOperation (OperationKind.Invalid, Type: null, IsInvalid) (Syntax: '')
Children(0)
null
IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i3 = *p1;')
Expression:
......@@ -313,18 +327,21 @@ void M1()
string expectedOperationTree = @"
IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'fixed (int* ... }')
Children(2):
IVariableDeclarationsOperation (1 declarations) (OperationKind.VariableDeclarations, Type: null) (Syntax: 'int* p1 = &i1')
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'p1 = &i1')
Variables: Local_1: System.Int32* p1
IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsImplicit) (Syntax: 'int* p1 = &i1')
IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'int* p1 = &i1')
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:
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')
null
IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid) (Syntax: '{ ... }')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: 'i3 = &p1;')
Expression:
......
......@@ -205,7 +205,7 @@ private void M()
Instance Receiver:
null
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')
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)
......@@ -219,7 +219,7 @@ private void M()
Instance Receiver:
null
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')
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)
......@@ -277,7 +277,7 @@ private void M()
Instance Receiver:
null
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')
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)
......@@ -289,7 +289,7 @@ private void M()
Instance Receiver:
null
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')
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)
......@@ -345,7 +345,7 @@ private void M()
Instance Receiver:
null
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.""')
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)
......@@ -401,7 +401,7 @@ private void M()
Instance Receiver:
null
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""')
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)
......@@ -421,7 +421,7 @@ private void M()
Instance Receiver:
null
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""')
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)
......@@ -433,7 +433,7 @@ private void M()
Instance Receiver:
null
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""')
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)
......@@ -467,11 +467,11 @@ private void M()
Instance Receiver:
null
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')
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)
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')
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)
......@@ -483,7 +483,7 @@ private void M()
Instance Receiver:
null
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}""')
Parts(4):
IInterpolatedStringTextOperation (OperationKind.InterpolatedStringText, Type: null) (Syntax: 'i =')
......@@ -515,7 +515,7 @@ private void M()
Instance Receiver:
null
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}""')
Parts(4):
IInterpolatedStringTextOperation (OperationKind.InterpolatedStringText, Type: null) (Syntax: 'i =')
......@@ -584,7 +584,7 @@ private int A()
Instance Receiver:
null
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()')
Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: P, IsImplicit) (Syntax: 'A')
......@@ -636,16 +636,16 @@ private void A(bool flag)
Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: P, IsImplicit) (Syntax: 'A')
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)')
Instance Receiver:
null
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')
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)
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')
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)
......@@ -696,7 +696,7 @@ private static void A(bool flag, int number)
Instance Receiver:
null
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')
Expression:
ILocalReferenceOperation: o (OperationKind.LocalReference, Type: System.Object) (Syntax: 'o')
......@@ -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')
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)
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')
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)
......@@ -752,7 +752,7 @@ private void M()
Instance Receiver:
null
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')
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)
......@@ -796,7 +796,7 @@ private static void A(object o)
Instance Receiver:
null
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')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
......@@ -849,7 +849,7 @@ private static void A(bool flag, int number)
Instance Receiver:
null
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')
Expression:
ILocalReferenceOperation: o (OperationKind.LocalReference, Type: System.Object) (Syntax: 'o')
......@@ -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')
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)
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')
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)
......@@ -906,7 +906,7 @@ private void M()
Instance Receiver:
null
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')
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)
......@@ -1145,7 +1145,7 @@ Type Arguments(0)
Operand:
IParameterReferenceOperation: d (OperationKind.ParameterReference, Type: dynamic) (Syntax: 'd')
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')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
......
......@@ -314,7 +314,7 @@ public void M()
Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: Class, IsImplicit) (Syntax: 'M2')
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')
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)
......@@ -369,7 +369,7 @@ public void M()
Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: Class, IsImplicit) (Syntax: 'M2')
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}""')
Parts(1):
IInterpolationOperation (OperationKind.Interpolation, Type: null) (Syntax: '{y}')
......
......@@ -162,7 +162,7 @@ public void M()
Instance Receiver:
null
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')
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)
......@@ -194,7 +194,7 @@ public void M(int x)
Instance Receiver:
null
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')
Left:
IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'x')
......@@ -240,7 +240,7 @@ public void M(int x)
Instance Receiver:
null
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')
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)
......
......@@ -364,7 +364,7 @@ public void M()
Instance Receiver:
null
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!""')
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)
......
......@@ -335,7 +335,7 @@ class C
Instance Receiver:
null
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')
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)
......@@ -363,7 +363,7 @@ class C
Instance Receiver:
null
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')
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)
......
......@@ -27,13 +27,15 @@ static void Main(string[] args)
}
";
string expectedOperationTree = @"
IVariableDeclarationsOperation (2 declarations) (OperationKind.VariableDeclarations, Type: null, IsInvalid) (Syntax: 'int x, ( 1 );')
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'x')
Variables: Local_1: System.Int32 x
Initializer:
null
IVariableDeclarationOperation (1 variables) (OperationKind.VariableDeclaration, Type: null, IsInvalid) (Syntax: '( 1 ')
Variables: Local_1: System.Int32
IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsInvalid) (Syntax: 'int x, ( 1 );')
IVariableDeclarationOperation (2 declarators) (OperationKind.VariableDeclaration, Type: null, IsInvalid) (Syntax: 'int x, ( 1 ')
Declarators:
IVariableDeclaratorOperation (Symbol: System.Int32 x) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'x')
Initializer:
null
IVariableDeclaratorOperation (Symbol: System.Int32 ) (OperationKind.VariableDeclarator, Type: null, IsInvalid) (Syntax: '( 1 ')
Initializer:
null
Initializer:
null
";
......
......@@ -78,7 +78,7 @@ public IOperation GetOperation(SyntaxNode node, CancellationToken cancellationTo
catch (Exception e) when (FatalError.ReportWithoutCrashUnlessCanceled(e))
{
// Log a Non-fatal-watson and then ignore the crash in the attempt of getting operation
Debug.Assert(false);
Debug.Assert(false, e.ToString());
}
return null;
......
......@@ -3,7 +3,7 @@
namespace Microsoft.CodeAnalysis.Operations
{
/// <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>
/// Current usage:
/// (1) C# declaration expression. For example,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册