// Disable control flow analysis while resolving the expression.
// This is used when resolving the instance expression of a field expression.
- DisableFlowAnalysis = 16
+ DisableFlowAnalysis = 16,
+
+ // Set if this is resolving the first part of a MemberAccess.
+ Intermediate = 32
}
//
Warning (warning, s);
}
+ /// <summary>
+ /// Tests presence of ObsoleteAttribute and report proper error
+ /// </summary>
+ protected void CheckObsoleteAttribute (Type type)
+ {
+ ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (type);
+ if (obsolete_attr == null)
+ return;
+
+ AttributeTester.Report_ObsoleteMessage (obsolete_attr, type.FullName, loc);
+ }
+
/// <summary>
/// Performs semantic analysis on the Expression
/// </summary>
ec.DoFlowAnalysis = false;
Expression e;
+ bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate;
if (this is SimpleName)
- e = ((SimpleName) this).DoResolveAllowStatic (ec);
+ e = ((SimpleName) this).DoResolveAllowStatic (ec, intermediate);
+
else
e = DoResolve (ec);
return null;
}
+
+ private static ArrayList almostMatchedMembers = new ArrayList (4);
+
//
// FIXME: Probably implement a cache for (t,name,current_access_set)?
//
string name, MemberTypes mt,
BindingFlags bf, Location loc)
{
+ almostMatchedMembers.Clear ();
+
MemberInfo [] mi = TypeManager.MemberLookup (
- container_type, qualifier_type,queried_type, mt, bf, name);
+ container_type, qualifier_type,queried_type, mt, bf, name,
+ almostMatchedMembers);
if (mi == null)
return null;
e = MemberLookup (ec, ec.ContainerType, qualifier_type, queried_type,
name, mt, bf, loc);
- if (e != null)
- return e;
-
- // Error has already been reported.
- if (errors < Report.Errors)
- return null;
+ if (e == null && errors == Report.Errors)
+ // No errors were reported by MemberLookup, but there was an error.
+ MemberLookupFailed (ec, qualifier_type, queried_type, name,
+ null, loc);
- MemberLookupFailed (ec, qualifier_type, queried_type, name,
- null, loc);
- return null;
+ return e;
}
public static void MemberLookupFailed (EmitContext ec, Type qualifier_type,
Type queried_type, string name,
string class_name, Location loc)
{
+ if (almostMatchedMembers.Count != 0) {
+ if (qualifier_type == null) {
+ foreach (MemberInfo m in almostMatchedMembers)
+ Report.Error (38, loc,
+ "Cannot access non-static member `{0}' via nested type `{1}'",
+ TypeManager.GetFullNameSignature (m),
+ TypeManager.CSharpName (ec.ContainerType));
+ return;
+ }
+
+
+ if (qualifier_type != ec.ContainerType) {
+ // Although a derived class can access protected members of
+ // its base class it cannot do so through an instance of the
+ // base class (CS1540). If the qualifier_type is a parent of the
+ // ec.ContainerType and the lookup succeeds with the latter one,
+ // then we are in this situation.
+ foreach (MemberInfo m in almostMatchedMembers)
+ 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)",
+ TypeManager.GetFullNameSignature (m),
+ TypeManager.CSharpName (qualifier_type),
+ TypeManager.CSharpName (ec.ContainerType));
+ return;
+ }
+ almostMatchedMembers.Clear ();
+ }
+
MemberInfo[] mi = TypeManager.MemberLookup (queried_type, null, queried_type,
AllMemberTypes, AllBindingFlags |
- BindingFlags.NonPublic, name);
+ BindingFlags.NonPublic, name, null);
if (mi == null) {
if (class_name != null)
if (TypeManager.MemberLookup (queried_type, null, queried_type,
AllMemberTypes, AllBindingFlags |
- BindingFlags.NonPublic, name) == null) {
+ BindingFlags.NonPublic, name, null) == null) {
if ((mi.Length == 1) && (mi [0] is Type)) {
Type t = (Type) mi [0];
}
}
- if ((qualifier_type != null) && (qualifier_type != ec.ContainerType) &&
- ec.ContainerType.IsSubclassOf (qualifier_type)) {
- // Although a derived class can access protected members of
- // its base class it cannot do so through an instance of the
- // base class (CS1540). If the qualifier_type is a parent of the
- // ec.ContainerType and the lookup succeeds with the latter one,
- // then we are in this situation.
-
- mi = TypeManager.MemberLookup (
- ec.ContainerType, ec.ContainerType, ec.ContainerType,
- AllMemberTypes, AllBindingFlags, name);
- if (mi != null) {
- Report.Error (
- 1540, loc, "Cannot access protected member `" +
- TypeManager.CSharpName (qualifier_type) + "." +
- name + "' " + "via a qualifier of type `" +
- TypeManager.CSharpName (qualifier_type) + "'; the " +
- "qualifier must be of type `" +
- TypeManager.CSharpName (ec.ContainerType) + "' " +
- "(or derived from it)");
- return;
- }
- }
if (qualifier_type != null)
- Report.Error (
- 122, loc, "`" + TypeManager.CSharpName (qualifier_type) + "." +
- name + "' is inaccessible due to its protection level");
+ Report.Error_T (122, loc, TypeManager.CSharpName (qualifier_type) + "." + name);
else if (name == ".ctor") {
Report.Error (143, loc, String.Format ("The type {0} has no constructors defined",
TypeManager.CSharpName (queried_type)));
} else {
- Report.Error (
- 122, loc, "`" + name + "' is inaccessible due to its " +
- "protection level");
+ Report.Error_T (122, loc, name);
}
}
//
// Default implementation of IAssignMethod.CacheTemporaries
//
- public void CacheTemporaries (EmitContext ec)
+ public virtual void CacheTemporaries (EmitContext ec)
{
}
public override Expression DoResolve (EmitContext ec)
{
- return SimpleNameResolve (ec, null, false);
+ return SimpleNameResolve (ec, null, false, false);
}
public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
{
- return SimpleNameResolve (ec, right_side, false);
+ return SimpleNameResolve (ec, right_side, false, false);
}
- public Expression DoResolveAllowStatic (EmitContext ec)
+ public Expression DoResolveAllowStatic (EmitContext ec, bool intermediate)
{
- return SimpleNameResolve (ec, null, true);
+ return SimpleNameResolve (ec, null, true, intermediate);
}
public override Expression ResolveAsTypeStep (EmitContext ec)
return this;
}
+ Expression SimpleNameResolve (EmitContext ec, Expression right_side,
+ bool allow_static, bool intermediate)
+ {
+ Expression e = DoSimpleNameResolve (ec, right_side, allow_static, intermediate);
+ if (e == null)
+ return null;
+
+ Block current_block = ec.CurrentBlock;
+ if (current_block != null){
+ LocalInfo vi = current_block.GetLocalInfo (Name);
+ if (is_base &&
+ current_block.IsVariableNameUsedInChildBlock(Name)) {
+ Report.Error (135, Location,
+ "'{0}' has a different meaning in a " +
+ "child block", Name);
+ return null;
+ }
+ }
+
+ if (e.Type != null && e.Type.IsPointer && !ec.InUnsafe) {
+ UnsafeError (loc);
+ return null;
+ }
+
+ return e;
+ }
+
/// <remarks>
/// 7.5.2: Simple Names.
///
/// Type is both an instance variable and a Type; Type.GetType
/// is the static method not an instance method of type.
/// </remarks>
- Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool allow_static)
+ Expression DoSimpleNameResolve (EmitContext ec, Expression right_side, bool allow_static, bool intermediate)
{
Expression e = null;
//
Block current_block = ec.CurrentBlock;
if (current_block != null){
- if (is_base && current_block.IsVariableNameUsedInChildBlock(Name)) {
- Report.Error (135, Location, "'" + Name + "' has a different meaning in a child block");
- return null;
- }
-
LocalInfo vi = current_block.GetLocalInfo (Name);
if (vi != null){
Expression var;
// This fails if ResolveMemberAccess() was unable to decide whether
// it's a field or a type of the same name.
+
if (!me.IsStatic && (me.InstanceExpression == null))
return e;
if (!me.IsStatic &&
TypeManager.IsNestedChildOf (me.InstanceExpression.Type, me.DeclaringType) &&
- !me.InstanceExpression.Type.IsSubclassOf (me.DeclaringType)) {
+ !me.InstanceExpression.Type.IsSubclassOf (me.DeclaringType) &&
+ (!intermediate || !MemberAccess.IdenticalNameAndTypeName (ec, this, e, loc))) {
Error (38, "Cannot access nonstatic member `" + me.Name + "' of " +
"outer type `" + me.DeclaringType + "' via nested type `" +
me.InstanceExpression.Type + "'");
return null;
}
- if (right_side != null)
- e = e.DoResolveLValue (ec, right_side);
- else
- e = e.DoResolve (ec);
-
- return e;
+ return (right_side != null)
+ ? e.DoResolveLValue (ec, right_side)
+ : e.DoResolve (ec);
}
if (ec.IsStatic || ec.IsFieldInitializer){
Expression instance_expression = null;
bool is_explicit_impl = false;
bool has_type_arguments = false;
+ bool identical_type_name = false;
public MethodGroupExpr (MemberInfo [] mi, Location l)
{
}
}
+ public bool IdenticalTypeName {
+ get {
+ return identical_type_name;
+ }
+
+ set {
+ identical_type_name = value;
+ }
+ }
+
public string Name {
get {
return TypeManager.CSharpSignature (
Expression instance_expr;
VariableInfo variable_info;
+ LocalTemporary temporary;
+ IMemoryLocation instance_ml;
+ bool have_temporary;
+
public FieldExpr (FieldInfo fi, Location l)
{
FieldInfo = fi;
return null;
}
+ ObsoleteAttribute oa;
+ FieldBase f = TypeManager.GetField (FieldInfo);
+ if (f != null) {
+ oa = f.GetObsoleteAttribute (ec.DeclSpace);
+ if (oa != null)
+ AttributeTester.Report_ObsoleteMessage (oa, f.GetSignatureForError (), loc);
+ // To be sure that type is external because we do not register generated fields
+ } else if (!(FieldInfo.DeclaringType is TypeBuilder)) {
+ oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo);
+ if (oa != null)
+ AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc);
+ }
+
// If the instance expression is a local variable or parameter.
IVariable var = instance_expr as IVariable;
if ((var == null) || (var.VariableInfo == null))
return true;
}
+ public override void CacheTemporaries (EmitContext ec)
+ {
+ if (!FieldInfo.IsStatic && (temporary == null))
+ temporary = new LocalTemporary (ec, instance_expr.Type);
+ }
+
+ void EmitInstance (EmitContext ec)
+ {
+ if (instance_expr.Type.IsValueType)
+ CacheTemporaries (ec);
+
+ if ((temporary == null) || have_temporary)
+ return;
+
+ if (instance_expr.Type.IsValueType) {
+ instance_ml = instance_expr as IMemoryLocation;
+ if (instance_ml == null) {
+ instance_expr.Emit (ec);
+ temporary.Store (ec);
+ instance_ml = temporary;
+ }
+ } else {
+ instance_expr.Emit (ec);
+ temporary.Store (ec);
+ }
+
+ have_temporary = true;
+ }
+
override public void Emit (EmitContext ec)
{
ILGenerator ig = ec.ig;
return;
}
- if (instance_expr.Type.IsValueType){
- IMemoryLocation ml;
- LocalTemporary tempo = null;
-
- if (!(instance_expr is IMemoryLocation)){
- tempo = new LocalTemporary (ec, instance_expr.Type);
-
- InstanceExpression.Emit (ec);
- tempo.Store (ec);
- ml = tempo;
- } else
- ml = (IMemoryLocation) instance_expr;
-
- ml.AddressOf (ec, AddressOp.Load);
- } else {
+ EmitInstance (ec);
+ if (instance_ml != null)
+ instance_ml.AddressOf (ec, AddressOp.Load);
+ else if (temporary != null)
+ temporary.Emit (ec);
+ else
instance_expr.Emit (ec);
- }
+
if (is_volatile)
ig.Emit (OpCodes.Volatile);
}
if (!is_static){
- Expression instance = instance_expr;
-
- if (instance.Type.IsValueType){
- IMemoryLocation ml = (IMemoryLocation) instance;
-
- ml.AddressOf (ec, AddressOp.Store);
- } else {
- instance.Emit (ec);
- }
+ EmitInstance (ec);
+ if (instance_ml != null)
+ instance_ml.AddressOf (ec, AddressOp.Store);
+ else if (temporary != null)
+ temporary.Emit (ec);
+ else
+ instance_expr.Emit (ec);
}
source.Emit (ec);
// only load the pointer, and not perform an Ldobj immediately after
// the value has been loaded into the stack.
//
- if (instance_expr is This)
+ EmitInstance (ec);
+ if (instance_ml != null)
+ instance_ml.AddressOf (ec, AddressOp.LoadStore);
+ else if (temporary != null)
+ temporary.Emit (ec);
+ else if (instance_expr is This)
((This)instance_expr).AddressOf (ec, AddressOp.LoadStore);
- else if (instance_expr.Type.IsValueType && instance_expr is IMemoryLocation){
- IMemoryLocation ml = (IMemoryLocation) instance_expr;
-
- ml.AddressOf (ec, AddressOp.LoadStore);
- } else {
+ else
instance_expr.Emit (ec);
-
- if (instance_expr.Type.IsValueType) {
- LocalBuilder local = ig.DeclareLocal (instance_expr.Type);
- ig.Emit(OpCodes.Stloc, local);
- ig.Emit(OpCodes.Ldloca, local);
- ig.Emit(OpCodes.Ldfld, FieldInfo);
- LocalBuilder local2 = ig.DeclareLocal(type);
- ig.Emit(OpCodes.Stloc, local2);
- ig.Emit(OpCodes.Ldloca, local2);
- return;
- }
- }
ig.Emit (OpCodes.Ldflda, FieldInfo);
}
}
bool must_do_cs1540_check;
Expression instance_expr;
+ LocalTemporary temporary;
+ bool have_temporary;
public PropertyExpr (EmitContext ec, PropertyInfo pi, Location l)
{
for (; current != null; current = current.BaseType) {
MemberInfo[] group = TypeManager.MemberLookup (
invocation_type, invocation_type, current,
- MemberTypes.Property, flags, PropertyInfo.Name);
+ MemberTypes.Property, flags, PropertyInfo.Name, null);
if (group == null)
continue;
is_static = true;
if (setter == null && getter == null){
- Error (122, "`" + PropertyInfo.Name + "' " +
- "is inaccessible because of its protection level");
-
+ Report.Error_T (122, loc, PropertyInfo.Name);
}
}
return this;
}
+ public override void CacheTemporaries (EmitContext ec)
+ {
+ if (!is_static)
+ temporary = new LocalTemporary (ec, instance_expr.Type);
+ }
+
+ Expression EmitInstance (EmitContext ec)
+ {
+ if (temporary != null){
+ if (!have_temporary){
+ instance_expr.Emit (ec);
+ temporary.Store (ec);
+ have_temporary = true;
+ }
+ return temporary;
+ } else
+ return instance_expr;
+ }
+
override public void Emit (EmitContext ec)
{
+ Expression expr = EmitInstance (ec);
+
//
// Special case: length of single dimension array property is turned into ldlen
//
// support invoking GetArrayRank, so test for that case first
//
if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)){
- instance_expr.Emit (ec);
+ expr.Emit (ec);
ec.ig.Emit (OpCodes.Ldlen);
ec.ig.Emit (OpCodes.Conv_I4);
return;
}
}
- Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, getter, null, loc);
+ Invocation.EmitCall (ec, IsBase, IsStatic, expr, getter, null, loc);
}
//
public void EmitAssign (EmitContext ec, Expression source)
{
+ Expression expr = EmitInstance (ec);
+
Argument arg = new Argument (source, Argument.AType.Expression);
ArrayList args = new ArrayList ();
args.Add (arg);
- Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, setter, args, loc);
+ Invocation.EmitCall (ec, IsBase, IsStatic, expr, setter, args, loc);
}
override public void EmitStatement (EmitContext ec)
/// </summary>
public class EventExpr : Expression, IMemberExpr {
public readonly EventInfo EventInfo;
- public Expression instance_expr;
+ Expression instance_expr;
bool is_static;
MethodInfo add_accessor, remove_accessor;