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 ();
value_on_stack = false;
}
- Variable.CreateBuilder (ec);
+ //
+ // It's ok to have variable builder create out of order. It simplified emit
+ // of statements like while (condition) { }
+ //
+ if (!Variable.Created)
+ Variable.CreateBuilder (ec);
+
Variable.EmitAssign (ec);
if (expr_unwrap != null) {
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 (type == null) {
+ type = InternalType.ErrorType;
+ return this;
+ }
+
if (!TypeSpec.IsReferenceType (type) && !type.IsNullableType) {
if (TypeManager.IsGenericParameter (type)) {
ec.Report.Error (413, loc,
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:
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);
if (element == null)
return null;
- if (element is CompoundAssign.TargetExpression) {
- if (first_emit != null)
- throw new InternalErrorException ("Can only handle one mutator at a time");
- first_emit = element;
- element = first_emit_temp = new LocalTemporary (element.Type);
+ var te = element as CompoundAssign.TargetExpression;
+ if (te != null) {
+ for (int i = 1; i < initializers.Count; ++i) {
+ if (initializers [i].ContainsEmitWithAwait ()) {
+ te.RequiresEmitWithAwait = true;
+ break;
+ }
+ }
+
+ if (!te.RequiresEmitWithAwait) {
+ if (first_emit != null)
+ throw new InternalErrorException ("Can only handle one mutator at a time");
+ first_emit = element;
+ element = first_emit_temp = new LocalTemporary (element.Type);
+ }
}
return Convert.ImplicitConversionRequired (
TypeSpec nested = null;
while (expr_type != null) {
- nested = MemberCache.FindNestedType (expr_type, Name, Arity);
+ nested = MemberCache.FindNestedType (expr_type, Name, Arity, false);
if (nested == null) {
if (expr_type == tnew_expr) {
Error_IdentifierNotFound (rc, expr_type);
}
expr_type = tnew_expr;
- nested = MemberCache.FindNestedType (expr_type, Name, Arity);
+ nested = MemberCache.FindNestedType (expr_type, Name, Arity, false);
ErrorIsInaccesible (rc, nested.GetSignatureForError (), loc);
break;
}
public void Error_IdentifierNotFound (IMemberContext rc, TypeSpec expr_type)
{
- var nested = MemberCache.FindNestedType (expr_type, Name, -System.Math.Max (1, Arity));
+ var nested = MemberCache.FindNestedType (expr_type, Name, -System.Math.Max (1, Arity), false);
if (nested != null) {
Error_TypeArgumentsCannotBeUsed (rc, nested, expr.Location);
}
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)
throw new NotImplementedException ();
sf = ec.GetTemporaryField (type);
+ sf.AutomaticallyReuse = false;
sf.EmitAssign (ec, temp, false, false);
temp_target = sf;
temp.Release (ec);
temp.Release (ec);
if (sf != null)
- sf.IsAvailableForReuse = true;
-
+ sf.PrepareCleanup (ec);
+
return true;
}
int errors = ec.Report.Errors;
type.CreateContainer ();
type.DefineContainer ();
+ type.ExpandBaseInterfaces ();
type.Define ();
if ((ec.Report.Errors - errors) == 0) {
parent.Module.AddAnonymousType (type);
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 ();
+ }
+ }
}