public static bool GetAttributeArgumentExpression (Expression e, Location loc, Type arg_type, out object result)
{
if (e is EnumConstant) {
- result = e;
+ if (RootContext.StdLib)
+ result = ((EnumConstant)e).GetValueAsEnumType ();
+ else
+ result = ((EnumConstant)e).GetValue ();
+
return true;
}
}
pos_values = new object [pos_arg_count];
- object[] real_pos_values = new object [pos_arg_count];
//
// First process positional arguments
if (!GetAttributeArgumentExpression (e, Location, a.Type, out val))
return null;
- if (val is EnumConstant) {
- EnumConstant econst = (EnumConstant) e;
-
- pos_values [i] = val = econst.GetValue ();
- real_pos_values [i] = econst.GetValueAsEnumType ();
- } else {
- real_pos_values [i] = pos_values [i] = val;
- }
+ pos_values [i] = val;
if (DoCompares){
- if (usage_attr)
- usage_attribute = new AttributeUsageAttribute ((AttributeTargets) val);
- else if (MethodImplAttr)
+ if (usage_attr) {
+ usage_attribute = new AttributeUsageAttribute ((AttributeTargets)val);
+ } else if (MethodImplAttr) {
this.ImplOptions = (MethodImplOptions) val;
- else if (GuidAttr){
+ } else if (GuidAttr){
//
// we will later check the validity of the type
//
continue;
if (j == group_in_params_array){
- object v = real_pos_values [j];
+ object v = pos_values [j];
int count = pos_arg_count - j;
object [] array = new object [count];
- real_pos_values [j] = array;
+ pos_values [j] = array;
array [0] = v;
} else {
- object [] array = (object []) real_pos_values [group_in_params_array];
+ object [] array = (object []) pos_values [group_in_params_array];
- array [j - group_in_params_array] = real_pos_values [j];
+ array [j - group_in_params_array] = pos_values [j];
}
}
object [] new_pos_values = new object [argc];
for (int p = 0; p < argc; p++)
- new_pos_values [p] = real_pos_values [p];
- real_pos_values = new_pos_values;
+ new_pos_values [p] = pos_values [p];
+ pos_values = new_pos_values;
}
try {
prop_infos.CopyTo (prop_info_arr, 0);
cb = new CustomAttributeBuilder (
- (ConstructorInfo) constructor, real_pos_values,
+ (ConstructorInfo) constructor, pos_values,
prop_info_arr, prop_values_arr,
field_info_arr, field_values_arr);
}
else
cb = new CustomAttributeBuilder (
- (ConstructorInfo) constructor, real_pos_values);
+ (ConstructorInfo) constructor, pos_values);
} catch (NullReferenceException) {
//
// Don't know what to do here
int errors = Report.Errors;
- TypeExpr d = e.ResolveAsTypeTerminal (type_resolve_ec);
+ TypeExpr d = e.ResolveAsTypeTerminal (type_resolve_ec, silent);
if ((d != null) && (d.eclass == ExprClass.Type))
return d;
if (e is SimpleName){
SimpleName s = new SimpleName (((SimpleName) e).Name, loc);
- d = s.ResolveAsTypeTerminal (type_resolve_ec);
+ d = s.ResolveAsTypeTerminal (type_resolve_ec, silent);
if ((d == null) || (d.Type == null)) {
Report.Error (246, loc, "Cannot find type `{0}'", e);
case TypeAttributes.NotPublic:
- // In same cases is null.
- if (TypeBuilder == null)
- return true;
+ if (TypeBuilder == null)
+ // FIXME: TypeBuilder will be null when invoked by Class.GetNormalBases().
+ // However, this is invoked again later -- so safe to return true.
+ // May also be null when resolving top-level attributes.
+ return true;
- //
- // This test should probably use the declaringtype.
- //
+ //
+ // This test should probably use the declaringtype.
+ //
return check_type.Assembly == TypeBuilder.Assembly;
case TypeAttributes.NestedPublic:
return true;
case TypeAttributes.NestedPrivate:
- string check_type_name = check_type.FullName;
- string type_name = tb.FullName;
-
- int cio = check_type_name.LastIndexOf ('+');
- string container = check_type_name.Substring (0, cio);
-
- //
- // Check if the check_type is a nested class of the current type
- //
- if (check_type_name.StartsWith (type_name + "+")){
- return true;
- }
-
- if (type_name.StartsWith (container)){
- return true;
- }
-
- return false;
+ return NestedAccessible (check_type);
case TypeAttributes.NestedFamily:
//
// Only accessible to methods in current type or any subtypes
//
- return FamilyAccessible (tb, check_type);
+ return FamilyAccessible (check_type);
case TypeAttributes.NestedFamANDAssem:
return (check_type.Assembly == tb.Assembly) &&
- FamilyAccessible (tb, check_type);
+ FamilyAccessible (check_type);
case TypeAttributes.NestedFamORAssem:
return (check_type.Assembly == tb.Assembly) ||
- FamilyAccessible (tb, check_type);
+ FamilyAccessible (check_type);
case TypeAttributes.NestedAssembly:
return check_type.Assembly == tb.Assembly;
}
- protected bool FamilyAccessible (TypeBuilder tb, Type check_type)
+ protected bool NestedAccessible (Type check_type)
{
- Type declaring = check_type.DeclaringType;
- if (tb.IsSubclassOf (declaring))
- return true;
-
string check_type_name = check_type.FullName;
+ // At this point, we already know check_type is a nested class.
int cio = check_type_name.LastIndexOf ('+');
- string container = check_type_name.Substring (0, cio);
- //
- // Check if the check_type is a nested class of the current type
- //
- if (check_type_name.StartsWith (container + "+"))
+ // Ensure that the string 'container' has a '+' in it to avoid false matches
+ string container = check_type_name.Substring (0, cio + 1);
+
+ // Ensure that type_name ends with a '+' so that it can match 'container', if necessary
+ string type_name = TypeBuilder.FullName + "+";
+
+ // If the current class is nested inside the container of check_type,
+ // we can access check_type even if it is private or protected.
+ return type_name.StartsWith (container);
+ }
+
+ protected bool FamilyAccessible (Type check_type)
+ {
+ Type declaring = check_type.DeclaringType;
+ if (TypeBuilder == declaring ||
+ TypeBuilder.IsSubclassOf (declaring))
return true;
- return false;
+ return NestedAccessible (check_type);
}
// Access level of a type.
/// size.
/// </remarks>
public abstract class Probe : Expression {
- public readonly Expression ProbeType;
+ public Expression ProbeType;
protected Expression expr;
protected Type probe_type;
public override Expression DoResolve (EmitContext ec)
{
- probe_type = ec.DeclSpace.ResolveType (ProbeType, false, loc);
-
- if (probe_type == null)
+ ProbeType = ProbeType.ResolveAsTypeTerminal (ec, false);
+ if (ProbeType == null)
return null;
+ probe_type = ProbeType.Type;
CheckObsoleteAttribute (probe_type);
if (expr == null)
return null;
- type = ec.DeclSpace.ResolveType (target_type, false, Location);
-
- if (type == null)
+ TypeExpr target = target_type.ResolveAsTypeTerminal (ec, false);
+ if (target == null)
return null;
+ type = target.Type;
+
CheckObsoleteAttribute (type);
if (type.IsAbstract && type.IsSealed) {
Expression expr;
MethodBase method = null;
- bool is_base;
static Hashtable method_parameter_cache;
/// <summary>
/// Determines "better conversion" as specified in 7.4.2.3
///
- /// Returns : 1 if a->p is better
- /// 0 if a->q or neither is better
+ /// Returns : p if a->p is better,
+ /// q if a->q is better,
+ /// null if neither is better
/// </summary>
- static int BetterConversion (EmitContext ec, Argument a, Type p, Type q, Location loc)
+ static Type BetterConversion (EmitContext ec, Argument a, Type p, Type q, Location loc)
{
Type argument_type = TypeManager.TypeToCoreType (a.Type);
Expression argument_expr = a.Expr;
if (p == null || q == null)
throw new InternalErrorException ("BetterConversion Got a null conversion");
- //
- // This is a special case since csc behaves this way.
- //
- if (argument_expr is NullLiteral &&
- p == TypeManager.string_type &&
- q == TypeManager.object_type)
- return 1;
- else if (argument_expr is NullLiteral &&
- p == TypeManager.object_type &&
- q == TypeManager.string_type)
- return 0;
-
- //
- // csc behaves this way so we emulate it. Basically, if the argument
- // is null and one of the types to compare is 'object' and the other
- // is a reference type, we prefer the other.
- //
- // I can't find this anywhere in the spec but we can interpret this
- // to mean that null can be of any type you wish in such a context
- //
- if (argument_expr is NullLiteral &&
- !p.IsValueType &&
- q == TypeManager.object_type)
- return 1;
- else if (argument_expr is NullLiteral &&
- !q.IsValueType &&
- p == TypeManager.object_type)
- return 0;
-
-
if (p == q)
- return 0;
-
+ return null;
+
+ if (argument_expr is NullLiteral) {
+ //
+ // If the argument is null and one of the types to compare is 'object' and
+ // the other is a reference type, we prefer the other.
+ //
+ // This follows from the usual rules:
+ // * There is an implicit conversion from 'null' to type 'object'
+ // * There is an implicit conversion from 'null' to any reference type
+ // * There is an implicit conversion from any reference type to type 'object'
+ // * There is no implicit conversion from type 'object' to other reference types
+ // => Conversion of 'null' to a reference type is better than conversion to 'object'
+ //
+ // FIXME: This probably isn't necessary, since the type of a NullLiteral is 'System.Null'.
+ // I think it used to be 'object' and thus needed a special case to avoid the
+ // immediately following two checks.
+ //
+ if (!p.IsValueType && q == TypeManager.object_type)
+ return p;
+ if (!q.IsValueType && p == TypeManager.object_type)
+ return q;
+ }
+
if (argument_type == p)
- return 1;
+ return p;
if (argument_type == q)
- return 0;
+ return q;
Expression p_tmp = new EmptyExpression (p);
Expression q_tmp = new EmptyExpression (q);
-
- if (Convert.ImplicitConversionExists (ec, p_tmp, q) == true &&
- Convert.ImplicitConversionExists (ec, q_tmp, p) == false)
- return 1;
+
+ bool p_to_q = Convert.ImplicitConversionExists (ec, p_tmp, q);
+ bool q_to_p = Convert.ImplicitConversionExists (ec, q_tmp, p);
+
+ if (p_to_q && !q_to_p)
+ return p;
+
+ if (q_to_p && !p_to_q)
+ return q;
if (p == TypeManager.sbyte_type)
if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
q == TypeManager.uint32_type || q == TypeManager.uint64_type)
- return 1;
+ return p;
+ if (q == TypeManager.sbyte_type)
+ if (p == TypeManager.byte_type || p == TypeManager.ushort_type ||
+ p == TypeManager.uint32_type || p == TypeManager.uint64_type)
+ return q;
if (p == TypeManager.short_type)
if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
q == TypeManager.uint64_type)
- return 1;
+ return p;
+
+ if (q == TypeManager.short_type)
+ if (p == TypeManager.ushort_type || p == TypeManager.uint32_type ||
+ p == TypeManager.uint64_type)
+ return q;
if (p == TypeManager.int32_type)
if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
- return 1;
+ return p;
+
+ if (q == TypeManager.int32_type)
+ if (p == TypeManager.uint32_type || p == TypeManager.uint64_type)
+ return q;
if (p == TypeManager.int64_type)
if (q == TypeManager.uint64_type)
- return 1;
+ return p;
+ if (q == TypeManager.int64_type)
+ if (p == TypeManager.uint64_type)
+ return q;
- return 0;
+ return null;
}
/// <summary>
/// </summary>
/// <remarks>
/// Returns an integer indicating :
- /// 0 if candidate ain't better
- /// 1 if candidate is better than the current best match
+ /// false if candidate ain't better
+ /// true if candidate is better than the current best match
/// </remarks>
- static int BetterFunction (EmitContext ec, ArrayList args, int argument_count,
- MethodBase candidate, bool candidate_params,
- MethodBase best, bool best_params, Location loc)
+ static bool BetterFunction (EmitContext ec, ArrayList args, int argument_count,
+ MethodBase candidate, bool candidate_params,
+ MethodBase best, bool best_params, Location loc)
{
ParameterData candidate_pd = GetParameterData (candidate);
ParameterData best_pd = GetParameterData (best);
// }
//
// interface IFooBar : IFoo, IBar {}
- //
+ //
// We cant tell if IFoo.DoIt is better than IBar.DoIt
//
// However, we have to consider that
// Trim (); is better than Trim (params char[] chars);
//
if (cand_count == 0 && argument_count == 0)
- return best_params ? 1 : 0;
+ return !candidate_params && best_params;
if ((candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS) &&
(candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.ARGLIST))
if (cand_count != argument_count)
- return 0;
-
- int rating1 = 0, rating2 = 0;
-
+ return false;
+
+ bool better_at_least_one = false;
for (int j = 0; j < argument_count; ++j) {
- int x, y;
-
Argument a = (Argument) args [j];
- Type ct = TypeManager.TypeToCoreType (
- candidate_pd.ParameterType (j));
- Type bt = TypeManager.TypeToCoreType (
- best_pd.ParameterType (j));
+ Type ct = candidate_pd.ParameterType (j);
+ Type bt = best_pd.ParameterType (j);
if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
if (candidate_params)
if (best_params)
bt = TypeManager.GetElementType (bt);
- x = BetterConversion (ec, a, ct, bt, loc);
- y = BetterConversion (ec, a, bt, ct, loc);
+ Type better = BetterConversion (ec, a, ct, bt, loc);
- if (x < y)
- return 0;
+ // for each argument, the conversion to 'ct' should be no worse than
+ // the conversion to 'bt'.
+ if (better == bt)
+ return false;
- rating1 += x;
- rating2 += y;
+ // for at least one argument, the conversion to 'ct' should be better than
+ // the conversion to 'bt'.
+ if (better == ct)
+ better_at_least_one = true;
}
//
// force it to select the candidate
//
if (!candidate_params && best_params && cand_count == argument_count)
- return 1;
+ return true;
- if (rating1 > rating2)
- return 1;
- else
- return 0;
+ return better_at_least_one;
}
public static string FullMethodDesc (MethodBase mb)
if (BetterFunction (ec, Arguments, arg_count,
candidate, cand_params,
- method, method_params, loc) != 0) {
+ method, method_params, loc)) {
method = candidate;
method_params = cand_params;
}
continue;
bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
- if (BetterFunction (ec, Arguments, arg_count,
+ if (!BetterFunction (ec, Arguments, arg_count,
method, method_params,
candidate, cand_params,
- loc) != 1) {
+ loc)) {
Report.SymbolRelatedToPreviousError (candidate);
ambiguous = true;
}
// First, resolve the expression that is used to
// trigger the invocation
//
- if (expr is BaseAccess)
- is_base = true;
-
if (expr is ConstructedType)
expr = ((ConstructedType) expr).GetSimpleName (ec);
//
// Only base will allow this invocation to happen.
//
- if (is_base && method.IsAbstract){
+ if (mg.IsBase && method.IsAbstract){
Report.Error (205, loc, "Cannot call an abstract base member: " +
FullMethodDesc (method));
return null;
}
if (method.Name == "Finalize" && Arguments == null) {
- if (is_base)
+ if (mg.IsBase)
Report.Error (250, loc, "Do not directly call your base class Finalize method. It is called automatically from your destructor");
else
Report.Error (245, loc, "Destructors and object.Finalize cannot be called directly. Consider calling IDisposable.Dispose if available");
{
MethodGroupExpr mg = (MethodGroupExpr) this.expr;
- EmitCall (ec, is_base, method.IsStatic, mg.InstanceExpression, method, Arguments, loc);
+ EmitCall (ec, mg.IsBase, method.IsStatic, mg.InstanceExpression, method, Arguments, loc);
}
public override void EmitStatement (EmitContext ec)
//
// First try to resolve it as a cast.
//
- type = ec.DeclSpace.ResolveType (expr, true, loc);
- if (type != null) {
- Cast cast = new Cast (new TypeExpression (type, loc), argument, loc);
+ TypeExpr te = expr.ResolveAsTypeTerminal (ec, true);
+ if (te != null) {
+ Cast cast = new Cast (te, argument, loc);
return cast.Resolve (ec);
}
//
// First try to resolve it as a cast.
//
- type = ec.DeclSpace.ResolveType (expr, true, loc);
- if (type != null) {
+ TypeExpr te = expr.ResolveAsTypeTerminal (ec, true);
+ if (te != null) {
error201 ();
return null;
}
return this;
}
- type = ec.DeclSpace.ResolveType (RequestedType, false, loc);
-
- if (type == null)
+ RequestedType = RequestedType.ResolveAsTypeTerminal (ec, false);
+ if (RequestedType == null)
return null;
+ type = RequestedType.Type;
+
CheckObsoleteAttribute (type);
bool IsDelegate = TypeManager.IsDelegateType (type);
/// Implements the typeof operator
/// </summary>
public class TypeOf : Expression {
- public readonly Expression QueriedType;
+ public Expression QueriedType;
protected Type typearg;
public TypeOf (Expression queried_type, Location l)
public override Expression DoResolve (EmitContext ec)
{
- typearg = ec.DeclSpace.ResolveType (QueriedType, false, loc);
-
- if (typearg == null)
+ QueriedType = QueriedType.ResolveAsTypeTerminal (ec, false);
+ if (QueriedType == null)
return null;
+ typearg = QueriedType.Type;
+
if (typearg == TypeManager.void_type) {
Error (673, "System.Void cannot be used from C# - " +
"use typeof (void) to get the void type object");