if (expr_type == TypeManager.float_type) {
FloatLiteral fl = e as FloatLiteral;
// For better error reporting
- if (fl != null) {
- fl.Value = -fl.Value;
- return fl;
- }
+ if (fl != null)
+ return new FloatLiteral (-fl.Value, e.Location);
+
return new FloatConstant (-((FloatConstant)e).Value, e.Location);
}
if (expr_type == TypeManager.double_type) {
DoubleLiteral dl = e as DoubleLiteral;
// For better error reporting
- if (dl != null) {
- dl.Value = -dl.Value;
- return dl;
- }
-
+ if (dl != null)
+ return new DoubleLiteral (-dl.Value, e.Location);
+
return new DoubleConstant (-((DoubleConstant)e).Value, e.Location);
}
if (expr_type == TypeManager.decimal_type)
t_is_nullable = true;
}
- if (t.IsValueType) {
+ if (TypeManager.IsStruct (t)) {
if (d == t) {
//
// D and T are the same value types but D can be null
if (TypeManager.IsGenericParameter (t))
return ResolveGenericParameter (d, t);
- if (d.IsValueType) {
+ if (TypeManager.IsStruct (d)) {
bool temp;
if (Convert.ImplicitBoxingConversionExists (expr, t, out temp))
return CreateConstantResult (true);
#if GMCS_SOURCE
GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
if (constraints != null) {
- if (constraints.IsReferenceType && d.IsValueType)
+ if (constraints.IsReferenceType && TypeManager.IsStruct (d))
return CreateConstantResult (false);
- if (constraints.IsValueType && !d.IsValueType)
+ if (constraints.IsValueType && !TypeManager.IsStruct (d))
return CreateConstantResult (TypeManager.IsEqual (d, t));
}
expr.Emit (ec);
if (do_isinst)
- ig.Emit (OpCodes.Isinst, probe_type_expr.Type);
+ ig.Emit (OpCodes.Isinst, type);
#if GMCS_SOURCE
- if (TypeManager.IsNullableType (type))
+ if (TypeManager.IsGenericParameter (type) || TypeManager.IsNullableType (type))
ig.Emit (OpCodes.Unbox_Any, type);
#endif
}
protected override string OperatorName {
get { return "as"; }
}
+
+ public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+ {
+ type = storey.MutateType (type);
+ base.MutateHoistedGenericType (storey);
+ }
public override bool GetAttributableValue (EmitContext ec, Type value_type, out object value)
{
// The conversion rules are ignored in enum context but why
if (!ec.InEnumContext && lc != null && rc != null && (TypeManager.IsEnumType (left.Type) || TypeManager.IsEnumType (right.Type))) {
- left = lc = EnumLiftUp (ec, lc, rc, loc);
- if (lc == null)
- return null;
-
- right = rc = EnumLiftUp (ec, rc, lc, loc);
- if (rc == null)
- return null;
+ lc = EnumLiftUp (ec, lc, rc, loc);
+ if (lc != null)
+ rc = EnumLiftUp (ec, rc, lc, loc);
}
if (rc != null && lc != null) {
if (RootContext.Version >= LanguageVersion.ISO_2 &&
((TypeManager.IsNullableType (left.Type) && (right is NullLiteral || TypeManager.IsNullableType (right.Type) || TypeManager.IsValueType (right.Type))) ||
- (left.Type.IsValueType && right is NullLiteral) ||
+ (TypeManager.IsValueType (left.Type) && right is NullLiteral) ||
(TypeManager.IsNullableType (right.Type) && (left is NullLiteral || TypeManager.IsNullableType (left.Type) || TypeManager.IsValueType (left.Type))) ||
- (right.Type.IsValueType && left is NullLiteral)))
+ (TypeManager.IsValueType (right.Type) && left is NullLiteral)))
return new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec);
return DoResolveCore (ec, left, right);
return null;
} else if (l.IsInterface) {
l = TypeManager.object_type;
- } else if (l.IsValueType) {
+ } else if (TypeManager.IsStruct (l)) {
return null;
}
return null;
} else if (r.IsInterface) {
r = TypeManager.object_type;
- } else if (r.IsValueType) {
+ } else if (TypeManager.IsStruct (r)) {
return null;
}
LocalTemporary temp;
#region Abstract
- public abstract HoistedVariable HoistedVariable { get; }
+ public abstract HoistedVariable GetHoistedVariable (EmitContext ec);
public abstract bool IsFixed { get; }
public abstract bool IsRef { get; }
public abstract string Name { get; }
public void AddressOf (EmitContext ec, AddressOp mode)
{
- if (IsHoistedEmitRequired (ec)) {
- HoistedVariable.AddressOf (ec, mode);
+ HoistedVariable hv = GetHoistedVariable (ec);
+ if (hv != null) {
+ hv.AddressOf (ec, mode);
return;
}
{
Report.Debug (64, "VARIABLE EMIT", this, Variable, type, IsRef, loc);
- if (IsHoistedEmitRequired (ec)) {
- HoistedVariable.Emit (ec, leave_copy);
+ HoistedVariable hv = GetHoistedVariable (ec);
+ if (hv != null) {
+ hv.Emit (ec, leave_copy);
return;
}
public void EmitAssign (EmitContext ec, Expression source, bool leave_copy,
bool prepare_for_load)
{
- if (IsHoistedEmitRequired (ec)) {
- HoistedVariable.EmitAssign (ec, source, leave_copy, prepare_for_load);
+ HoistedVariable hv = GetHoistedVariable (ec);
+ if (hv != null) {
+ hv.EmitAssign (ec, source, leave_copy, prepare_for_load);
return;
}
}
public bool IsHoisted {
- get { return HoistedVariable != null; }
- }
-
- protected virtual bool IsHoistedEmitRequired (EmitContext ec)
- {
- //
- // Default implementation return true when there is a hosted variable
- //
- return HoistedVariable != null;
+ get { return GetHoistedVariable (null) != null; }
}
public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
get { return local_info.VariableInfo; }
}
- public override HoistedVariable HoistedVariable {
- get { return local_info.HoistedVariableReference; }
+ public override HoistedVariable GetHoistedVariable (EmitContext ec)
+ {
+ return local_info.HoistedVariableReference;
}
//
/// </summary>
public class ParameterReference : VariableReference {
readonly ToplevelParameterInfo pi;
- readonly ToplevelBlock referenced;
- public ParameterReference (ToplevelBlock referenced, ToplevelParameterInfo pi, Location loc)
+ public ParameterReference (ToplevelParameterInfo pi, Location loc)
{
this.pi = pi;
- this.referenced = referenced;
this.loc = loc;
}
get { return pi.Parameter.ModFlags == Parameter.Modifier.OUT; }
}
- public override HoistedVariable HoistedVariable {
- get { return pi.Parameter.HoistedVariableReference; }
+ public override HoistedVariable GetHoistedVariable (EmitContext ec)
+ {
+ return pi.Parameter.HoistedVariableReference;
}
//
if (am == null)
return true;
- ToplevelBlock declared = pi.Block;
- if (declared != referenced) {
- if (IsRef) {
- Report.Error (1628, loc,
- "Parameter `{0}' cannot be used inside `{1}' when using `ref' or `out' modifier",
- Name, am.ContainerType);
- return false;
+ Block b = ec.CurrentBlock;
+ while (b != null) {
+ IParameterData[] p = b.Toplevel.Parameters.FixedParameters;
+ for (int i = 0; i < p.Length; ++i) {
+ if (p [i] != Parameter)
+ continue;
+
+ //
+ // Skip closest anonymous method parameters
+ //
+ if (b == ec.CurrentBlock && !am.IsIterator)
+ return true;
+
+ if (IsRef) {
+ Report.Error (1628, loc,
+ "Parameter `{0}' cannot be used inside `{1}' when using `ref' or `out' modifier",
+ Name, am.ContainerType);
+ }
+
+ b = null;
+ break;
}
- } else {
- if (!am.IsIterator)
- return true;
+
+ if (b != null)
+ b = b.Toplevel.Parent;
}
- if (ec.IsVariableCapturingRequired) {
- if (pi.Parameter.HasAddressTaken)
- AnonymousMethodExpression.Error_AddressOfCapturedVar (this, loc);
+ if (pi.Parameter.HasAddressTaken)
+ AnonymousMethodExpression.Error_AddressOfCapturedVar (this, loc);
- AnonymousMethodStorey storey = declared.CreateAnonymousMethodStorey (ec);
+ if (ec.IsVariableCapturingRequired) {
+ AnonymousMethodStorey storey = pi.Block.CreateAnonymousMethodStorey (ec);
storey.CaptureParameter (ec, this);
}
if (pr == null)
return false;
- return Name == pr.Name && referenced == pr.referenced;
+ return Name == pr.Name;
}
protected override void CloneTo (CloneContext clonectx, Expression target)
public override Expression CreateExpressionTree (EmitContext ec)
{
- if (IsHoistedEmitRequired (ec))
- return HoistedVariable.CreateExpressionTree (ec);
+ HoistedVariable hv = GetHoistedVariable (ec);
+ if (hv != null)
+ return hv.CreateExpressionTree (ec);
return Parameter.ExpressionTreeVariableReference ();
}
return null;
}
- if (Arguments == null && method.DeclaringType == TypeManager.object_type && method.Name == "Finalize") {
+ if (Arguments == null && method.DeclaringType == TypeManager.object_type && method.Name == Destructor.MetadataName) {
if (mg.IsBase)
Report.Error (250, loc, "Do not directly call your base class Finalize method. It is called automatically from your destructor");
else
bool is_static = method.IsStatic;
if (!is_static){
this_call = instance_expr is This;
- if (decl_type.IsValueType || (!this_call && instance_expr.Type.IsValueType))
+ if (TypeManager.IsStruct (decl_type) || TypeManager.IsEnumType (decl_type) || (!this_call && TypeManager.IsStruct (instance_expr.Type)))
struct_call = true;
//
//
// Push the instance expression
//
- if (TypeManager.IsValueType (iexpr_type)) {
+ if (TypeManager.IsValueType (iexpr_type) || TypeManager.IsGenericParameter (iexpr_type)) {
//
// Special case: calls to a function declared in a
// reference-type with a value-type argument need
// to have their value boxed.
- if (decl_type.IsValueType ||
+ if (TypeManager.IsStruct (decl_type) ||
TypeManager.IsGenericParameter (iexpr_type)) {
//
// If the expression implements IMemoryLocation, then
if (!omit_args)
EmitArguments (ec, Arguments, dup_args, this_arg);
-#if GMCS_SOURCE
- if ((instance_expr != null) && (instance_expr.Type.IsGenericParameter))
- ig.Emit (OpCodes.Constrained, instance_expr.Type);
-#endif
-
OpCode call_op;
- if (is_static || struct_call || is_base || (this_call && !method.IsVirtual))
+ if (is_static || struct_call || is_base || (this_call && !method.IsVirtual)) {
call_op = OpCodes.Call;
- else
+ } else {
call_op = OpCodes.Callvirt;
+
+#if GMCS_SOURCE
+ if ((instance_expr != null) && (instance_expr.Type.IsGenericParameter))
+ ig.Emit (OpCodes.Constrained, instance_expr.Type);
+#endif
+ }
if ((method.CallingConvention & CallingConventions.VarArgs) != 0) {
Type[] varargs_types = GetVarargsTypes (method, Arguments);
return null;
}
- bool is_struct = type.IsValueType;
+ bool is_struct = TypeManager.IsStruct (type);
eclass = ExprClass.Value;
//
return;
}
- if (!type.IsValueType){
+ if (!TypeManager.IsStruct (type)){
//
// We throw an exception. So far, I believe we only need to support
// value types:
// If we are dealing with a struct, get the
// address of it, so we can store it.
//
- if ((dims == 1) && etype.IsValueType &&
+ if ((dims == 1) && TypeManager.IsStruct (etype) &&
(!TypeManager.IsBuiltinOrEnum (etype) ||
etype == TypeManager.decimal_type)) {
return this;
}
- public override HoistedVariable HoistedVariable {
- get { return null; }
+ public override HoistedVariable GetHoistedVariable (EmitContext ec)
+ {
+ return null;
}
}
get { return false; }
}
- protected override bool IsHoistedEmitRequired (EmitContext ec)
+ public override HoistedVariable GetHoistedVariable (EmitContext ec)
{
- //
- // Handle 'this' differently, it cannot be assigned hence
- // when we are not inside anonymous method we can emit direct access
- //
- return ec.CurrentAnonymousMethod != null && base.IsHoistedEmitRequired (ec);
- }
+ // Is null when probing IsHoisted
+ if (ec == null)
+ return null;
+
+ if (ec.CurrentAnonymousMethod == null)
+ return null;
+
+ AnonymousMethodStorey storey = ec.CurrentAnonymousMethod.Storey;
+ while (storey != null) {
+ AnonymousMethodStorey temp = storey.Parent as AnonymousMethodStorey;
+ if (temp == null)
+ return storey.HoistedThis;
+
+ storey = temp;
+ }
- public override HoistedVariable HoistedVariable {
- get { return TopToplevelBlock.HoistedThisVariable; }
+ return null;
}
public override bool IsRef {
get { return ThisVariable.Instance; }
}
- // TODO: Move to ToplevelBlock
- ToplevelBlock TopToplevelBlock {
- get {
- ToplevelBlock tl = block.Toplevel;
- while (tl.Parent != null) tl = tl.Parent.Toplevel;
- return tl;
- }
- }
-
public static bool IsThisAvailable (EmitContext ec)
{
if (ec.IsStatic || ec.IsInFieldInitializer)
variable_info = block.Toplevel.ThisVariable.VariableInfo;
AnonymousExpression am = ec.CurrentAnonymousMethod;
- if (am != null) {
- //
- // this is hoisted to very top level block
- //
- if (ec.IsVariableCapturingRequired) {
- //
- // TODO: it should be optimized, see test-anon-75.cs
- //
- // `this' variable has its own scope which is mostly empty
- // and causes creation of extraneous storey references.
- // Also it's hard to remove `this' dependencies when we Undo
- // this access.
- //
- AnonymousMethodStorey scope = TopToplevelBlock.Explicit.CreateAnonymousMethodStorey (ec);
- if (HoistedVariable == null) {
- TopToplevelBlock.HoistedThisVariable = scope.CaptureThis (ec, this);
- }
- }
+ if (am != null && ec.IsVariableCapturingRequired) {
+ am.SetHasThisAccess ();
}
}
//
public override void CheckMarshalByRefAccess (EmitContext ec)
{
- if ((variable_info != null) && !(type.IsValueType && ec.OmitStructFlowAnalysis) &&
+ if ((variable_info != null) && !(TypeManager.IsStruct (type) && ec.OmitStructFlowAnalysis) &&
!variable_info.IsAssigned (ec)) {
Error (188, "The `this' object cannot be used before all of its " +
"fields are assigned to");
target.block = clonectx.LookupBlock (block);
}
- public void RemoveHoisting ()
- {
- TopToplevelBlock.HoistedThisVariable = null;
- }
-
public override void SetHasAddressTaken ()
{
// Nothing
this.expr = expr;
}
- // TODO: this method has very poor performace for Enum fields and
- // probably for other constants as well
Expression DoResolve (EmitContext ec, Expression right_side)
{
if (type != null)
string LookupIdentifier = MemberName.MakeName (Name, targs);
- if (expr_resolved is Namespace) {
- Namespace ns = (Namespace) expr_resolved;
+ Namespace ns = expr_resolved as Namespace;
+ if (ns != null) {
FullNamedExpression retval = ns.Lookup (ec.DeclContainer, LookupIdentifier, loc);
-#if GMCS_SOURCE
- if ((retval != null) && (targs != null))
- retval = new ConstructedType (retval, targs, loc).ResolveAsTypeStep (ec, false);
-#endif
if (retval == null)
- ns.Error_NamespaceDoesNotExist (ec.DeclContainer, loc, Name);
+ ns.Error_NamespaceDoesNotExist (ec.DeclContainer, loc, LookupIdentifier);
+ else if (targs != null)
+ retval = new GenericTypeExpr (retval.Type, targs, loc).ResolveAsTypeStep (ec, false);
+
return retval;
}
}
#if GMCS_SOURCE
- ConstructedType ct = expr_resolved as ConstructedType;
+ GenericTypeExpr ct = expr_resolved as GenericTypeExpr;
if (ct != null) {
//
// When looking up a nested type in a generic instance
//
// See gtest-172-lib.cs and gtest-172.cs for an example.
//
- ct = new ConstructedType (
+ ct = new GenericTypeExpr (
member_lookup.Type, ct.TypeArguments, loc);
return ct.ResolveAsTypeStep (ec, false);
public FullNamedExpression ResolveNamespaceOrType (IResolveContext rc, bool silent)
{
- FullNamedExpression new_expr = expr.ResolveAsTypeStep (rc, silent);
+ FullNamedExpression expr_resolved = expr.ResolveAsTypeStep (rc, silent);
- if (new_expr == null)
+ if (expr_resolved == null)
return null;
string LookupIdentifier = MemberName.MakeName (Name, targs);
- if (new_expr is Namespace) {
- Namespace ns = (Namespace) new_expr;
+ Namespace ns = expr_resolved as Namespace;
+ if (ns != null) {
FullNamedExpression retval = ns.Lookup (rc.DeclContainer, LookupIdentifier, loc);
-#if GMCS_SOURCE
- if ((retval != null) && (targs != null))
- retval = new ConstructedType (retval, targs, loc).ResolveAsTypeStep (rc, false);
-#endif
- if (!silent && retval == null)
+
+ if (retval == null && !silent)
ns.Error_NamespaceDoesNotExist (rc.DeclContainer, loc, LookupIdentifier);
+ else if (targs != null)
+ retval = new GenericTypeExpr (retval.Type, targs, loc).ResolveAsTypeStep (rc, silent);
+
return retval;
}
- TypeExpr tnew_expr = new_expr.ResolveAsTypeTerminal (rc, false);
+ TypeExpr tnew_expr = expr_resolved.ResolveAsTypeTerminal (rc, false);
if (tnew_expr == null)
return null;
if (silent)
return null;
- Error_IdentifierNotFound (rc, new_expr, LookupIdentifier);
+ Error_IdentifierNotFound (rc, expr_resolved, LookupIdentifier);
return null;
}
#if GMCS_SOURCE
TypeArguments the_args = targs;
Type declaring_type = texpr.Type.DeclaringType;
- if (TypeManager.HasGenericArguments (declaring_type)) {
+ if (TypeManager.HasGenericArguments (declaring_type) && !TypeManager.IsGenericTypeDefinition (expr_type)) {
while (!TypeManager.IsEqual (TypeManager.DropGenericTypeArguments (expr_type), declaring_type)) {
expr_type = expr_type.BaseType;
}
- TypeArguments new_args = new TypeArguments (loc);
+ TypeArguments new_args = new TypeArguments ();
foreach (Type decl in TypeManager.GetTypeArguments (expr_type))
new_args.Add (new TypeExpression (decl, loc));
}
if (the_args != null) {
- ConstructedType ctype = new ConstructedType (texpr.Type, the_args, loc);
+ GenericTypeExpr ctype = new GenericTypeExpr (texpr.Type, the_args, loc);
return ctype.ResolveAsTypeStep (rc, false);
}
#endif
if (expr_type == null)
return;
- Namespace.Error_TypeArgumentsCannotBeUsed (expr_type.Type, loc);
+ Namespace.Error_TypeArgumentsCannotBeUsed (expr_type, loc);
return;
}
if (type.IsPointer)
return MakePointerAccess (ec, type);
- if (Expr.eclass != ExprClass.Variable && type.IsValueType)
+ if (Expr.eclass != ExprClass.Variable && TypeManager.IsStruct (type))
Error_CannotModifyIntermediateExpressionValue (ec);
return (new IndexerAccess (this, loc)).DoResolveLValue (ec, right_side);
ig.Emit (OpCodes.Ldelem_I);
else if (TypeManager.IsEnumType (type)){
EmitLoadOpcode (ig, TypeManager.GetEnumUnderlyingType (type), rank);
- } else if (type.IsValueType){
+ } else if (TypeManager.IsStruct (type)){
ig.Emit (OpCodes.Ldelema, type);
ig.Emit (OpCodes.Ldobj, type);
#if GMCS_SOURCE
has_type_arg = true;
is_stobj = true;
return OpCodes.Stobj;
- } else if (t.IsValueType) {
+ } else if (TypeManager.IsStruct (t)) {
has_type_arg = true;
is_stobj = true;
return OpCodes.Stobj;
private EmptyExpressionStatement ()
{
- type = TypeManager.object_type;
eclass = ExprClass.Value;
loc = Location.Null;
}
public override Expression DoResolve (EmitContext ec)
{
+ type = TypeManager.object_type;
return this;
}
Type ltype = lexpr.Type;
#if GMCS_SOURCE
if ((dim.Length > 0) && (dim [0] == '?')) {
- TypeExpr nullable = new Nullable.NullableType (left, loc);
+ TypeExpr nullable = new Nullable.NullableType (lexpr, loc);
if (dim.Length > 1)
nullable = new ComposedCast (nullable, dim.Substring (1), loc);
return nullable.ResolveAsTypeTerminal (ec, false);
//
Constant c = source as Constant;
if (c != null && c.IsDefaultInitializer (type) && target.eclass == ExprClass.Variable)
- return EmptyExpressionStatement.Instance;
+ return EmptyExpressionStatement.Instance.DoResolve (ec);
return expr;
}
if (anonymous_type == null)
return null;
- ConstructedType te = new ConstructedType (anonymous_type.TypeBuilder,
- new TypeArguments (loc, t_args), loc);
+ GenericTypeExpr te = new GenericTypeExpr (anonymous_type.TypeBuilder,
+ new TypeArguments (t_args), loc);
return new New (te, arguments, loc).Resolve (ec);
}