Default = 3, // argument created from default parameter value
DynamicTypeName = 4, // System.Type argument for dynamic binding
ExtensionType = 5, // Instance expression inserted as the first argument
+
+ // Conditional instance expression inserted as the first argument
+ ExtensionTypeConditionalAccess = 5 | ConditionalAccessFlag,
+
+ ConditionalAccessFlag = 1 << 7
}
public readonly AType ArgType;
public Argument (Expression expr)
{
- if (expr == null)
- throw new ArgumentNullException ();
-
this.Expr = expr;
}
get { return ArgType == AType.Default; }
}
+ public bool IsExtensionType {
+ get {
+ return (ArgType & AType.ExtensionType) == AType.ExtensionType;
+ }
+ }
+
public Parameter.Modifier Modifier {
get {
switch (ArgType) {
return Clone (Expr.Clone (clonectx));
}
- public virtual Expression CreateExpressionTree (ResolveContext ec)
+ public virtual Expression CreateExpressionTree (ResolveContext rc)
{
+ if (Type.Kind == MemberKind.ByRef) {
+ rc.Report.Error (8153, Expr.Location, "An expression tree lambda cannot contain a call to a method, property, or indexer that returns by reference");
+ return null;
+ }
+
if (ArgType == AType.Default)
- ec.Report.Error (854, Expr.Location, "An expression tree cannot contain an invocation which uses optional parameter");
+ rc.Report.Error (854, Expr.Location, "An expression tree cannot contain an invocation which uses optional parameter");
- return Expr.CreateExpressionTree (ec);
+ return Expr.CreateExpressionTree (rc);
}
public virtual void Emit (EmitContext ec)
{
if (!IsByRef) {
+ if (ArgType == AType.ExtensionTypeConditionalAccess) {
+ var ie = new InstanceEmitter (Expr, false);
+ ie.Emit (ec, true);
+ } else {
+ Expr.Emit (ec);
+ }
+
+ return;
+ }
+
+ if (Expr.Type.Kind == MemberKind.ByRef) {
Expr.Emit (ec);
return;
}
if (ArgType == AType.Ref)
mode |= AddressOp.Load;
- IMemoryLocation ml = (IMemoryLocation) Expr;
- ml.AddressOf (ec, mode);
+ ((IMemoryLocation)Expr).AddressOf (ec, mode);
}
public Argument EmitToField (EmitContext ec, bool cloneResult)
return this;
}
+ public void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (ArgType == AType.Out) {
+ var vr = Expr as VariableReference;
+ if (vr != null) {
+ if (vr.VariableInfo != null)
+ fc.SetVariableAssigned (vr.VariableInfo);
+
+ return;
+ }
+
+ var fe = Expr as FieldExpr;
+ if (fe != null) {
+ fe.SetFieldAssigned (fc);
+ return;
+ }
+
+ return;
+ }
+
+ Expr.FlowAnalysis (fc);
+ }
+
public string GetSignatureForError ()
{
if (Expr.eclass == ExprClass.MethodGroup)
return Expr.ExprClassName;
- return TypeManager.CSharpName (Expr.Type);
+ return Expr.Type.GetSignatureForError ();
}
public bool ResolveMethodGroup (ResolveContext ec)
public void Resolve (ResolveContext ec)
{
-// using (ec.With (ResolveContext.Options.DoFlowAnalysis, true)) {
- // Verify that the argument is readable
- if (ArgType != AType.Out)
- Expr = Expr.Resolve (ec);
+ // Verify that the argument is readable
+ if (ArgType != AType.Out)
+ Expr = Expr.Resolve (ec);
- // Verify that the argument is writeable
- if (Expr != null && IsByRef)
- Expr = Expr.ResolveLValue (ec, EmptyExpression.OutAccess);
+ // Verify that the argument is writeable
+ if (Expr != null && IsByRef)
+ Expr = Expr.ResolveLValue (ec, EmptyExpression.OutAccess);
- if (Expr == null)
- Expr = ErrorExpression.Instance;
-// }
+ if (Expr == null)
+ Expr = ErrorExpression.Instance;
}
}
ordered.Add (arg);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc, List<MovableArgument> movable = null)
+ {
+ foreach (var arg in ordered) {
+ if (arg.ArgType != Argument.AType.Out)
+ arg.FlowAnalysis (fc);
+ }
+
+ base.FlowAnalysis (fc, ordered);
+ }
+
public override Arguments Emit (EmitContext ec, bool dup_args, bool prepareAwait)
{
foreach (var a in ordered) {
} else if (arg_type.Kind == MemberKind.Void || arg_type == InternalType.Arglist || arg_type.IsPointer) {
rc.Report.Error (1978, a.Expr.Location,
"An expression of type `{0}' cannot be used as an argument of dynamic operation",
- TypeManager.CSharpName (arg_type));
+ arg_type.GetSignatureForError ());
}
info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags,
return all;
}
- public static Arguments CreateForExpressionTree (ResolveContext ec, Arguments args, params Expression[] e)
+ public static Arguments CreateForExpressionTree (ResolveContext rc, Arguments args, params Expression[] e)
{
Arguments all = new Arguments ((args == null ? 0 : args.Count) + e.Length);
for (int i = 0; i < e.Length; ++i) {
- if (e [i] != null)
- all.Add (new Argument (e[i]));
+ var expr = e [i];
+ if (expr != null) {
+ all.Add (new Argument (expr));
+ }
}
if (args != null) {
foreach (Argument a in args.args) {
- Expression tree_arg = a.CreateExpressionTree (ec);
+ Expression tree_arg = a.CreateExpressionTree (rc);
if (tree_arg != null)
all.Add (new Argument (tree_arg));
}
Emit (ec, false, false);
}
+ public void EmitPrepare (EmitContext ec)
+ {
+ foreach (var a in args) {
+ a.Expr.EmitPrepare (ec);
+ }
+ }
+
//
// if `dup_args' is true or any of arguments contains await.
// A copy of all arguments will be returned to the caller
return null;
}
+ public virtual void FlowAnalysis (FlowAnalysisContext fc, List<MovableArgument> movable = null)
+ {
+ bool has_out = false;
+ foreach (var arg in args) {
+ if (arg.ArgType == Argument.AType.Out) {
+ has_out = true;
+ continue;
+ }
+
+ if (movable == null) {
+ arg.FlowAnalysis (fc);
+ continue;
+ }
+
+ var ma = arg as MovableArgument;
+ if (ma != null && !movable.Contains (ma))
+ arg.FlowAnalysis (fc);
+ }
+
+ if (!has_out)
+ return;
+
+ foreach (var arg in args) {
+ if (arg.ArgType != Argument.AType.Out)
+ continue;
+
+ arg.FlowAnalysis (fc);
+ }
+ }
+
public List<Argument>.Enumerator GetEnumerator ()
{
return args.GetEnumerator ();
//
// Returns dynamic when at least one argument is of dynamic type
//
- public void Resolve (ResolveContext ec, out bool dynamic)
+ public void Resolve (ResolveContext rc, out bool dynamic)
{
dynamic = false;
+
+ List<LocalVariable> var_locals = null;
foreach (Argument a in args) {
- a.Resolve (ec);
- if (a.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && !a.IsByRef)
+ a.Resolve (rc);
+
+ if (a.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && !a.IsByRef) {
dynamic = true;
+ continue;
+ }
+
+ if (a.Type == InternalType.VarOutType) {
+ var de = a.Expr as DeclarationExpression;
+ if (de != null) {
+ if (var_locals == null)
+ var_locals = new List<LocalVariable> ();
+
+ var_locals.Add (de.Variable);
+ continue;
+ }
+
+ var lvr = a.Expr as LocalVariableReference;
+ if (lvr != null && var_locals != null && var_locals.Contains (lvr.local_info)) {
+ rc.Report.Error (8196, lvr.Location, "Reference to an implicitly typed out variable `{0}' is not permitted in the same argument list", lvr.Name);
+ lvr.Type = InternalType.ErrorType;
+ }
+ }
}
}