public override ModelfieldContract VisitModelfieldContract(ModelfieldContract mfC) { if (mfC == null) return null; SpecSharpCompilerOptions options = this.currentOptions as SpecSharpCompilerOptions; if (options != null && options.CheckContractAdmissibility) { AdmissibilityChecker checker = new AdmissibilityChecker(this); this.TransferStateTo(checker); checker.CheckModelfieldAdmissibility(mfC); } return base.VisitModelfieldContract(mfC); }
public override MethodContract VisitMethodContract (MethodContract contract) { if (contract == null) return null; ExpressionList modifies = contract.Modifies; if (modifies != null) { for (int i = 0, n = modifies.Count; i < n; i++) { #region modifies g, E.x, E[E0, E1, ... ] UnaryExpression ue = modifies[i] as UnaryExpression; if (ue != null) { Expression operand = ue.Operand; if (operand == null) continue; // something else is wrong: let other parts of the compiler warn about it MemberBinding mb = operand as MemberBinding; if (mb != null && mb.BoundMember is Field) { Field field = mb.BoundMember as Field; #region modifies g if (field != null && field.IsStatic) { if (mb.TargetObject != null) { this.HandleError(modifies[i], Error.InvalidModifiesClause, ": invalid static field reference"); modifies[i] = null; continue; } continue; // OK } #endregion #region modifies E.x // last conjunct is because at this stage, parameters look like "<implicit this>.p" if (field != null && !field.IsStatic && IsReferenceTypeButNotArray(mb.TargetObject.Type) && (!(field is ParameterField))) continue; this.HandleError(modifies[i], Error.InvalidModifiesClause, ": 'E.x' is allowed only when E has a reference type, not '" + this.GetTypeName(mb.TargetObject.Type) + "'"); modifies[i] = null; continue; #endregion } #region modifies E[E0, E1, ... ] Indexer ie = ue.Operand as Indexer; if (ie != null) continue; // other checks will make sure that E is an array with the right rank and the indices are the right type #endregion #region Exhausted all possibilities, but don't issue an error. // Assume (!!?!) that some other check will complain, e.g., "modifies o.f" where the type of o doesn't have a field f //this.HandleError(modifies[i], Error.InvalidModifiesClause, ""); //modifies[i] = null; continue; #endregion } #endregion #region modifies E*, E.**, E.0, E[*] ModifiesClause mc = modifies[i] as ModifiesClause; if (mc == null || mc.Operands == null || mc.Operands.Count != 1) { // Assume (!!?!) that some other check will complain, e.g., "modifies o.f" where the type of o doesn't have a field f //this.HandleError(mc.Operands[0], Error.InvalidModifiesClause, ""); //modifies[i] = null; continue; } TypeNode operandType = mc.Operands[0].Type; TypeNode unwrapped = this.typeSystem.Unwrap(operandType); #region modifies E.* if (mc is ModifiesObjectClause && !IsReferenceTypeButNotArray(operandType)) { this.HandleError(mc.Operands[0], Error.InvalidModifiesClause, ": 'E.*' is allowed only when E has a reference type, not '" + this.GetTypeName(operandType) + "'"); modifies[i] = null; continue; } #endregion #region modifies E.** if (mc is ModifiesPeersClause && unwrapped.IsValueType) { this.HandleError(mc.Operands[0], Error.InvalidModifiesClause, ": 'E.**' is allowed only when E has a reference type, not '" + this.GetTypeName(operandType) + "'"); modifies[i] = null; continue; } #endregion #region modifies E.0 if (mc is ModifiesNothingClause && unwrapped is Reference || unwrapped.IsValueType) { // a Reference should be created only when the type of the thing is *not* a reference type this.HandleError(mc.Operands[0], Error.InvalidModifiesClause, ": 'E.0' is allowed only when E has a reference type, not '" + this.GetTypeName(operandType) + "'"); modifies[i] = null; continue; } #endregion #region modifies E[*] if (mc is ModifiesArrayClause && (!(unwrapped is ArrayType))) { this.HandleError(mc.Operands[0], Error.InvalidModifiesClause, ": E[*] is allowed only when E has an array type, not " + this.GetTypeName(operandType)); modifies[i] = null; continue; } #endregion #endregion } } SpecSharpCompilerOptions options = this.currentOptions as SpecSharpCompilerOptions; if (options != null && options.CheckContractAdmissibility) { AdmissibilityChecker checker = new AdmissibilityChecker(this); this.TransferStateTo(checker); Method method = contract.DeclaringMethod; if (method == contract.OriginalDeclaringMethod) { bool isPure = method.IsPure; if (method.IsPure || method.IsConfined || method.IsStateIndependent) { foreach (Requires r in contract.Requires) checker.CheckMethodSpecAdmissibility(r.Condition, method, isPure, false); foreach (Ensures e in contract.Ensures) checker.CheckMethodSpecAdmissibility(e.PostCondition, method, isPure, false); } } } return base.VisitMethodContract(contract); }
public override Invariant VisitInvariant(Invariant inv) { if (inv == null) return null; SpecSharpCompilerOptions options = this.currentOptions as SpecSharpCompilerOptions; if (options != null && options.CheckContractAdmissibility) { AdmissibilityChecker checker = new AdmissibilityChecker(this); this.TransferStateTo(checker); checker.CheckInvariantAdmissibility(inv); } return base.VisitInvariant(inv); }