+2009-12-01 Marek Safar <marek.safar@gmail.com>
+
+ argument.cs, assign.cs, expression.cs, cs-parser.jay: Named
+ arguments by ref.
+
2009-12-01 Marek Safar <marek.safar@gmail.com>
A fix for bug #360455
mode |= AddressOp.Load;
IMemoryLocation ml = (IMemoryLocation) Expr;
- ParameterReference pr = ml as ParameterReference;
-
- //
- // ParameterReferences might already be references, so we want
- // to pass just the value
- //
- if (pr != null && pr.IsRef)
- pr.EmitLoad (ec);
- else
- ml.AddressOf (ec, mode);
+ ml.AddressOf (ec, mode);
}
public Argument Clone (CloneContext clonectx)
readonly Location loc;
LocalTemporary variable;
- public NamedArgument (string Name, Location loc, Expression expr)
- : base (expr)
+ public NamedArgument (string name, Location loc, Expression expr)
+ : this (name, loc, expr, AType.None)
{
- this.Name = Name;
+ }
+
+ public NamedArgument (string name, Location loc, Expression expr, AType modifier)
+ : base (expr, modifier)
+ {
+ this.Name = name;
this.loc = loc;
}
public void EmitAssign (EmitContext ec)
{
- Expr.Emit (ec);
- variable = new LocalTemporary (Expr.Type);
+ var type = Expr.Type;
+ if (IsByRef) {
+ var ml = (IMemoryLocation) Expr;
+ ml.AddressOf (ec, AddressOp.Load);
+ type = TypeManager.GetReferenceType (type);
+ } else {
+ Expr.Emit (ec);
+ }
+
+ variable = new LocalTemporary (type);
variable.Store (ec);
Expr = variable;
/// Does not happen with a class because a class is a pointer -- so you always
/// get the indirection.
///
- /// The `is_address' stuff is really just a hack. We need to come up with a better
- /// way to handle it.
/// </remarks>
public class LocalTemporary : Expression, IMemoryLocation, IAssignMethod {
LocalBuilder builder;
- bool is_address;
- public LocalTemporary (Type t) : this (t, false) {}
-
- public LocalTemporary (Type t, bool is_address)
+ public LocalTemporary (Type t)
{
type = t;
eclass = ExprClass.Value;
- this.is_address = is_address;
}
public LocalTemporary (LocalBuilder b, Type t)
+ : this (t)
{
- type = t;
- eclass = ExprClass.Value;
- loc = Location.Null;
builder = b;
}
throw new InternalErrorException ("Emit without Store, or after Release");
ig.Emit (OpCodes.Ldloc, builder);
+
// we need to copy from the pointer
- if (is_address)
+ if (builder.LocalType.IsByRef)
LoadFromPtr (ig, type);
}
get { return builder; }
}
- // NB: if you have `is_address' on the stack there must
- // be a managed pointer. Otherwise, it is the type from
- // the ctor.
public void Store (EmitContext ec)
{
ILGenerator ig = ec.ig;
if (builder == null)
- builder = ec.GetTemporaryLocal (is_address ? TypeManager.GetReferenceType (type): type);
+ builder = ec.GetTemporaryLocal (type);
ig.Emit (OpCodes.Stloc, builder);
}
public void AddressOf (EmitContext ec, AddressOp mode)
{
if (builder == null)
- builder = ec.GetTemporaryLocal (is_address ? TypeManager.GetReferenceType (type): type);
+ builder = ec.GetTemporaryLocal (type);
- // if is_address, than this is just the address anyways,
- // so we just return this.
ILGenerator ig = ec.ig;
- if (is_address)
+ if (builder.LocalType.IsByRef) {
+ //
+ // if is_address, than this is just the address anyways,
+ // so we just return this.
+ //
ig.Emit (OpCodes.Ldloc, builder);
- else
+ } else {
ig.Emit (OpCodes.Ldloca, builder);
+ }
}
public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
{
type = storey.MutateType (type);
}
-
- public bool PointsToAddress {
- get {
- return is_address;
- }
- }
}
/// <summary>
;
named_argument
- : IDENTIFIER COLON expression
+ : IDENTIFIER COLON opt_named_modifier expression
{
if (RootContext.Version <= LanguageVersion.V_3)
Report.FeatureIsNotAvailable (GetLocation ($1), "named argument");
+ // Avoid boxing in common case (no modifier)
+ var arg_mod = $3 == null ? Argument.AType.None : (Argument.AType) $3;
+
var lt = (Tokenizer.LocatedToken) $1;
- $$ = new NamedArgument (lt.Value, lt.Location, (Expression) $3);
- }
- ;
-
+ $$ = new NamedArgument (lt.Value, lt.Location, (Expression) $4, arg_mod);
+ }
+ ;
+
+opt_named_modifier
+ : /* empty */ { $$ = null; }
+ | REF
+ {
+ $$ = Argument.AType.Ref;
+ }
+ | OUT
+ {
+ $$ = Argument.AType.Out;
+ }
+ ;
class_body
: OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
public abstract VariableInfo VariableInfo { get; }
#endregion
- public void AddressOf (EmitContext ec, AddressOp mode)
+ public virtual void AddressOf (EmitContext ec, AddressOp mode)
{
HoistedVariable hv = GetHoistedVariable (ec);
if (hv != null) {
return Name == pr.Name;
}
+
+ public override void AddressOf (EmitContext ec, AddressOp mode)
+ {
+ //
+ // ParameterReferences might already be a reference
+ //
+ if (IsRef) {
+ EmitLoad (ec);
+ return;
+ }
+
+ base.AddressOf (ec, mode);
+ }
protected override void CloneTo (CloneContext clonectx, Expression target)
{