protected override Expression DoResolve (ResolveContext rc)
{
Expression res = null;
-
using (rc.With (ResolveContext.Options.DontSetConditionalAccessReceiver, false)) {
res = expr.Resolve (rc);
}
}
New n_source = source as New;
- if (n_source != null) {
+ if (n_source != null && n_source.CanEmitOptimizedLocalTarget (ec)) {
if (!n_source.Emit (ec, this)) {
if (leave_copy) {
EmitLoad (ec);
}
}
+ bool statement_resolve;
+ public override ExpressionStatement ResolveStatement (BlockContext bc)
+ {
+ statement_resolve = true;
+ var es = base.ResolveStatement (bc);
+ statement_resolve = false;
+
+ return es;
+ }
+
protected override Expression DoResolve (ResolveContext rc)
{
ResolveConditionalAccessReceiver (rc);
var method = mg.BestCandidate;
type = mg.BestCandidateReturnType;
- if (conditional_access_receiver)
+ if (conditional_access_receiver && !statement_resolve)
type = LiftMemberType (ec, type);
if (arguments == null && method.DeclaringType.BuiltinType == BuiltinTypeSpec.Type.Object && method.Name == Destructor.MetadataName) {
args.Insert (0, new Argument (inst.Resolve (ec), mod));
}
} else { // is SimpleName
- if (ec.IsStatic) {
+ if (ec.IsStatic || ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.BaseInitializer)) {
args.Insert (0, new Argument (new TypeOf (ec.CurrentType, loc).Resolve (ec), Argument.AType.DynamicTypeName));
} else {
args.Insert (0, new Argument (new This (loc).Resolve (ec)));
}
}
- return new DynamicInvocation (expr as ATypeNameExpression, args, loc).Resolve (ec);
+ return new DynamicInvocation (expr as ATypeNameExpression, args, conditional_access_receiver, loc).Resolve (ec);
}
protected virtual MethodGroupExpr DoResolveOverload (ResolveContext ec)
ec.Emit (OpCodes.Pop);
}
+ public virtual bool CanEmitOptimizedLocalTarget (EmitContext ec)
+ {
+ return true;
+ }
+
public override void FlowAnalysis (FlowAnalysisContext fc)
{
if (arguments != null)
{
}
+ public bool NoEmptyInterpolation { get; set; }
+
public ComposedTypeSpecifier Rank {
get {
return this.rank;
public override void Emit (EmitContext ec)
{
+ if (!NoEmptyInterpolation && EmitOptimizedEmpty (ec))
+ return;
+
var await_field = EmitToFieldSource (ec);
if (await_field != null)
await_field.Emit (ec);
}
+ bool EmitOptimizedEmpty (EmitContext ec)
+ {
+ if (arguments.Count != 1 || dimensions != 1)
+ return false;
+
+ var c = arguments [0] as Constant;
+ if (c == null || !c.IsZeroInteger)
+ return false;
+
+ var m = ec.Module.PredefinedMembers.ArrayEmpty.Get ();
+ if (m == null || ec.CurrentType.MemberDefinition.DeclaringAssembly == m.DeclaringType.MemberDefinition.DeclaringAssembly)
+ return false;
+
+ m = m.MakeGenericMethod (ec.MemberContext, array_element_type);
+ ec.Emit (OpCodes.Call, m);
+ return true;
+ }
+
protected sealed override FieldExpr EmitToFieldSource (EmitContext ec)
{
if (first_emit != null) {
return retval;
}
+ var cma = this as ConditionalMemberAccess;
+
MemberExpr me;
TypeSpec expr_type = expr.Type;
if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
Arguments args = new Arguments (1);
args.Add (new Argument (expr));
+
+ if (cma != null)
+ return new DynamicConditionalMemberBinder (Name, args, loc);
+
return new DynamicMemberBinder (Name, args, loc);
}
- var cma = this as ConditionalMemberAccess;
if (cma != null) {
if (!IsNullPropagatingValid (expr.Type)) {
expr.Error_OperatorCannotBeApplied (rc, loc, "?", expr.Type);
args.AddRange (arguments);
best_candidate = null;
- return new DynamicIndexBinder (args, loc);
+ return new DynamicIndexBinder (args, conditional_access_receiver, ConditionalAccess, loc);
}
//
args.Add (new Argument (rc.CurrentInitializerVariable));
target = new DynamicMemberBinder (Name, args, loc);
} else {
-
var member = MemberLookup (rc, false, t, Name, 0, MemberLookupRestrictions.ExactArity, loc);
if (member == null) {
member = Expression.MemberLookup (rc, true, t, Name, 0, MemberLookupRestrictions.ExactArity, loc);
public override void Emit (EmitContext ec)
{
- if (method == null && TypeSpec.IsValueType (type) && initializers.Initializers.Count > 1 && ec.HasSet (BuilderContext.Options.AsyncBody) && initializers.ContainsEmitWithAwait ()) {
+ if (!CanEmitOptimizedLocalTarget (ec)) {
var fe = ec.GetTemporaryField (type);
if (!Emit (ec, fe))
return true;
}
+ public override bool CanEmitOptimizedLocalTarget (EmitContext ec)
+ {
+ return !(method == null && TypeSpec.IsValueType (type) &&
+ initializers.Initializers.Count > 1 && ec.HasSet (BuilderContext.Options.AsyncBody) &&
+ initializers.ContainsEmitWithAwait ());
+ }
+
protected override IMemoryLocation EmitAddressOf (EmitContext ec, AddressOp Mode)
{
instance = base.EmitAddressOf (ec, Mode);