Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'mcs/gmcs/generic.cs')
-rw-r--r--mcs/gmcs/generic.cs87
1 files changed, 66 insertions, 21 deletions
diff --git a/mcs/gmcs/generic.cs b/mcs/gmcs/generic.cs
index d52299761d6..8d0c4b03d8b 100644
--- a/mcs/gmcs/generic.cs
+++ b/mcs/gmcs/generic.cs
@@ -1495,7 +1495,7 @@ namespace Mono.CSharp {
is_class = is_struct = false;
}
} else {
- is_class = atype.IsClass || atype.IsInterface;
+ is_class = atype.IsClass;
is_struct = atype.IsValueType && !TypeManager.IsNullableType (atype);
}
@@ -1526,16 +1526,26 @@ namespace Mono.CSharp {
// The class constraint comes next.
//
if (gc.HasClassConstraint) {
- if (!CheckConstraint (ec, ptype, aexpr, gc.ClassConstraint))
+ if (!CheckConstraint (ec, ptype, aexpr, gc.ClassConstraint)) {
+ Error_TypeMustBeConvertible (atype, gc.ClassConstraint, ptype);
return false;
+ }
}
//
// Now, check the interface constraints.
//
foreach (Type it in gc.InterfaceConstraints) {
- if (!CheckConstraint (ec, ptype, aexpr, it))
+ Type itype;
+ if (it.IsGenericParameter)
+ itype = atypes [it.GenericParameterPosition];
+ else
+ itype = it;
+
+ if (!CheckConstraint (ec, ptype, aexpr, itype)) {
+ Error_TypeMustBeConvertible (atype, itype, ptype);
return false;
+ }
}
//
@@ -1590,11 +1600,7 @@ namespace Mono.CSharp {
ctype = atypes [pos];
}
- if (Convert.ImplicitStandardConversionExists (ec, expr, ctype))
- return true;
-
- Error_TypeMustBeConvertible (expr.Type, ctype, ptype);
- return false;
+ return Convert.ImplicitStandardConversionExists (ec, expr, ctype);
}
bool HasDefaultConstructor (EmitContext ec, Type atype)
@@ -2685,8 +2691,7 @@ namespace Mono.CSharp {
if (expr == null)
return null;
- if (!(expr is IMemoryLocation))
- temp = new LocalTemporary (ec, expr.Type);
+ temp = new LocalTemporary (ec, expr.Type);
info = new NullableInfo (expr.Type);
type = info.UnderlyingType;
@@ -2706,6 +2711,11 @@ namespace Mono.CSharp {
ec.ig.EmitCall (OpCodes.Call, info.HasValue, null);
}
+ public void Store (EmitContext ec)
+ {
+ create_temp (ec);
+ }
+
void create_temp (EmitContext ec)
{
if ((temp != null) && !has_temp) {
@@ -2740,14 +2750,35 @@ namespace Mono.CSharp {
public void EmitAssign (EmitContext ec, Expression source,
bool leave_copy, bool prepare_for_load)
{
- source.Emit (ec);
- ec.ig.Emit (OpCodes.Newobj, info.Constructor);
+ InternalWrap wrap = new InternalWrap (source, info, loc);
+ ((IAssignMethod) expr).EmitAssign (ec, wrap, leave_copy, false);
+ }
+
+ protected class InternalWrap : Expression
+ {
+ public Expression expr;
+ public NullableInfo info;
+
+ public InternalWrap (Expression expr, NullableInfo info, Location loc)
+ {
+ this.expr = expr;
+ this.info = info;
+ this.loc = loc;
- if (leave_copy)
- ec.ig.Emit (OpCodes.Dup);
+ type = info.Type;
+ eclass = ExprClass.Value;
+ }
- Expression empty = new EmptyExpression (expr.Type);
- ((IAssignMethod) expr).EmitAssign (ec, empty, false, prepare_for_load);
+ public override Expression DoResolve (EmitContext ec)
+ {
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ expr.Emit (ec);
+ ec.ig.Emit (OpCodes.Newobj, info.Constructor);
+ }
}
}
@@ -2951,7 +2982,8 @@ namespace Mono.CSharp {
{
public readonly Binary.Operator Oper;
- Expression left, right, underlying, null_value, bool_wrap;
+ Expression left, right, original_left, original_right;
+ Expression underlying, null_value, bool_wrap;
Unwrap left_unwrap, right_unwrap;
bool is_equality, is_comparision, is_boolean;
@@ -2959,8 +2991,8 @@ namespace Mono.CSharp {
Location loc)
{
this.Oper = op;
- this.left = left;
- this.right = right;
+ this.left = original_left = left;
+ this.right = original_right = right;
this.loc = loc;
}
@@ -2980,8 +3012,16 @@ namespace Mono.CSharp {
return null;
}
- if (((Oper == Binary.Operator.BitwiseAnd) || (Oper == Binary.Operator.BitwiseOr) ||
- (Oper == Binary.Operator.LogicalAnd) || (Oper == Binary.Operator.LogicalOr)) &&
+ if ((Oper == Binary.Operator.LogicalAnd) ||
+ (Oper == Binary.Operator.LogicalOr)) {
+ Binary.Error_OperatorCannotBeApplied (
+ loc, Binary.OperName (Oper),
+ original_left.GetSignatureForError (),
+ original_right.GetSignatureForError ());
+ return null;
+ }
+
+ if (((Oper == Binary.Operator.BitwiseAnd) || (Oper == Binary.Operator.BitwiseOr)) &&
((left.Type == TypeManager.bool_type) && (right.Type == TypeManager.bool_type))) {
Expression empty = new EmptyExpression (TypeManager.bool_type);
bool_wrap = new Wrap (empty, loc).Resolve (ec);
@@ -3214,6 +3254,11 @@ namespace Mono.CSharp {
public override void Emit (EmitContext ec)
{
+ if (left_unwrap != null)
+ left_unwrap.Store (ec);
+ if (right_unwrap != null)
+ right_unwrap.Store (ec);
+
if (is_boolean) {
EmitBoolean (ec);
return;