{
var ctors = MemberCache.FindMembers (type, Constructor.ConstructorName, true);
if (ctors == null) {
- rc.Report.SymbolRelatedToPreviousError (type);
- if (type.IsStruct) {
+ switch (type.Kind) {
+ case MemberKind.Struct:
+ rc.Report.SymbolRelatedToPreviousError (type);
// Report meaningful error for struct as they always have default ctor in C# context
OverloadResolver.Error_ConstructorMismatch (rc, type, args == null ? 0 : args.Count, loc);
- } else {
+ break;
+ case MemberKind.MissingType:
+ case MemberKind.InternalCompilerType:
+ break;
+ default:
+ rc.Report.SymbolRelatedToPreviousError (type);
rc.Report.Error (143, loc, "The class `{0}' has no constructors defined",
type.GetSignatureForError ());
+ break;
}
return null;
ec.Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation");
}
+ public virtual void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ }
+
/// <summary>
/// Returns an expression that can be used to invoke operator true
/// on the expression if it exists.
/// </summary>
public abstract class ExpressionStatement : Expression
{
+ public virtual void MarkReachable (Reachability rc)
+ {
+ }
+
public ExpressionStatement ResolveStatement (BlockContext ec)
{
Expression e = Resolve (ec);
return null;
ExpressionStatement es = e as ExpressionStatement;
- if (es == null)
+ if (es == null || e is AnonymousMethodBody)
Error_InvalidExpressionStatement (ec);
//
child.Emit (ec);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ child.FlowAnalysis (fc);
+ }
+
public override SLE.Expression MakeExpression (BuilderContext ctx)
{
#if STATIC
{
stm.EmitStatement (ec);
}
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ stm.FlowAnalysis (fc);
+ }
}
readonly Expression expr, orig_expr;
expr.EmitBranchable (ec, target, on_true);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ expr.FlowAnalysis (fc);
+ }
+
public override SLE.Expression MakeExpression (BuilderContext ctx)
{
return orig_expr.MakeExpression (ctx);
{
throw new InternalErrorException ("Missing Resolve call");
}
+ }
+
+ public class UnreachableExpression : Expression
+ {
+ public UnreachableExpression (Expression expr)
+ {
+ this.loc = expr.Location;
+ }
+ public override Expression CreateExpressionTree (ResolveContext ec)
+ {
+ // TODO: is it ok
+ throw new NotImplementedException ();
+ }
+
+ protected override Expression DoResolve (ResolveContext rc)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ fc.Report.Warning (429, 4, loc, "Unreachable expression code detected");
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ }
+
+ public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
+ {
+ }
}
//
protected override Expression DoResolve (ResolveContext rc)
{
- var e = SimpleNameResolve (rc, null);
-
- var fe = e as FieldExpr;
- if (fe != null) {
- fe.VerifyAssignedStructField (rc, null);
- }
-
- return e;
+ return SimpleNameResolve (rc, null);
}
public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
member.GetSignatureForError (), qualifier.GetSignatureForError (), rc.CurrentType.GetSignatureForError ());
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (InstanceExpression != null)
+ InstanceExpression.FlowAnalysis (fc);
+ }
+
public bool ResolveInstanceExpression (ResolveContext rc, Expression rhs)
{
if (!ResolveInstanceExpressionCore (rc, rhs))
DeclaringType.GetSignatureForError (), rc.CurrentType.GetSignatureForError ());
}
- InstanceExpression = new This (loc);
- if (this is FieldExpr && rc.CurrentBlock.ParametersBlock.TopBlock.ThisVariable != null) {
- using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) {
- InstanceExpression = InstanceExpression.Resolve (rc);
- }
- } else {
- InstanceExpression = InstanceExpression.Resolve (rc);
- }
-
+ InstanceExpression = new This (loc).Resolve (rc);
return false;
}
if (me != null) {
me.ResolveInstanceExpressionCore (rc, rhs);
- // Using this check to detect probing instance expression resolve
- if (!rc.OmitStructFlowAnalysis) {
- var fe = me as FieldExpr;
- 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",
- me.GetSignatureForError ());
- }
+ var fe = me as FieldExpr;
+ 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",
+ me.GetSignatureForError ());
}
return true;
}
- //
- // Run member-access postponed check once we know that
- // the expression is not field expression which is the only
- // expression which can use uninitialized this
- //
- if (InstanceExpression is This && !(this is FieldExpr) && rc.CurrentBlock.ParametersBlock.TopBlock.ThisVariable != null) {
- ((This)InstanceExpression).CheckStructThisDefiniteAssignment (rc);
- }
-
//
// Additional checks for l-value member access
//
/// </summary>
public class MethodGroupExpr : MemberExpr, OverloadResolver.IBaseMembersProvider
{
+ static readonly MemberSpec[] Excluded = new MemberSpec[0];
+
protected IList<MemberSpec> Methods;
MethodSpec best_candidate;
TypeSpec best_candidate_return;
}
}
+ public bool IsConditionallyExcluded {
+ get {
+ return Methods == Excluded;
+ }
+ }
+
public override bool IsInstance {
get {
if (best_candidate != null)
return null;
}
- if (best_candidate.IsConditionallyExcluded (ec))
+ if (IsConditionallyExcluded)
ec.Report.Error (765, loc,
"Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree");
ErrorIsInaccesible (ec, best_candidate.GetSignatureForError (), loc);
}
+ // Speed up the check by not doing it on disallowed targets
+ if (best_candidate_return.Kind == MemberKind.Void && best_candidate.IsConditionallyExcluded (ec))
+ Methods = Excluded;
+
return this;
}
// "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 || rhs == EmptyExpression.LValueMemberOutAccess;
+ 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);
- }
+ InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
} else {
- using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
- InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue);
- }
+ InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue);
}
if (InstanceExpression == null)
var fb = spec as FixedFieldSpec;
IVariableReference var = InstanceExpression as IVariableReference;
- if (lvalue_instance && var != null && var.VariableInfo != null) {
- var.VariableInfo.SetStructFieldAssigned (ec, Name);
- }
-
if (fb != null) {
IFixedExpression fe = InstanceExpression as IFixedExpression;
if (!ec.HasSet (ResolveContext.Options.FixedInitializerScope) && (fe == null || !fe.IsFixed)) {
//
if (var != null && var.VariableInfo != null && InstanceExpression.Type.IsStruct) {
variable_info = var.VariableInfo.GetStructFieldInfo (Name);
- if (rhs != null && variable_info != null)
- variable_info.SetStructFieldAssigned (ec, Name);
}
eclass = ExprClass.Variable;
return this;
}
- public void VerifyAssignedStructField (ResolveContext rc, Expression rhs)
+ public void SetFieldAssigned (FlowAnalysisContext fc)
+ {
+ if (!IsInstance)
+ return;
+
+ bool lvalue_instance = spec.DeclaringType.IsStruct;
+ if (lvalue_instance) {
+ var var = InstanceExpression as IVariableReference;
+ if (var != null && var.VariableInfo != null) {
+ fc.SetStructFieldAssigned (var.VariableInfo, Name);
+ }
+ }
+
+ var fe = InstanceExpression as FieldExpr;
+ if (fe != null || lvalue_instance) {
+ if (fe == null)
+ return;
+
+ /*
+ while (fe.InstanceExpression is FieldExpr) {
+ fe = (FieldExpr) fe.InstanceExpression;
+ if (!fe.Spec.DeclaringType.IsStruct)
+ continue;
+
+ if (fe.VariableInfo != null && fc.IsStructFieldDefinitelyAssigned (fe.VariableInfo, fe.Name)) {
+ fc.Report.Warning (1060, 1, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
+ }
+ }
+
+ fe.InstanceExpression.FlowAnalysis (fc);
+ */
+ } else {
+ InstanceExpression.FlowAnalysis (fc);
+ }
+ }
+
+
+ public void VerifyAssignedStructField (FlowAnalysisContext fc)
{
var fe = this;
if (var != null) {
var vi = var.VariableInfo;
- if (vi != null && !vi.IsStructFieldAssigned (rc, fe.Name) && (rhs == null || !fe.type.IsStruct)) {
- if (rhs != null) {
- rc.Report.Warning (1060, 1, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
- } else {
- rc.Report.Error (170, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
- }
-
- return;
+ if (vi != null && !fc.IsStructFieldDefinitelyAssigned (vi, fe.Name) && !fe.type.IsStruct) {
+ fc.Report.Warning (1060, 1, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
}
}
rc.Report.Error (1649, loc, "Members of readonly field `{0}' cannot be passed ref or out (except in a constructor)",
GetSignatureForError ());
}
-
return null;
}
return this;
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ var var = InstanceExpression as IVariableReference;
+ if (var != null) {
+ var vi = var.VariableInfo;
+ if (vi != null && !fc.IsStructFieldDefinitelyAssigned (vi, Name)) {
+ fc.Report.Error (170, loc, "Use of possibly unassigned field `{0}'", Name);
+ return;
+ }
+
+ if (TypeSpec.IsValueType (InstanceExpression.Type))
+ return;
+ }
+
+ base.FlowAnalysis (fc);
+ }
+
public override int GetHashCode ()
{
return spec.GetHashCode ();
DoEmit (ec);
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ return false;
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement target)
{
// Nothing
public override VariableInfo VariableInfo {
get { return null; }
}
-
- public override void VerifyDefiniteAssignment (ResolveContext rc)
- {
- }
}
///