public override Expression VisitMethodCall(MethodCall call) { if (call == null) return null; MemberBinding mb = call.Callee as MemberBinding; Method m = mb == null ? null : mb.BoundMember as Method; if (m != null && !this.typeSystem.insideUnsafeCode) { bool badMethod = m.ReturnType is Pointer; for (int i = 0, n = m.Parameters == null ? 0 : m.Parameters.Count; i < n; i++) { Parameter p = m.Parameters[i]; if (p == null) continue; if (p.Type is Pointer) { badMethod = true; break; } } if (badMethod && call.SourceContext.Document != null) { this.HandleError(call, Error.UnsafeNeeded); return null; } } #region Pure methods that have an out parameter cannot be used in a contract // This is checked here and not where ref parameters are checked (VisitMethod) // because we want to allow pure methods to have out parameters for use in purity // analysis. It is just that Boogie doesn't generate the right axioms, etc. for // pure methods that have out parameters. So for now, just don't allow them in // contracts. if ((insideMethodContract || insideInvariant || insideAssertOrAssume) && m != null && !m.IsPropertyGetter && (m.IsPure || m.IsConfined || m.IsStateIndependent)) { // don't check property getters: they already will have an error if they have out parameters. for (int i = 0, n = m.Parameters == null ? 0 : m.Parameters.Count; i < n; i++) { Parameter p = m.Parameters[i]; if (p.IsOut) { this.HandleError(p, Error.PureMethodWithOutParamUsedInContract); } } } #endregion // if any two arguments Might Return Newly Allocated Object then method must be marked NoReferenceComparison if ((insideMethodContract || insideInvariant || insideAssertOrAssume) && m != null && mb != null) { int MRNAOargs = 0; MightReturnNewlyAllocatedObjectVisitor visitor = new MightReturnNewlyAllocatedObjectVisitor(this); this.TransferStateTo(visitor); visitor.CurrentMethod = this.currentMethod; // receiver visitor.Visit(mb); if (visitor.IsMRNAO) MRNAOargs++; else // parameters for (int i = 0, n = call.Operands == null ? 0 : call.Operands.Count; i < n; i++) { Expression exp = call.Operands[i]; visitor.IsMRNAO = false; visitor.Visit(exp); if (visitor.IsMRNAO) { MRNAOargs++; } } if (MRNAOargs > 1 && m.GetAttribute(SystemTypes.NoReferenceComparisonAttribute) == null) { this.HandleError(call, Error.MethodShouldBeMarkedNoReferenceComparison, m.Name.ToString()); return null; } } return base.VisitMethodCall(call); }