// This is used if the expression should be resolved as a type or namespace name.
// the default implementation fails.
//
- public virtual FullNamedExpression ResolveAsTypeStep (IMemberContext rc, bool silent)
+ public virtual TypeSpec ResolveAsType (IMemberContext mc)
{
- if (!silent) {
- ResolveContext ec = new ResolveContext (rc);
- Expression e = Resolve (ec);
- if (e != null)
- e.Error_UnexpectedKind (ec, ResolveFlags.Type, loc);
- }
+ ResolveContext ec = new ResolveContext (mc);
+ Expression e = Resolve (ec);
+ if (e != null)
+ e.Error_UnexpectedKind (ec, ResolveFlags.Type, loc);
return null;
}
- //
- // This is used to resolve the expression as a type, a null
- // value will be returned if the expression is not a type
- // reference
- //
- public virtual TypeExpr ResolveAsTypeTerminal (IMemberContext ec , bool silent)
- {
- // FIXME: THIS IS TOO SLOW and it should not be needed either
- int errors = ec.Module.Compiler.Report.Errors;
-
- FullNamedExpression fne = ResolveAsTypeStep (ec, silent);
-
- if (fne == null)
- return null;
-
- TypeExpr te = fne as TypeExpr;
- if (te == null) {
- if (!silent && errors == ec.Module.Compiler.Report.Errors)
- fne.Error_UnexpectedKind (ec.Module.Compiler.Report, null, "type", loc);
- return null;
- }
-
- if (!te.type.IsAccessible (ec.CurrentType)) {
- ec.Module.Compiler.Report.SymbolRelatedToPreviousError (te.Type);
- ErrorIsInaccesible (ec, te.Type.GetSignatureForError (), loc);
- }
-
- te.loc = loc;
-
- var dep = te.type.GetMissingDependencies ();
- if (dep != null) {
- ImportedTypeDefinition.Error_MissingDependency (ec, dep, loc);
- }
-
- //
- // Obsolete checks cannot be done when resolving base context as they
- // require type dependecies to be set but we are just resolving them
- //
- if (!silent && !(ec is TypeContainer.BaseContext)) {
- ObsoleteAttribute obsolete_attr = te.Type.GetAttributeObsolete ();
- if (obsolete_attr != null && !ec.IsObsolete) {
- AttributeTester.Report_ObsoleteMessage (obsolete_attr, te.GetSignatureForError (), Location, ec.Module.Compiler.Report);
- }
- }
-
- return te;
- }
-
public static void ErrorIsInaccesible (IMemberContext rc, string member, Location loc)
{
rc.Module.Compiler.Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", member);
string from_type = type.GetSignatureForError ();
string to_type = target.GetSignatureForError ();
if (from_type == to_type) {
- from_type = string.Format ("{0} [{1}]", from_type, type.MemberDefinition.DeclaringAssembly.FullName);
- to_type = string.Format ("{0} [{1}]", to_type, target.MemberDefinition.DeclaringAssembly.FullName);
+ from_type = type.GetSignatureForErrorIncludingAssemblyName ();
+ to_type = target.GetSignatureForErrorIncludingAssemblyName ();
}
if (expl) {
}
}
- public void Error_TypeArgumentsCannotBeUsed (Report report, Location loc, MemberSpec member, int arity)
+ public void Error_TypeArgumentsCannotBeUsed (IMemberContext context, MemberSpec member, int arity, Location loc)
{
// Better message for possible generic expressions
if (member != null && (member.Kind & MemberKind.GenericMask) != 0) {
+ var report = context.Module.Compiler.Report;
report.SymbolRelatedToPreviousError (member);
if (member is TypeSpec)
member = ((TypeSpec) member).GetDefinition ();
name, member.GetSignatureForError ());
}
} else {
- Error_TypeArgumentsCannotBeUsed (report, ExprClassName, GetSignatureForError (), loc);
+ Error_TypeArgumentsCannotBeUsed (context, ExprClassName, GetSignatureForError (), loc);
}
}
- public void Error_TypeArgumentsCannotBeUsed (Report report, string exprType, string name, Location loc)
+ public void Error_TypeArgumentsCannotBeUsed (IMemberContext context, string exprType, string name, Location loc)
{
- report.Error (307, loc, "The {0} `{1}' cannot be used with type arguments",
+ context.Module.Compiler.Report.Error (307, loc, "The {0} `{1}' cannot be used with type arguments",
exprType, name);
}
return e;
} catch (Exception ex) {
- if (loc.IsNull || Report.DebugFlags > 0 || ex is CompletionResult || ec.Report.IsDisabled)
+ if (loc.IsNull || ec.Module.Compiler.Settings.DebugFlags > 0 || ex is CompletionResult || ec.Report.IsDisabled)
throw;
ec.Report.Error (584, loc, "Internal compiler error: {0}", ex.Message);
public Expression ResolveLValue (ResolveContext ec, Expression right_side)
{
int errors = ec.Report.Errors;
- bool out_access = right_side == EmptyExpression.OutAccess.Instance;
+ bool out_access = right_side == EmptyExpression.OutAccess;
Expression e = DoResolveLValue (ec, right_side);
}
var r = new OverloadResolver (ctors, OverloadResolver.Restrictions.NoBaseMembers, loc);
- return r.ResolveMember<MethodSpec> (rc, ref args);
+ var ctor = r.ResolveMember<MethodSpec> (rc, ref args);
+ if (ctor == null)
+ return null;
+
+ if ((ctor.Modifiers & Modifiers.PROTECTED) != 0 && !rc.HasSet (ResolveContext.Options.BaseInitializer)) {
+ MemberExpr.CheckProtectedMemberAccess (rc, ctor, ctor.DeclaringType, loc);
+ }
+
+ return ctor;
}
[Flags]
// Lookup type `queried_type' for code in class `container_type' with a qualifier of
// `qualifier_type' or null to lookup members in the current class.
//
- public static Expression MemberLookup (ResolveContext rc, TypeSpec currentType, TypeSpec queried_type, string name, int arity, MemberLookupRestrictions restrictions, Location loc)
+ public static Expression MemberLookup (IMemberContext rc, bool errorMode, TypeSpec queried_type, string name, int arity, MemberLookupRestrictions restrictions, Location loc)
{
var members = MemberCache.FindMembers (queried_type, name, false);
if (members == null)
MemberSpec non_method = null;
MemberSpec ambig_non_method = null;
- currentType = currentType ?? InternalType.FakeInternalType;
do {
for (int i = 0; i < members.Count; ++i) {
var member = members[i];
if ((arity > 0 || (restrictions & MemberLookupRestrictions.ExactArity) != 0) && member.Arity != arity)
continue;
- if (rc != null) {
- if (!member.IsAccessible (currentType))
+ if (!errorMode) {
+ if (!member.IsAccessible (rc))
continue;
//
// }
// }
//
- if (rc.IsRuntimeBinder && !member.DeclaringType.IsAccessible (currentType))
+ if (rc.Module.Compiler.IsRuntimeBinder && !member.DeclaringType.IsAccessible (rc))
continue;
}
continue;
}
- if (non_method == null || member is MethodSpec) {
+ if (non_method == null || member is MethodSpec || non_method.IsNotCSharpCompatible) {
non_method = member;
- } else if (currentType != null) {
+ } else if (!errorMode && !member.IsNotCSharpCompatible) {
ambig_non_method = member;
}
}
if (non_method != null) {
if (ambig_non_method != null && rc != null) {
- rc.Report.SymbolRelatedToPreviousError (non_method);
- rc.Report.SymbolRelatedToPreviousError (ambig_non_method);
- rc.Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
+ var report = rc.Module.Compiler.Report;
+ report.SymbolRelatedToPreviousError (non_method);
+ report.SymbolRelatedToPreviousError (ambig_non_method);
+ report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
non_method.GetSignatureForError (), ambig_non_method.GetSignatureForError ());
}
//
protected Expression ConvertExpressionToArrayIndex (ResolveContext ec, Expression source)
{
- var btypes = ec.BuildinTypes;
+ var btypes = ec.BuiltinTypes;
- if (source.type == InternalType.Dynamic) {
+ if (source.type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
Arguments args = new Arguments (1);
args.Add (new Argument (source));
return new DynamicConversion (btypes.Int, CSharpBinderFlags.ConvertArrayIndex, args, loc).Resolve (ec);
Error_NegativeArrayIndex (ec, source.loc);
// No conversion needed to array index
- if (converted.Type.BuildinType == BuildinTypeSpec.Type.Int)
+ if (converted.Type.BuiltinType == BuiltinTypeSpec.Type.Int)
return converted;
- return new ArrayIndexCast (converted).Resolve (ec);
+ return new ArrayIndexCast (converted, btypes.Int).Resolve (ec);
}
//
protected static TypeExpr CreateExpressionTypeExpression (ResolveContext ec, Location loc)
{
- var t = ec.Module.PredefinedTypes.Expression.Resolve (loc);
+ var t = ec.Module.PredefinedTypes.Expression.Resolve ();
if (t == null)
return null;
{
Arguments args = new Arguments (2);
args.Add (new Argument (child.CreateExpressionTree (ec)));
- args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
+ args.Add (new Argument (new TypeOf (type, loc)));
if (type.IsPointer || child.Type.IsPointer)
Error_PointerInsideExpressionTree (ec);
}
//
- // Used for predefined class library user casts (no obsolete check, etc.)
+ // Used for predefined type user operator (no obsolete check, etc.)
//
- public class OperatorCast : TypeCast {
- MethodSpec conversion_operator;
-
- public OperatorCast (Expression child, TypeSpec target_type)
- : this (child, target_type, false)
- {
- }
-
- public OperatorCast (Expression child, TypeSpec target_type, bool find_explicit)
- : base (child, target_type)
- {
- conversion_operator = GetConversionOperator (find_explicit);
- if (conversion_operator == null)
- throw new InternalErrorException ("Outer conversion routine is out of sync");
- }
-
- // Returns the implicit operator that converts from
- // 'child.Type' to our target type (type)
- MethodSpec GetConversionOperator (bool find_explicit)
- {
- var op = find_explicit ? Operator.OpType.Explicit : Operator.OpType.Implicit;
-
- var mi = MemberCache.GetUserOperator (child.Type, op, true);
- if (mi == null){
- mi = MemberCache.GetUserOperator (type, op, true);
- }
-
- foreach (MethodSpec oper in mi) {
- if (oper.ReturnType != type)
- continue;
-
- if (oper.Parameters.Types [0] == child.Type)
- return oper;
- }
-
- return null;
- }
+ public class OperatorCast : TypeCast
+ {
+ readonly MethodSpec conversion_operator;
- public override void Emit (EmitContext ec)
- {
- child.Emit (ec);
- ec.Emit (OpCodes.Call, conversion_operator);
- }
- }
-
- /// <summary>
- /// This is a numeric cast to a Decimal
- /// </summary>
- public class CastToDecimal : OperatorCast {
- public CastToDecimal (Expression child)
- : this (child, false)
+ public OperatorCast (Expression expr, TypeSpec target_type)
+ : this (expr, target_type, target_type, false)
{
}
-
- public CastToDecimal (Expression child, bool find_explicit)
- : base (child, TypeManager.decimal_type, find_explicit)
+
+ public OperatorCast (Expression expr, TypeSpec target_type, bool find_explicit)
+ : this (expr, target_type, target_type, find_explicit)
{
}
- }
-
- /// <summary>
- /// This is an explicit numeric cast from a Decimal
- /// </summary>
- public class CastFromDecimal : TypeCast
- {
- static Dictionary<TypeSpec, MethodSpec> operators;
-
- public CastFromDecimal (Expression child, TypeSpec return_type)
- : base (child, return_type)
+
+ public OperatorCast (Expression expr, TypeSpec declaringType, TypeSpec returnType, bool isExplicit)
+ : base (expr, returnType)
{
- if (child.Type.BuildinType != BuildinTypeSpec.Type.Decimal)
- throw new ArgumentException ("Expected decimal child " + child.Type.GetSignatureForError ());
- }
+ var op = isExplicit ? Operator.OpType.Explicit : Operator.OpType.Implicit;
+ var mi = MemberCache.GetUserOperator (declaringType, op, true);
- // Returns the explicit operator that converts from an
- // express of type System.Decimal to 'type'.
- public Expression Resolve ()
- {
- if (operators == null) {
- var all_oper = MemberCache.GetUserOperator (TypeManager.decimal_type, Operator.OpType.Explicit, true);
+ if (mi != null) {
+ foreach (MethodSpec oper in mi) {
+ if (oper.ReturnType != returnType)
+ continue;
- operators = new Dictionary<TypeSpec, MethodSpec> ();
- foreach (MethodSpec oper in all_oper) {
- AParametersCollection pd = oper.Parameters;
- if (pd.Types [0].BuildinType == BuildinTypeSpec.Type.Decimal)
- operators.Add (oper.ReturnType, oper);
+ if (oper.Parameters.Types[0] == expr.Type) {
+ conversion_operator = oper;
+ return;
+ }
}
}
- return operators.ContainsKey (type) ? this : null;
+ throw new InternalErrorException ("Missing predefined user operator between `{0}' and `{1}'",
+ returnType.GetSignatureForError (), expr.Type.GetSignatureForError ());
}
public override void Emit (EmitContext ec)
{
child.Emit (ec);
-
- ec.Emit (OpCodes.Call, operators [type]);
- }
-
- public static void Reset ()
- {
- operators = null;
+ ec.Emit (OpCodes.Call, conversion_operator);
}
}
-
//
// Constant specialization of EmptyCast.
//
public class EmptyConstantCast : Constant
{
- public Constant child;
+ public readonly Constant child;
public EmptyConstantCast (Constant child, TypeSpec type)
: base (child.Location)
{
Arguments args = Arguments.CreateForExpressionTree (ec, null,
child.CreateExpressionTree (ec),
- new TypeOf (new TypeExpression (type, loc), loc));
+ new TypeOf (type, loc));
if (type.IsPointer)
Error_PointerInsideExpressionTree (ec);
get { return child.IsZeroInteger; }
}
- protected override Expression DoResolve (ResolveContext rc)
- {
- return this;
- }
-
public override void Emit (EmitContext ec)
{
child.Emit (ec);
return child.GetValueAsLong ();
}
- public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec target_type)
+ public override Constant ConvertImplicitly (TypeSpec target_type)
{
if (type == target_type)
return this;
if (!Convert.ImplicitStandardConversionExists (this, target_type))
return null;
- return child.ConvertImplicitly (rc, target_type);
+ return child.ConvertImplicitly (target_type);
}
}
: base (child.Location)
{
this.Child = child;
+
+ this.eclass = ExprClass.Value;
this.type = enum_type;
}
{
}
- protected override Expression DoResolve (ResolveContext rc)
- {
- Child = Child.Resolve (rc);
- this.eclass = ExprClass.Value;
- return this;
- }
-
public override void Emit (EmitContext ec)
{
Child.Emit (ec);
return Child.ConvertExplicitly (in_checked_context, target_type);
}
- public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
+ public override Constant ConvertImplicitly (TypeSpec type)
{
if (this.type == type) {
return this;
return null;
}
- return Child.ConvertImplicitly (rc, type);
+ return Child.ConvertImplicitly (type);
}
}
public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
{
// Only boxing to object type is supported
- if (targetType.BuildinType != BuildinTypeSpec.Type.Object) {
+ if (targetType.BuiltinType != BuiltinTypeSpec.Type.Object) {
base.EncodeAttributeValue (rc, enc, targetType);
return;
}
{
// boxing is side-effectful, since it involves runtime checks, except when boxing to Object or ValueType
// so, we need to emit the box+pop instructions in most cases
- if (TypeManager.IsStruct (child.Type) &&
- (type.BuildinType == BuildinTypeSpec.Type.Object || type.BuildinType == BuildinTypeSpec.Type.ValueType))
+ if (child.Type.IsStruct &&
+ (type.BuiltinType == BuiltinTypeSpec.Type.Object || type.BuiltinType == BuiltinTypeSpec.Type.ValueType))
child.EmitSideEffect (ec);
else
base.EmitSideEffect (ec);
this.orig_expr = orig_expr;
}
- public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec target_type)
+ public override Constant ConvertImplicitly (TypeSpec target_type)
{
- Constant c = base.ConvertImplicitly (rc, target_type);
+ Constant c = base.ConvertImplicitly (target_type);
if (c != null)
c = new ReducedConstantExpression (c, orig_expr);
{
this.orig_expr = orig;
this.stm = stm;
+ this.eclass = stm.eclass;
+ this.type = stm.Type;
+
this.loc = orig.Location;
}
protected override Expression DoResolve (ResolveContext ec)
{
- eclass = stm.eclass;
- type = stm.Type;
return this;
}
this.loc = expr.Location;
}
- public override Expression CreateExpressionTree (ResolveContext ec)
+ public override Expression CreateExpressionTree (ResolveContext rc)
{
- return expr.CreateExpressionTree (ec);
+ return expr.CreateExpressionTree (rc);
}
public Expression Child {
get { return expr; }
}
- protected override Expression DoResolve (ResolveContext ec)
+ protected override Expression DoResolve (ResolveContext rc)
{
- expr = expr.Resolve (ec);
+ expr = expr.Resolve (rc);
if (expr != null) {
type = expr.Type;
eclass = expr.eclass;
this.expr = expr;
}
+ public Expression Expr {
+ get {
+ return expr;
+ }
+ }
+
protected override void CloneTo (CloneContext clonectx, Expression t)
{
if (expr == null)
throw new InternalErrorException ("Missing Resolve call");
}
- public Expression Expr {
- get { return expr; }
- }
}
//
return new SimpleName (Name, targs, loc);
}
- protected virtual void Error_TypeOrNamespaceNotFound (IMemberContext ec)
+ protected override Expression DoResolve (ResolveContext ec)
+ {
+ return SimpleNameResolve (ec, null, false);
+ }
+
+ public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
+ {
+ return SimpleNameResolve (ec, right_side, false);
+ }
+
+ protected virtual void Error_TypeOrNamespaceNotFound (IMemberContext ctx)
{
- if (ec.CurrentType != null) {
- if (ec.CurrentMemberDefinition != null) {
- MemberCore mc = ec.CurrentMemberDefinition.Parent.GetDefinition (Name);
+ if (ctx.CurrentType != null) {
+ if (ctx.CurrentMemberDefinition != null) {
+ MemberCore mc = ctx.CurrentMemberDefinition.Parent.GetDefinition (Name);
if (mc != null) {
- Error_UnexpectedKind (ec.Module.Compiler.Report, mc, "type", GetMemberType (mc), loc);
+ Error_UnexpectedKind (ctx.Module.Compiler.Report, mc, "type", GetMemberType (mc), loc);
return;
}
}
-
- /*
- // TODO MemberCache: Implement
-
- string ns = ec.CurrentType.Namespace;
- string fullname = (ns.Length > 0) ? ns + "." + Name : Name;
- foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) {
- var type = a.GetType (fullname);
- if (type != null) {
- ec.Compiler.Report.SymbolRelatedToPreviousError (type);
- Expression.ErrorIsInaccesible (loc, TypeManager.CSharpName (type), ec.Compiler.Report);
- return;
- }
- }
-
- if (ec.CurrentTypeDefinition != null) {
- TypeSpec t = ec.CurrentTypeDefinition.LookupAnyGeneric (Name);
- if (t != null) {
- Namespace.Error_InvalidNumberOfTypeArguments (ec.Compiler.Report, t, loc);
- return;
- }
- }
- */
}
- FullNamedExpression retval = ec.LookupNamespaceOrType (Name, -System.Math.Max (1, Arity), loc, true);
+ // MSAF
+ var retval = ctx.LookupNamespaceOrType (Name, Arity, LookupMode.IgnoreAccessibility, loc);
if (retval != null) {
- Error_TypeArgumentsCannotBeUsed (ec.Module.Compiler.Report, loc, retval.Type, Arity);
-/*
- var te = retval as TypeExpr;
- if (HasTypeArguments && te != null && !te.Type.IsGeneric)
- retval.Error_TypeArgumentsCannotBeUsed (ec.Compiler.Report, loc);
- else
- Namespace.Error_InvalidNumberOfTypeArguments (ec.Compiler.Report, retval.Type, loc);
-*/
+ ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (retval.Type);
+ ErrorIsInaccesible (ctx, retval.GetSignatureForError (), loc);
return;
}
- NamespaceEntry.Error_NamespaceNotFound (loc, Name, ec.Module.Compiler.Report);
- }
-
- protected override Expression DoResolve (ResolveContext ec)
- {
- return SimpleNameResolve (ec, null, false);
- }
+ retval = ctx.LookupNamespaceOrType (Name, -System.Math.Max (1, Arity), LookupMode.Probing, loc);
+ if (retval != null) {
+ Error_TypeArgumentsCannotBeUsed (ctx, retval.Type, Arity, loc);
+ return;
+ }
- public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
- {
- return SimpleNameResolve (ec, right_side, false);
+ NamespaceContainer.Error_NamespaceNotFound (loc, Name, ctx.Module.Compiler.Report);
}
- public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent)
+ public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext ec)
{
- int errors = ec.Module.Compiler.Report.Errors;
- FullNamedExpression fne = ec.LookupNamespaceOrType (Name, Arity, loc, /*ignore_cs0104=*/ false);
+ FullNamedExpression fne = ec.LookupNamespaceOrType (Name, Arity, LookupMode.Normal, loc);
if (fne != null) {
if (fne.Type != null && Arity > 0) {
if (HasTypeArguments) {
GenericTypeExpr ct = new GenericTypeExpr (fne.Type, targs, loc);
- return ct.ResolveAsTypeStep (ec, false);
+ if (ct.ResolveAsType (ec) == null)
+ return null;
+
+ return ct;
}
return new GenericOpenTypeExpr (fne.Type, loc);
ec.Module.PredefinedAttributes.Dynamic.GetSignatureForError ());
}
- return new DynamicTypeExpr (loc);
+ fne = new DynamicTypeExpr (loc);
+ fne.ResolveAsType (ec);
}
if (fne != null)
return fne;
- if (silent || errors != ec.Module.Compiler.Report.Errors)
- return null;
-
Error_TypeOrNamespaceNotFound (ec);
return null;
}
+ public bool IsPossibleTypeOrNamespace (IMemberContext mc)
+ {
+ return mc.LookupNamespaceOrType (Name, Arity, LookupMode.Probing, loc) != null;
+ }
+
public override Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restrictions)
{
int lookup_arity = Arity;
e = variable.CreateReferenceExpression (rc, loc);
if (e != null) {
if (Arity > 0)
- Error_TypeArgumentsCannotBeUsed (rc.Report, "variable", Name, loc);
+ Error_TypeArgumentsCannotBeUsed (rc, "variable", Name, loc);
return e;
}
// Stage 2: Lookup members if we are inside a type up to top level type for nested types
//
TypeSpec member_type = rc.CurrentType;
- TypeSpec current_type = member_type;
for (; member_type != null; member_type = member_type.DeclaringType) {
- e = MemberLookup (errorMode ? null : rc, current_type, member_type, Name, lookup_arity, restrictions, loc);
+ e = MemberLookup (rc, errorMode, member_type, Name, lookup_arity, restrictions, loc);
if (e == null)
continue;
// Break as there is no other overload available anyway
if ((restrictions & MemberLookupRestrictions.ReadAccess) != 0) {
- if (!pe.PropertyInfo.HasGet || !pe.PropertyInfo.Get.IsAccessible (current_type))
+ if (!pe.PropertyInfo.HasGet || !pe.PropertyInfo.Get.IsAccessible (rc))
break;
pe.Getter = pe.PropertyInfo.Get;
} else {
- if (!pe.PropertyInfo.HasSet || !pe.PropertyInfo.Set.IsAccessible (current_type))
+ if (!pe.PropertyInfo.HasSet || !pe.PropertyInfo.Set.IsAccessible (rc))
break;
pe.Setter = pe.PropertyInfo.Set;
// Stage 3: Lookup nested types, namespaces and type parameters in the context
//
if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0 && !variable_found) {
- e = ResolveAsTypeStep (rc, lookup_arity == 0 || !errorMode);
- if (e != null) {
+ if (IsPossibleTypeOrNamespace (rc)) {
if (variable != null) {
rc.Report.SymbolRelatedToPreviousError (variable.Location, Name);
rc.Report.Error (135, loc, "`{0}' conflicts with a declaration in a child block", Name);
}
- return e;
+ return ResolveAsTypeOrNamespace (rc);
}
}
if (variable_found) {
rc.Report.Error (841, loc, "A local variable `{0}' cannot be used before it is declared", Name);
} else {
+ if (Arity > 0) {
+ TypeParameter[] tparams = rc.CurrentTypeParameters;
+ if (tparams != null) {
+ foreach (var ctp in tparams) {
+ if (ctp.Name == Name) {
+ Error_TypeArgumentsCannotBeUsed (rc, "type parameter", Name, loc);
+ return null;
+ }
+ }
+ }
+
+ var ct = rc.CurrentType;
+ do {
+ if (ct.MemberDefinition.TypeParametersCount > 0) {
+ foreach (var ctp in ct.MemberDefinition.TypeParameters) {
+ if (ctp.Name == Name) {
+ Error_TypeArgumentsCannotBeUsed (rc, "type parameter", Name, loc);
+ return null;
+ }
+ }
+ }
+
+ ct = ct.DeclaringType;
+ } while (ct != null);
+ }
+
+ if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0) {
+ e = rc.LookupNamespaceOrType (Name, Arity, LookupMode.IgnoreAccessibility, loc);
+ if (e != null) {
+ rc.Report.SymbolRelatedToPreviousError (e.Type);
+ ErrorIsInaccesible (rc, e.GetSignatureForError (), loc);
+ return e;
+ }
+ }
+
+ e = rc.LookupNamespaceOrType (Name, -System.Math.Max (1, Arity), LookupMode.Probing, loc);
+ if (e != null) {
+ if (!(e is TypeExpr) || (restrictions & MemberLookupRestrictions.InvocableOnly) == 0 || !e.Type.IsDelegate) {
+ Error_TypeArgumentsCannotBeUsed (rc, e.Type, Arity, loc);
+ return e;
+ }
+ }
+
rc.Report.Error (103, loc, "The name `{0}' does not exist in the current context", Name);
}
- return null;
+ return ErrorExpression.Instance;
}
if (rc.Module.Evaluator != null) {
}
lookup_arity = 0;
- restrictions &= ~MemberLookupRestrictions.InvocableOnly;
errorMode = true;
}
}
throw new NotSupportedException ("ET");
}
- public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent)
+ public abstract FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc);
+
+ //
+ // This is used to resolve the expression as a type, a null
+ // value will be returned if the expression is not a type
+ // reference
+ //
+ public override TypeSpec ResolveAsType (IMemberContext mc)
{
- return this;
+ FullNamedExpression fne = ResolveAsTypeOrNamespace (mc);
+
+ if (fne == null)
+ return null;
+
+ TypeExpr te = fne as TypeExpr;
+ if (te == null) {
+ fne.Error_UnexpectedKind (mc.Module.Compiler.Report, null, "type", loc);
+ return null;
+ }
+
+ te.loc = loc;
+
+ type = te.Type;
+
+ var dep = type.GetMissingDependencies ();
+ if (dep != null) {
+ ImportedTypeDefinition.Error_MissingDependency (mc, dep, loc);
+ }
+
+ //
+ // Obsolete checks cannot be done when resolving base context as they
+ // require type dependencies to be set but we are in process of resolving them
+ //
+ if (!(mc is TypeContainer.BaseContext)) {
+ ObsoleteAttribute obsolete_attr = type.GetAttributeObsolete ();
+ if (obsolete_attr != null && !mc.IsObsolete) {
+ AttributeTester.Report_ObsoleteMessage (obsolete_attr, te.GetSignatureForError (), Location, mc.Module.Compiler.Report);
+ }
+ }
+
+ return type;
}
+
public override void Emit (EmitContext ec)
{
throw new InternalErrorException ("FullNamedExpression `{0}' found in resolved tree",
/// <summary>
/// Expression that evaluates to a type
/// </summary>
- public abstract class TypeExpr : FullNamedExpression {
- public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent)
+ public abstract class TypeExpr : FullNamedExpression
+ {
+ public sealed override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc)
{
- TypeExpr t = DoResolveAsTypeStep (ec);
- if (t == null)
- return null;
-
- eclass = ExprClass.Type;
- return t;
+ ResolveAsType (mc);
+ return this;
}
- protected override Expression DoResolve (ResolveContext ec)
+ protected sealed override Expression DoResolve (ResolveContext ec)
{
- return ResolveAsTypeTerminal (ec, false);
+ ResolveAsType (ec);
+ return this;
}
- protected abstract TypeExpr DoResolveAsTypeStep (IMemberContext ec);
-
public override bool Equals (object obj)
{
TypeExpr tobj = obj as TypeExpr;
/// <summary>
/// Fully resolved Expression that already evaluated to a type
/// </summary>
- public class TypeExpression : TypeExpr {
+ public class TypeExpression : TypeExpr
+ {
public TypeExpression (TypeSpec t, Location l)
{
Type = t;
loc = l;
}
- protected override TypeExpr DoResolveAsTypeStep (IMemberContext ec)
- {
- return this;
- }
-
- public override TypeExpr ResolveAsTypeTerminal (IMemberContext ec, bool silent)
+ public sealed override TypeSpec ResolveAsType (IMemberContext ec)
{
- return this;
+ return type;
}
}
get;
}
- // TODO: Not needed
protected abstract TypeSpec DeclaringType {
get;
}
// Overload resulution works on virtual or non-virtual members only (no overrides). That
// means for base.member access we have to find the closest match after we found best candidate
//
- if ((method.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.STATIC)) != Modifiers.STATIC) {
+ if ((method.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
//
// The method could already be what we are looking for
//
return;
if ((member.Modifiers & Modifiers.PROTECTED) != 0 && !(InstanceExpression is This)) {
- var ct = rc.CurrentType;
- var expr_type = InstanceExpression.Type;
- if (ct == expr_type)
- return;
+ CheckProtectedMemberAccess (rc, member, InstanceExpression.Type, loc);
+ }
+ }
- if ((member.Modifiers & Modifiers.INTERNAL) != 0 && rc.CurrentType.MemberDefinition.IsInternalAsPublic (expr_type.MemberDefinition.DeclaringAssembly))
- return;
+ public static void CheckProtectedMemberAccess<T> (ResolveContext rc, T member, TypeSpec qualifier, Location loc) where T : MemberSpec
+ {
+ var ct = rc.CurrentType;
+ if (ct == qualifier)
+ return;
- expr_type = expr_type.GetDefinition ();
- if (ct != expr_type && !IsSameOrBaseQualifier (ct, expr_type)) {
- rc.Report.SymbolRelatedToPreviousError (member);
- rc.Report.Error (1540, loc,
- "Cannot access protected member `{0}' via a qualifier of type `{1}'. The qualifier must be of type `{2}' or derived from it",
- member.GetSignatureForError (), expr_type.GetSignatureForError (), ct.GetSignatureForError ());
- }
+ if ((member.Modifiers & Modifiers.INTERNAL) != 0 && member.DeclaringType.MemberDefinition.IsInternalAsPublic (ct.MemberDefinition.DeclaringAssembly))
+ return;
+
+ qualifier = qualifier.GetDefinition ();
+ if (ct != qualifier && !IsSameOrBaseQualifier (ct, qualifier)) {
+ rc.Report.SymbolRelatedToPreviousError (member);
+ rc.Report.Error (1540, loc,
+ "Cannot access protected member `{0}' via a qualifier of type `{1}'. The qualifier must be of type `{2}' or derived from it",
+ member.GetSignatureForError (), qualifier.GetSignatureForError (), ct.GetSignatureForError ());
}
}
// a constant, field, property, local variable, or parameter with the same type as the meaning of E as a type-name
if (left is MemberExpr || left is VariableReference) {
- rc.Report.DisableReporting ();
- Expression identical_type = rc.LookupNamespaceOrType (name.Name, 0, loc, true) as TypeExpr;
- rc.Report.EnableReporting ();
+ var identical_type = rc.LookupNamespaceOrType (name.Name, 0, LookupMode.Probing, loc) as TypeExpr;
if (identical_type != null && identical_type.Type == left.Type)
return identical_type;
}
me.ResolveInstanceExpression (rc, rhs);
var fe = me as FieldExpr;
- if (fe != null && fe.IsMarshalByRefAccess ()) {
+ if (fe != null && fe.IsMarshalByRefAccess (rc)) {
rc.Report.SymbolRelatedToPreviousError (me.DeclaringType);
rc.Report.Warning (1690, 1, loc,
"Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
public virtual MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original)
{
- if (left != null && left.IsNull && TypeManager.IsReferenceType (left.Type)) {
+ if (left != null && left.IsNull && TypeSpec.IsReferenceType (left.Type)) {
ec.Report.Warning (1720, 1, left.Location,
"Expression will always cause a `{0}'", "System.NullReferenceException");
}
protected void EmitInstance (EmitContext ec, bool prepare_for_load)
{
TypeSpec instance_type = InstanceExpression.Type;
- if (TypeManager.IsValueType (instance_type)) {
+ if (TypeSpec.IsValueType (instance_type)) {
if (InstanceExpression is IMemoryLocation) {
- ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
+ ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.Load);
} else {
LocalTemporary t = new LocalTemporary (instance_type);
InstanceExpression.Emit (ec);
InstanceExpression.Emit (ec);
// Only to make verifier happy
- if (instance_type.IsGenericParameter && !(InstanceExpression is This) && TypeManager.IsReferenceType (instance_type))
+ if (instance_type.IsGenericParameter && !(InstanceExpression is This) && TypeSpec.IsReferenceType (instance_type))
ec.Emit (OpCodes.Box, instance_type);
}
//
class ExtensionMethodGroupExpr : MethodGroupExpr, OverloadResolver.IErrorHandler
{
- NamespaceEntry namespace_entry;
+ NamespaceContainer namespace_entry;
public readonly Expression ExtensionExpression;
- public ExtensionMethodGroupExpr (IList<MethodSpec> list, NamespaceEntry n, Expression extensionExpr, Location l)
+ public ExtensionMethodGroupExpr (IList<MethodSpec> list, NamespaceContainer n, Expression extensionExpr, Location l)
: base (list.Cast<MemberSpec>().ToList (), extensionExpr.Type, l)
{
this.namespace_entry = n;
}
}
+ public IList<MemberSpec> Candidates {
+ get {
+ return Methods;
+ }
+ }
+
protected override TypeSpec DeclaringType {
get {
return queried_type;
return null;
}
- if (best_candidate.IsConditionallyExcluded (loc))
+ if (best_candidate.IsConditionallyExcluded (ec.Module.Compiler, loc))
ec.Report.Error (765, loc,
"Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree");
return null;
int arity = type_arguments == null ? 0 : type_arguments.Count;
- NamespaceEntry methods_scope = null;
+ NamespaceContainer methods_scope = null;
var methods = rc.LookupExtensionMethod (InstanceExpression.Type, Methods[0].Name, arity, ref methods_scope);
if (methods == null)
return null;
//
// p and q are delegate types or expression tree types
//
- if (p.GetDefinition () == TypeManager.expression_type || q.GetDefinition () == TypeManager.expression_type) {
+ if (p.IsExpressionTreeType || q.IsExpressionTreeType) {
if (q.MemberDefinition != p.MemberDefinition) {
return 0;
}
//
// With identical parameter lists
//
- if (!TypeSpecComparer.Equals (p_m.Parameters.Types,q_m.Parameters.Types))
+ if (!TypeSpecComparer.Equals (p_m.Parameters.Types, q_m.Parameters.Types))
return 0;
p = p_m.ReturnType;
if (q.Kind == MemberKind.Void) {
return p.Kind != MemberKind.Void ? 1: 0;
}
+
+ //
+ // When anonymous method is an asynchronous, and P has a return type Task<Y1>, and Q has a return type Task<Y2>
+ // better conversion is performed between underlying types Y1 and Y2
+ //
+ if (p.IsGenericTask || q.IsGenericTask) {
+ if (p.IsGenericTask != q.IsGenericTask) {
+ return 0;
+ }
+
+ var async_am = a.Expr as AnonymousMethodExpression;
+ if (async_am == null || !async_am.IsAsync)
+ return 0;
+
+ q = q.TypeArguments[0];
+ p = p.TypeArguments[0];
+ }
+
+ //
+ // The parameters are identicial and return type is not void, use better type conversion
+ // on return type to determine better one
+ //
} else {
if (argument_type == p)
return 1;
if (p == null || q == null)
throw new InternalErrorException ("BetterTypeConversion got a null conversion");
- switch (p.BuildinType) {
- case BuildinTypeSpec.Type.Int:
- if (q.BuildinType == BuildinTypeSpec.Type.UInt || q.BuildinType == BuildinTypeSpec.Type.ULong)
+ switch (p.BuiltinType) {
+ case BuiltinTypeSpec.Type.Int:
+ if (q.BuiltinType == BuiltinTypeSpec.Type.UInt || q.BuiltinType == BuiltinTypeSpec.Type.ULong)
return 1;
break;
- case BuildinTypeSpec.Type.Long:
- if (q.BuildinType == BuildinTypeSpec.Type.ULong)
+ case BuiltinTypeSpec.Type.Long:
+ if (q.BuiltinType == BuiltinTypeSpec.Type.ULong)
return 1;
break;
- case BuildinTypeSpec.Type.SByte:
- switch (q.BuildinType) {
- case BuildinTypeSpec.Type.Byte:
- case BuildinTypeSpec.Type.UShort:
- case BuildinTypeSpec.Type.UInt:
- case BuildinTypeSpec.Type.ULong:
+ case BuiltinTypeSpec.Type.SByte:
+ switch (q.BuiltinType) {
+ case BuiltinTypeSpec.Type.Byte:
+ case BuiltinTypeSpec.Type.UShort:
+ case BuiltinTypeSpec.Type.UInt:
+ case BuiltinTypeSpec.Type.ULong:
return 1;
}
break;
- case BuildinTypeSpec.Type.Short:
- switch (q.BuildinType) {
- case BuildinTypeSpec.Type.UShort:
- case BuildinTypeSpec.Type.UInt:
- case BuildinTypeSpec.Type.ULong:
+ case BuiltinTypeSpec.Type.Short:
+ switch (q.BuiltinType) {
+ case BuiltinTypeSpec.Type.UShort:
+ case BuiltinTypeSpec.Type.UInt:
+ case BuiltinTypeSpec.Type.ULong:
return 1;
}
break;
- case BuildinTypeSpec.Type.Dynamic:
+ case BuiltinTypeSpec.Type.Dynamic:
// Dynamic is never better
return 2;
}
- switch (q.BuildinType) {
- case BuildinTypeSpec.Type.Int:
- if (p.BuildinType == BuildinTypeSpec.Type.UInt || p.BuildinType == BuildinTypeSpec.Type.ULong)
+ switch (q.BuiltinType) {
+ case BuiltinTypeSpec.Type.Int:
+ if (p.BuiltinType == BuiltinTypeSpec.Type.UInt || p.BuiltinType == BuiltinTypeSpec.Type.ULong)
return 2;
break;
- case BuildinTypeSpec.Type.Long:
- if (p.BuildinType == BuildinTypeSpec.Type.ULong)
+ case BuiltinTypeSpec.Type.Long:
+ if (p.BuiltinType == BuiltinTypeSpec.Type.ULong)
return 2;
break;
- case BuildinTypeSpec.Type.SByte:
- switch (p.BuildinType) {
- case BuildinTypeSpec.Type.Byte:
- case BuildinTypeSpec.Type.UShort:
- case BuildinTypeSpec.Type.UInt:
- case BuildinTypeSpec.Type.ULong:
+ case BuiltinTypeSpec.Type.SByte:
+ switch (p.BuiltinType) {
+ case BuiltinTypeSpec.Type.Byte:
+ case BuiltinTypeSpec.Type.UShort:
+ case BuiltinTypeSpec.Type.UInt:
+ case BuiltinTypeSpec.Type.ULong:
return 2;
}
break;
- case BuildinTypeSpec.Type.Short:
- switch (p.BuildinType) {
- case BuildinTypeSpec.Type.UShort:
- case BuildinTypeSpec.Type.UInt:
- case BuildinTypeSpec.Type.ULong:
+ case BuiltinTypeSpec.Type.Short:
+ switch (p.BuiltinType) {
+ case BuiltinTypeSpec.Type.UShort:
+ case BuiltinTypeSpec.Type.UInt:
+ case BuiltinTypeSpec.Type.ULong:
return 2;
}
break;
- case BuildinTypeSpec.Type.Dynamic:
+ case BuiltinTypeSpec.Type.Dynamic:
// Dynamic is never better
return 1;
}
//
// LAMESPEC: No idea what the exact rules are for System.Reflection.Missing.Value instead of null
//
- if (e == EmptyExpression.MissingValue && ptypes[i].BuildinType == BuildinTypeSpec.Type.Object || ptypes[i] == InternalType.Dynamic) {
+ if (e == EmptyExpression.MissingValue && ptypes[i].BuiltinType == BuiltinTypeSpec.Type.Object || ptypes[i].BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
e = new MemberAccess (new MemberAccess (new MemberAccess (
new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Reflection", loc), "Missing", loc), "Value", loc);
} else {
//
var at = a.Type;
if (at == pt || TypeSpecComparer.IsEqual (at, pt) ||
- Convert.ImplicitReferenceConversionExists (a.Expr, pt) ||
- Convert.ImplicitBoxingConversion (EmptyExpression.Null, at, pt) != null) {
+ Convert.ImplicitReferenceConversionExists (at, pt) ||
+ Convert.ImplicitBoxingConversion (null, at, pt) != null) {
score = 0;
continue;
}
//
// Using dynamic for ref/out parameter can still succeed at runtime
//
- if (argument.Type == InternalType.Dynamic && argument.Modifier == 0 && (restrictions & Restrictions.CovariantDelegate) == 0)
+ if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && argument.Modifier == 0 && (restrictions & Restrictions.CovariantDelegate) == 0)
return -1;
return 2;
//
// Using dynamic for ref/out parameter can still succeed at runtime
//
- if (argument.Type == InternalType.Dynamic && argument.Modifier == 0 && (restrictions & Restrictions.CovariantDelegate) == 0)
+ if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && argument.Modifier == 0 && (restrictions & Restrictions.CovariantDelegate) == 0)
return -1;
return 1;
}
} else {
- if (argument.Type == InternalType.Dynamic && (restrictions & Restrictions.CovariantDelegate) == 0)
+ if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (restrictions & Restrictions.CovariantDelegate) == 0)
return -1;
//
// Deploy custom error reporting for lambda methods. When probing lambda methods
// keep all errors reported in separate set and once we are done and no best
- // candidate found, this set is used to report more details about what was wrong
+ // candidate was found, this set is used to report more details about what was wrong
// with lambda body
//
if (argument.Expr.Type == InternalType.AnonymousMethod) {
}
}
+ //
+ // Use implicit conversion in all modes to return same candidates when the expression
+ // is used as argument or delegate conversion
+ //
if (!Convert.ImplicitConversionExists (ec, argument.Expr, parameter)) {
if (lambda_conv_msgs != null) {
lambda_conv_msgs.EndSession ();
Arguments candidate_args = args;
bool error_mode = false;
- var current_type = rc.CurrentType;
MemberSpec invocable_member = null;
// Be careful, cannot return until error reporter is restored
continue;
if (!error_mode) {
- if (!member.IsAccessible (current_type))
+ if (!member.IsAccessible (rc))
continue;
- if (rc.IsRuntimeBinder && !member.DeclaringType.IsAccessible (current_type))
+ if (rc.IsRuntimeBinder && !member.DeclaringType.IsAccessible (rc))
continue;
}
return null;
}
+ //
+ // These flags indicates we are running delegate probing conversion. No need to
+ // do more expensive checks
+ //
+ if ((restrictions & (Restrictions.ProbingOnly | Restrictions.CovariantDelegate)) == (Restrictions.CovariantDelegate | Restrictions.ProbingOnly))
+ return (T) best_candidate;
+
if (ambiguous_candidates != null) {
//
// Now check that there are no ambiguities i.e the selected method
else
ec.Report.Error (1620, loc, "Argument `#{0}' is missing `{1}' modifier",
index, Parameter.GetModifierSignature (mod));
- } else {
+ } else if (a.Expr != ErrorExpression.Instance) {
string p1 = a.GetSignatureForError ();
string p2 = TypeManager.CSharpName (paramType);
if (p1 == p2) {
- ec.Report.ExtraInformation (loc, "(equally named types possibly from different assemblies in previous ");
- ec.Report.SymbolRelatedToPreviousError (a.Expr.Type);
- ec.Report.SymbolRelatedToPreviousError (paramType);
+ p1 = a.Type.GetSignatureForErrorIncludingAssemblyName ();
+ p2 = paramType.GetSignatureForErrorIncludingAssemblyName ();
}
ec.Report.Error (1503, loc,
if (ta_count != best_candidate.Arity && (ta_count > 0 || ((IParametersMember) best_candidate).Parameters.IsEmpty)) {
var mg = new MethodGroupExpr (new [] { best_candidate }, best_candidate.DeclaringType, loc);
- mg.Error_TypeArgumentsCannotBeUsed (rc.Report, loc, best_candidate, ta_count);
+ mg.Error_TypeArgumentsCannotBeUsed (rc, best_candidate, ta_count, loc);
return;
}
int unexpanded_count = ((IParametersMember) best_candidate).Parameters.HasParams ? pm.Parameters.Count - 1 : pm.Parameters.Count;
if (pm.Parameters.Count == arg_count || params_expanded || unexpanded_count == arg_count) {
// Reject any inaccessible member
- if (!best_candidate.IsAccessible (rc.CurrentType) || !best_candidate.DeclaringType.IsAccessible (rc.CurrentType)) {
+ if (!best_candidate.IsAccessible (rc) || !best_candidate.DeclaringType.IsAccessible (rc)) {
rc.Report.SymbolRelatedToPreviousError (best_candidate);
Expression.ErrorIsInaccesible (rc, best_candidate.GetSignatureForError (), loc);
return;
}
}
- if (a.Expr.Type == InternalType.Dynamic)
+ if (a.Expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
continue;
- if ((restrictions & Restrictions.CovariantDelegate) != 0 && !Delegate.IsTypeCovariant (ec, a.Expr, pt)) {
+ if ((restrictions & Restrictions.CovariantDelegate) != 0 && !Delegate.IsTypeCovariant (ec, a.Expr.Type, pt)) {
custom_errors.NoArgumentMatch (ec, member);
return false;
}
if (type_arguments == null && member.IsGeneric) {
var ms = (MethodSpec) member;
foreach (var ta in ms.TypeArguments) {
- if (!ta.IsAccessible (ec.CurrentType)) {
+ if (!ta.IsAccessible (ec)) {
ec.Report.SymbolRelatedToPreviousError (ta);
Expression.ErrorIsInaccesible (ec, member.GetSignatureForError (), loc);
break;
public class ConstantExpr : MemberExpr
{
- ConstSpec constant;
+ readonly ConstSpec constant;
public ConstantExpr (ConstSpec constant, Location loc)
{
var c = constant.GetConstant (rc);
// Creates reference expression to the constant value
- return Constant.CreateConstant (rc, constant.MemberType, c.GetValue (), loc);
+ return Constant.CreateConstant (constant.MemberType, c.GetValue (), loc);
}
public override void Emit (EmitContext ec)
public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
{
- Error_TypeArgumentsCannotBeUsed (ec.Report, "constant", GetSignatureForError (), loc);
+ Error_TypeArgumentsCannotBeUsed (ec, "constant", GetSignatureForError (), loc);
}
}
return TypeManager.GetFullNameSignature (spec);
}
- public bool IsMarshalByRefAccess ()
+ public bool IsMarshalByRefAccess (ResolveContext rc)
{
// Checks possible ldflda of field access expression
- return !spec.IsStatic && TypeManager.IsValueType (spec.MemberType) &&
- TypeSpec.IsBaseClass (spec.DeclaringType, TypeManager.mbr_type, false) &&
- !(InstanceExpression is This);
+ return !spec.IsStatic && TypeSpec.IsValueType (spec.MemberType) && !(InstanceExpression is This) &&
+ rc.Module.PredefinedTypes.MarshalByRefObject.Define () &&
+ TypeSpec.IsBaseClass (spec.DeclaringType, rc.Module.PredefinedTypes.MarshalByRefObject.TypeSpec, false);
}
public void SetHasAddressTaken ()
{
bool lvalue_instance = rhs != null && IsInstance && spec.DeclaringType.IsStruct;
- if (ResolveInstanceExpression (ec, rhs)) {
- // Resolve the field's instance expression while flow analysis is turned
- // off: when accessing a field "a.b", we must check whether the field
- // "a.b" is initialized, not whether the whole struct "a" is initialized.
+ if (rhs != this) {
+ if (ResolveInstanceExpression (ec, rhs)) {
+ // Resolve the field's instance expression while flow analysis is turned
+ // off: when accessing a field "a.b", we must check whether the field
+ // "a.b" is initialized, not whether the whole struct "a" is initialized.
- if (lvalue_instance) {
- using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
- bool out_access = rhs == EmptyExpression.OutAccess.Instance || rhs == EmptyExpression.LValueMemberOutAccess;
+ if (lvalue_instance) {
+ using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
+ bool out_access = rhs == EmptyExpression.OutAccess || rhs == EmptyExpression.LValueMemberOutAccess;
- Expression right_side =
- out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
+ Expression right_side =
+ out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
- InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
- }
- } else {
- using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
- InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue);
+ InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
+ }
+ } else {
+ using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
+ InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue);
+ }
}
+
+ if (InstanceExpression == null)
+ return null;
}
- if (InstanceExpression == null)
- return null;
+ DoBestMemberChecks (ec, spec);
}
- DoBestMemberChecks (ec, spec);
-
var fb = spec as FixedFieldSpec;
IVariableReference var = InstanceExpression as IVariableReference;
Expression Report_AssignToReadonly (ResolveContext ec, Expression right_side)
{
int i = 0;
- if (right_side == EmptyExpression.OutAccess.Instance || right_side == EmptyExpression.LValueMemberOutAccess)
+ if (right_side == EmptyExpression.OutAccess || right_side == EmptyExpression.LValueMemberOutAccess)
i += 1;
if (IsStatic)
i += 2;
spec.MemberDefinition.SetIsAssigned ();
- if ((right_side == EmptyExpression.UnaryAddress || right_side == EmptyExpression.OutAccess.Instance) &&
+ if ((right_side == EmptyExpression.UnaryAddress || right_side == EmptyExpression.OutAccess) &&
(spec.Modifiers & Modifiers.VOLATILE) != 0) {
ec.Report.Warning (420, 1, loc,
"`{0}': A volatile field references will not be treated as volatile",
}
}
- if (right_side == EmptyExpression.OutAccess.Instance &&
- !IsStatic && !(InstanceExpression is This) && TypeManager.mbr_type != null && TypeSpec.IsBaseClass (spec.DeclaringType, TypeManager.mbr_type, false)) {
+ if (right_side == EmptyExpression.OutAccess && IsMarshalByRefAccess (ec)) {
ec.Report.SymbolRelatedToPreviousError (spec.DeclaringType);
ec.Report.Warning (197, 1, loc,
"Passing `{0}' as ref or out or taking its address may cause a runtime exception because it is a field of a marshal-by-reference class",
EmitInstance (ec, false);
// Optimization for build-in types
- if (TypeManager.IsStruct (type) && type == ec.CurrentType && InstanceExpression.Type == type) {
+ if (type.IsStruct && type == ec.CurrentType && InstanceExpression.Type == type) {
ec.EmitLoadFromPtr (type);
} else {
var ff = spec as FixedFieldSpec;
public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
{
- prepared = prepare_for_load && !(source is DynamicExpressionStatement);
- if (IsInstance)
- EmitInstance (ec, prepared);
+ var await_expr = source as Await;
+ if (await_expr != null) {
+ //
+ // Await is not ordinary expression (it contains jump), hence the usual flow cannot be used
+ // to emit instance load before expression
+ //
+ await_expr.EmitAssign (ec, this);
+ } else {
+ prepared = prepare_for_load && !(source is DynamicExpressionStatement);
+ if (IsInstance)
+ EmitInstance (ec, prepared);
+
+ source.Emit (ec);
+ }
- source.Emit (ec);
if (leave_copy) {
ec.Emit (OpCodes.Dup);
if (!IsStatic) {
public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
{
- Error_TypeArgumentsCannotBeUsed (ec.Report, "field", GetSignatureForError (), loc);
+ Error_TypeArgumentsCannotBeUsed (ec, "field", GetSignatureForError (), loc);
}
}
bool IsSingleDimensionalArrayLength ()
{
- if (best_candidate.DeclaringType.BuildinType != BuildinTypeSpec.Type.Array || !best_candidate.HasGet || Name != "Length")
+ if (best_candidate.DeclaringType.BuiltinType != BuiltinTypeSpec.Type.Array || !best_candidate.HasGet || Name != "Length")
return false;
ArrayContainer ac = InstanceExpression.Type as ArrayContainer;
{
eclass = ExprClass.PropertyAccess;
- if (best_candidate.IsNotRealProperty) {
+ if (best_candidate.IsNotCSharpCompatible) {
Error_PropertyNotValid (rc);
}
public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
{
- Error_TypeArgumentsCannotBeUsed (ec.Report, "property", GetSignatureForError (), loc);
+ Error_TypeArgumentsCannotBeUsed (ec, "property", GetSignatureForError (), loc);
}
}
public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
{
- if (right_side == EmptyExpression.OutAccess.Instance) {
+ if (right_side == EmptyExpression.OutAccess) {
// TODO: best_candidate can be null at this point
INamedBlockVariable variable = null;
if (best_candidate != null && ec.CurrentBlock.ParametersBlock.TopBlock.GetLocalName (best_candidate.Name, ec.CurrentBlock, ref variable) && variable is Linq.RangeVariable) {
best_candidate.GetSignatureForError ());
return false;
}
- } else if (!best_candidate.Get.IsAccessible (rc.CurrentType)) {
+ } else if (!best_candidate.Get.IsAccessible (rc)) {
if (best_candidate.HasDifferentAccessibility) {
rc.Report.SymbolRelatedToPreviousError (best_candidate.Get);
rc.Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
return false;
}
- if (!best_candidate.Set.IsAccessible (rc.CurrentType)) {
+ if (!best_candidate.Set.IsAccessible (rc)) {
if (best_candidate.HasDifferentAccessibility) {
rc.Report.SymbolRelatedToPreviousError (best_candidate.Set);
rc.Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
{
- Error_TypeArgumentsCannotBeUsed (ec.Report, "event", GetSignatureForError (), loc);
+ Error_TypeArgumentsCannotBeUsed (ec, "event", GetSignatureForError (), loc);
}
}
throw new InternalErrorException ("An implicitly typed local variable could not be redefined");
type = right_side.Type;
- if (type == InternalType.Null || type.Kind == MemberKind.Void || type == InternalType.AnonymousMethod || type == InternalType.MethodGroup) {
+ if (type == InternalType.NullLiteral || type.Kind == MemberKind.Void || type == InternalType.AnonymousMethod || type == InternalType.MethodGroup) {
ec.Report.Error (815, loc,
"An implicitly typed local variable declaration cannot be initialized with `{0}'",
type.GetSignatureForError ());