Expression ResolveAddressOf (ResolveContext ec)
{
- if (!ec.IsUnsafe)
+ if (ec.CurrentIterator != null) {
+ UnsafeInsideIteratorError (ec, loc);
+ } else if (!ec.IsUnsafe) {
UnsafeError (ec, loc);
+ }
Expr = Expr.DoResolveLValue (ec, EmptyExpression.UnaryAddress);
if (Expr == null || Expr.eclass != ExprClass.Variable) {
is_fixed = vr.IsFixed;
vr.SetHasAddressTaken ();
- if (vr.IsHoisted) {
+ if (vr.IsHoisted && ec.CurrentIterator == null) {
AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, vr, loc);
}
} else {
if (expr == null)
return null;
- if (!ec.IsUnsafe)
+ if (ec.CurrentIterator != null) {
+ UnsafeInsideIteratorError (ec, loc);
+ } else if (!ec.IsUnsafe) {
UnsafeError (ec, loc);
+ }
var pc = expr.Type as PointerContainer;
expr.EmitSideEffect (ec);
}
+ public override void EmitPrepare (EmitContext ec)
+ {
+ expr.EmitPrepare (ec);
+ }
+
public override void FlowAnalysis (FlowAnalysisContext fc)
{
expr.FlowAnalysis (fc);
public override Expression CreateExpressionTree (ResolveContext ec)
{
if (Variable != null)
- throw new NotSupportedException ();
+ ec.Report.Error (8122, loc, "An expression tree cannot contain a pattern matching operator");
Arguments args = Arguments.CreateForExpressionTree (ec, null,
expr.CreateExpressionTree (ec),
ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
}
+ public override void EmitPrepare (EmitContext ec)
+ {
+ base.EmitPrepare (ec);
+
+ if (Variable != null)
+ Variable.CreateBuilder (ec);
+ }
+
void EmitPatternMatch (EmitContext ec)
{
var no_match = ec.DefineLabel ();
ec.Emit (OpCodes.Dup);
no_value_label = ec.DefineLabel ();
ec.Emit (OpCodes.Brfalse_S, no_value_label);
+
+ if (Variable.HoistedVariant != null)
+ ec.EmitThis ();
+
expr_unwrap.Emit (ec);
} else {
+ if (Variable?.HoistedVariant != null)
+ ec.EmitThis ();
+
expr.Emit (ec);
// Only to make verifier happy
value_on_stack = false;
}
- Variable.CreateBuilder (ec);
- Variable.EmitAssign (ec);
+ if (Variable.HoistedVariant != null) {
+ Variable.HoistedVariant.EmitAssignFromStack (ec);
+
+ if (expr_unwrap != null) {
+ ec.MarkLabel (no_value_label);
+ } else if (!value_on_stack) {
+ Variable.HoistedVariant.Emit (ec);
+ }
+ } else {
+ //
+ // It's ok to have variable builder created out of order. It simplifies emit
+ // of statements like while (condition) { }
+ //
+ if (!Variable.Created)
+ Variable.CreateBuilder (ec);
+
+ Variable.EmitAssign (ec);
- if (expr_unwrap != null) {
- ec.MarkLabel (no_value_label);
- } else if (!value_on_stack) {
- Variable.Emit (ec);
+ if (expr_unwrap != null) {
+ ec.MarkLabel (no_value_label);
+ } else if (!value_on_stack) {
+ Variable.Emit (ec);
+ }
}
}
}
fc.SetVariableAssigned (Variable.VariableInfo, true);
}
+ public override void FlowAnalysisConditional (FlowAnalysisContext fc)
+ {
+ if (Variable == null) {
+ base.FlowAnalysisConditional (fc);
+ return;
+ }
+
+ expr.FlowAnalysis (fc);
+
+ fc.DefiniteAssignmentOnTrue = fc.BranchDefiniteAssignment ();
+ fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignment;
+
+ fc.SetVariableAssigned (Variable.VariableInfo, fc.DefiniteAssignmentOnTrue);
+ }
+
protected override void ResolveProbeType (ResolveContext rc)
{
if (!(ProbeType is TypeExpr) && rc.Module.Compiler.Settings.Version == LanguageVersion.Experimental) {
Expression ResolveResultExpression (ResolveContext ec)
{
+ if (Variable != null) {
+ if (expr is NullLiteral) {
+ ec.Report.Error (8117, loc, "Cannot use null as pattern matching operand");
+ return this;
+ }
+
+ CheckExpressionVariable (ec);
+ }
+
TypeSpec d = expr.Type;
bool d_is_nullable = false;
// If E is a method group or the null literal, or if the type of E is a reference
// type or a nullable type and the value of E is null, the result is false
//
- if (expr.IsNull || expr.eclass == ExprClass.MethodGroup)
+ if (expr.IsNull)
return CreateConstantResult (ec, false);
if (d.IsNullableType) {
TypeSpec t = probe_type_expr;
bool t_is_nullable = false;
if (t.IsNullableType) {
+ if (Variable != null) {
+ ec.Report.Error (8116, loc, "The nullable type `{0}' pattern matching is not allowed. Consider using underlying type `{1}'",
+ t.GetSignatureForError (), Nullable.NullableInfo.GetUnderlyingType (t).GetSignatureForError ());
+ }
+
var ut = Nullable.NullableInfo.GetUnderlyingType (t);
if (!ut.IsGenericParameter) {
t = ut;
return ResolveGenericParameter (ec, d, tps);
if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
- ec.Report.Warning (1981, 3, loc,
- "Using `{0}' to test compatibility with `{1}' is identical to testing compatibility with `object'",
- OperatorName, t.GetSignatureForError ());
+ if (Variable != null) {
+ ec.Report.Error (8208, loc, "The type `{0}' pattern matching is not allowed", t.GetSignatureForError ());
+ } else {
+ ec.Report.Warning (1981, 3, loc,
+ "Using `{0}' to test compatibility with `{1}' is identical to testing compatibility with `object'",
+ OperatorName, t.GetSignatureForError ());
+ }
}
if (TypeManager.IsGenericParameter (d))
eclass = ExprClass.Value;
TypeSpec etype = expr.Type;
+ if (expr is TupleLiteral && TupleLiteral.ContainsNoTypeElement (etype)) {
+ ec.Report.Error (8307, expr.Location, "The first operand of an `as' operator may not be a tuple literal without a natural type");
+ type = InternalType.ErrorType;
+ return this;
+ }
+
if (type == null) {
type = InternalType.ErrorType;
return this;
return null;
}
- if (type.IsPointer && !ec.IsUnsafe) {
- UnsafeError (ec, loc);
+ if (type.IsPointer) {
+ if (ec.CurrentIterator != null) {
+ UnsafeInsideIteratorError (ec, loc);
+ } else if (!ec.IsUnsafe) {
+ UnsafeError (ec, loc);
+ }
}
eclass = ExprClass.Value;
public override Expression CreateExpressionTree (ResolveContext rc)
{
- rc.Report.Error (8046, loc, "An expression tree cannot contain a declaration expression");
+ rc.Report.Error (8198, loc, "An expression tree cannot contain out variable declaration");
return null;
}
bool DoResolveCommon (ResolveContext rc)
{
+ CheckExpressionVariable (rc);
+
var var_expr = VariableType as VarExpr;
if (var_expr != null) {
type = InternalType.VarOutType;
public override Expression ConvertResult (ResolveContext ec, Binary b)
{
if (left != null) {
- b.left = EmptyCast.Create (b.left, left);
+ b.left = Convert.UserDefinedConversion (ec, b.left, left, Convert.UserConversionRestriction.ImplicitOnly, b.loc) ?? EmptyCast.Create (b.left, left);
} else if (right != null) {
- b.right = EmptyCast.Create (b.right, right);
+ b.right = Convert.UserDefinedConversion (ec, b.right, right, Convert.UserConversionRestriction.ImplicitOnly, b.loc) ?? EmptyCast.Create (b.right, right);
}
TypeSpec r_type = ReturnType;
}
}
- static CSharp.Operator.OpType ConvertBinaryToUserOperator (Operator op)
+ public static CSharp.Operator.OpType ConvertBinaryToUserOperator (Operator op)
{
switch (op) {
case Operator.Addition:
return DoResolveInvocation (rc);
}
+ public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
+ {
+ var sn = expr as SimpleName;
+ if (sn != null && sn.Name == "var" && sn.Arity == 0 && arguments?.Count > 1) {
+ var targets = new List<Expression> (arguments.Count);
+ var variables = new List<LocalVariable> (arguments.Count);
+ foreach (var arg in arguments) {
+ var arg_sn = arg.Expr as SimpleName;
+ if (arg_sn == null || arg_sn.Arity != 0) {
+ rc.Report.Error (8199, loc, "The syntax `var (...)' as an lvalue is reserved");
+ return ErrorExpression.Instance;
+ }
+
+ var lv = new LocalVariable (rc.CurrentBlock, arg_sn.Name, arg.Expr.Location);
+ rc.CurrentBlock.AddLocalName (lv);
+ variables.Add (lv);
+
+ targets.Add (new LocalVariableReference (lv, arg_sn.Location));
+ }
+
+ var res = new TupleDeconstruct (targets, variables, right_side, loc);
+ return res.Resolve (rc);
+ }
+
+ return base.DoResolveLValue (rc, right_side);
+ }
+
Expression DoResolveInvocation (ResolveContext ec)
{
Expression member_expr;
protected override Expression DoResolve (ResolveContext ec)
{
+ if (RequestedType is TupleTypeExpr) {
+ ec.Report.Error (8181, loc, "Tuple type cannot be used in an object creation expression. Use a tuple literal expression instead.");
+ }
+
type = RequestedType.ResolveAsType (ec);
if (type == null)
return null;
bool is_value_type = type.IsStructOrEnum;
VariableReference vr = target as VariableReference;
+ bool prepare_await = ec.HasSet (BuilderContext.Options.AsyncBody) && arguments?.ContainsEmitWithAwait () == true;
+
if (target != null && is_value_type && (vr != null || method == null)) {
+ if (prepare_await) {
+ arguments = arguments.Emit (ec, false, true);
+ prepare_await = false;
+ }
+
target.AddressOf (ec, AddressOp.Store);
} else if (vr != null && vr.IsRef) {
vr.EmitLoad (ec);
}
if (arguments != null) {
- if (ec.HasSet (BuilderContext.Options.AsyncBody) && (arguments.Count > (this is NewInitialize ? 0 : 1)) && arguments.ContainsEmitWithAwait ())
+ if (prepare_await)
arguments = arguments.Emit (ec, false, true);
arguments.Emit (ec);
array_element_type = best_type_inference.InferredTypeArguments[0];
best_type_inference = null;
- if (array_element_type == null ||
- array_element_type == InternalType.NullLiteral || array_element_type == InternalType.MethodGroup || array_element_type == InternalType.AnonymousMethod ||
- arguments.Count != rank.Dimension) {
+ if (array_element_type == null || InternalType.HasNoType (array_element_type) || arguments.Count != rank.Dimension) {
ec.Report.Error (826, loc,
"The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly");
return null;
}
type = ac.Element;
- if (type.IsPointer && !ec.IsUnsafe) {
- UnsafeError (ec, ea.Location);
+ if (type.IsPointer) {
+ if (ec.CurrentIterator != null) {
+ UnsafeInsideIteratorError (ec, ea.Location);
+ } else if (!ec.IsUnsafe) {
+ UnsafeError (ec, ea.Location);
+ }
}
if (conditional_access_receiver)
#region IBaseMembersProvider Members
- IList<MemberSpec> OverloadResolver.IBaseMembersProvider.GetBaseMembers (TypeSpec baseType)
+ IList<MemberSpec> OverloadResolver.IBaseMembersProvider.GetBaseMembers (TypeSpec type)
{
- return baseType == null ? null : MemberCache.FindMembers (baseType, MemberCache.IndexerNameAlias, false);
+ var baseType = type.BaseType;
+ var members = baseType == null ? null : MemberCache.FindMembers (baseType, MemberCache.IndexerNameAlias, false);
+
+ if (members == null && !type.IsInterface) {
+ var tps = queried_type as TypeParameterSpec;
+ if (tps != null)
+ members = MemberCache.FindInterfaceMembers (tps, MemberCache.IndexerNameAlias);
+ }
+
+ return members;
}
IParametersMember OverloadResolver.IBaseMembersProvider.GetOverrideMemberParameters (MemberSpec member)
if (!(ec.CurrentMemberDefinition is Field) && !TypeManager.VerifyUnmanaged (ec.Module, type, loc))
return null;
- if (!ec.IsUnsafe) {
+ var rc = ec as ResolveContext;
+ if (rc?.CurrentIterator != null) {
+ UnsafeInsideIteratorError (ec.Module.Compiler.Report, loc);
+ } else if (!ec.IsUnsafe) {
UnsafeError (ec.Module.Compiler.Report, loc);
}
args);
}
- protected override Expression DoResolve (ResolveContext ec)
+ protected override Expression DoResolve (ResolveContext rc)
{
- Expression e = base.DoResolve (ec);
+ Expression e = base.DoResolve (rc);
if (type == null)
return null;
if (type.IsDelegate) {
- ec.Report.Error (1958, Initializers.Location,
+ rc.Report.Error (1958, Initializers.Location,
"Object and collection initializers cannot be used to instantiate a delegate");
}
- Expression previous = ec.CurrentInitializerVariable;
- ec.CurrentInitializerVariable = new InitializerTargetExpression (this);
- initializers.Resolve (ec);
- ec.CurrentInitializerVariable = previous;
+ Expression previous = rc.CurrentInitializerVariable;
+ rc.CurrentInitializerVariable = new InitializerTargetExpression (this);
+ using (rc.With (ResolveContext.Options.DontSetConditionalAccessReceiver, false)) {
+ initializers.Resolve (rc);
+ }
+ rc.CurrentInitializerVariable = previous;
dynamic = e as DynamicExpressionStatement;
if (dynamic != null)
}
type = e.Type;
- if (type.Kind == MemberKind.Void || type == InternalType.NullLiteral || type == InternalType.AnonymousMethod || type.IsPointer) {
+ if (type.Kind == MemberKind.Void || InternalType.HasNoType (type) || type.IsPointer || (e is TupleLiteral && TupleLiteral.ContainsNoTypeElement (type))) {
Error_InvalidInitializer (ec, type.GetSignatureForError ());
return null;
}
return value;
}
}
+
+ class ThrowExpression : ExpressionStatement
+ {
+ Expression expr;
+
+ public ThrowExpression (Expression expr, Location loc)
+ {
+ this.expr = expr;
+ this.loc = loc;
+ }
+
+ protected override void CloneTo (CloneContext clonectx, Expression t)
+ {
+ var target = (ThrowExpression)t;
+ target.expr = expr.Clone (clonectx);
+ }
+
+ public override bool ContainsEmitWithAwait ()
+ {
+ return expr.ContainsEmitWithAwait ();
+ }
+
+ public override Expression CreateExpressionTree (ResolveContext rc)
+ {
+ rc.Report.Error (8188, loc, "An expression tree cannot not contain a throw expression");
+ return expr;
+ }
+
+ protected override Expression DoResolve (ResolveContext rc)
+ {
+ expr = expr.Resolve (rc, ResolveFlags.Type | ResolveFlags.VariableOrValue);
+
+ if (expr == null)
+ return null;
+
+ expr = Throw.ConvertType (rc, expr);
+
+ eclass = ExprClass.Value;
+ type = InternalType.ThrowExpr;
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ EmitStatement (ec);
+ }
+
+ public override void EmitStatement (EmitContext ec)
+ {
+ expr.Emit (ec);
+
+ ec.Emit (OpCodes.Throw);
+ }
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ expr.FlowAnalysis (fc);
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ return Reachability.CreateUnreachable ();
+ }
+ }
}