public LispList <PathElement> VisibleAccessPathList(APC at, SymbolicValue value) { Domain domain; if (!this.parent.PreStateLookup(at, out domain)) { throw new ArgumentException("pc wasn't visited"); } AccessPathFilter <Method> filter = AccessPathFilter <Method> .FromPrecondition(MethodContext.CurrentMethod); return(domain.GetAccessPathList(value.Symbol, filter, false, false)); }
public LispList <PathElement> AccessPathList(APC at, SymbolicValue sv, bool allowLocal, bool preferLocal) { Domain domain; if (!this.parent.PreStateLookup(at, out domain)) { throw new ArgumentException("pc wasn't visited"); } AccessPathFilter <Method> filter = AccessPathFilter <Method> .IsVisibleFrom(MethodContext.CurrentMethod); return(domain.GetAccessPathList(sv.Symbol, filter, allowLocal, preferLocal)); }
private BoxedExpression ExpressionInPostStateHelper(BoxedExpression exp, bool replaceReturnValue, bool overrideAccessModifiers, bool allowReturnValue, ref Details details) { if (exp.IsConstant || exp.IsSizeOf /*|| exp.IsNull*/) { // Nothing to do return(exp); } if (exp.IsNull) { return(BoxedExpression.Const(null, this.metaDataDecoder.System_Object, this.metaDataDecoder)); } if (exp.IsVariable) { if (exp.IsVariableBoundedInQuantifier) { return(exp); } // F: this check is there as there may be slack variables form subpolyhedra Variable var; if (!exp.TryGetFrameworkVariable(out var)) { return(null); } // We want to replace the return variable with the marker for the return value if (replaceReturnValue && this.returnVariable.IsValid && var.Equals(this.returnVariable.Value)) { details.HasVariables = true; details.HasReturnVariable = true; return(this.returnExpression); } #region First try: Read it in the post-state var accessPath = context.ValueContext.VisibleAccessPathListFromPost(context.MethodContext.CFG.NormalExit, var, allowReturnValue); #if false // F: change!!!! // Console.WriteLine("Access paths for sv = {0}", var); foreach (var ap in context.ValueContext.AccessPaths(context.MethodContext.CFG.NormalExit, var, AccessPathFilter <Method> .FromPostcondition(this.context.MethodContext.CurrentMethod))) { // Console.WriteLine(ap); if (context.ValueContext.PathSuitableInEnsures(context.MethodContext.CFG.NormalExit, ap)) { // we found our accesspath accessPath = ap; break; } } #endif if (accessPath != null) { details.HasVariables = true; details.HasReturnVariable = accessPath.Head.IsReturnValue; if (accessPath.Length() == 1 && accessPath.ToString() == "this") { details.IsThis = true; } if (accessPath.Head.ToString() == "this") { details.IsRootedInThis = true; } // TODO: check possible bug here: this should be var not exp.UnderlyingVariable return(BoxedExpression.Var(var, accessPath)); } #endregion #region Second try: Read it in the pre-state accessPath = // context.ValueContext.VisibleAccessPathListFromPre(context.MethodContext.CFG.EntryAfterRequires, var); context.ValueContext.AccessPathList(context.MethodContext.CFG.EntryAfterRequires, var, false, false); if (accessPath != null) { details.HasVariables = true; var type = this.context.ValueContext.GetType(this.context.MethodContext.CFG.NormalExit, var); if (type.IsNormal) { details.HasOldVariable = true; return(BoxedExpression.Old(BoxedExpression.Var(var, accessPath), type.Value)); } else { return(null); } } #endregion #region Third try: use the extended refined, if any if (this.extendedRefiner != null) { BoxedExpression refined; if (this.extendedRefiner.TryRefineExpression(this.context.MethodContext.CFG.NormalExit, var, out refined) && refined.IsArrayIndex) // F: it seems we generate some recursive expression which causes a stack overflow. Should investigate!!!! { return(ExpressionInPostStateHelper(refined, replaceReturnValue, overrideAccessModifiers, allowReturnValue, ref details)); } } #endregion // giving up return(null); } if (exp.IsUnary) { var rec = ExpressionInPostStateHelper(exp.UnaryArgument, replaceReturnValue, overrideAccessModifiers, allowReturnValue, ref details); if (rec == null) { return(null); } // Avoid copying the expression (optimization?) if (rec == exp.UnaryArgument) { return(exp); } else { return(BoxedExpression.Unary(exp.UnaryOp, rec)); } } if (exp.IsBinary) { if (!exp.BinaryOp.IsComparisonBinaryOperator()) { details.HasCompoundExp = true; } var recLeft = ExpressionInPostStateHelper(exp.BinaryLeft, replaceReturnValue, overrideAccessModifiers, allowReturnValue, ref details); if (recLeft == null) { return(null); } var recRight = ExpressionInPostStateHelper(exp.BinaryRight, replaceReturnValue, overrideAccessModifiers, allowReturnValue, ref details); if (recRight == null) { return(null); } // Heuristics to rule out trivial expressions arr.Length >= 0 or 0 <= arr.Length or this.Count >= 0 or 0 <= this.Count int value; if ((exp.BinaryOp == BinaryOperator.Cge && recLeft.IsArrayLengthOrThisDotCount(context.MethodContext.CFG.NormalExit, this.context, this.metaDataDecoder) && recRight.IsConstantInt(out value) && value == 0) || (exp.BinaryOp == BinaryOperator.Cle && recLeft.IsConstantInt(out value) && value == 0 && recRight.IsArrayLengthOrThisDotCount(context.MethodContext.CFG.NormalExit, this.context, this.metaDataDecoder))) { return(null); } if (recLeft == exp.BinaryLeft && recRight == exp.BinaryRight) { return(exp); } else { return(BoxedExpression.Binary(exp.BinaryOp, recLeft, recRight)); } } object t; BoxedExpression array, index; if (exp.IsArrayIndexExpression(out array, out index, out t) && t is Typ) { // Sanity check. We have a case with post-inference where the array and the index get swapped by the underlying framework if (array.UnderlyingVariable is Variable) { var type = this.context.ValueContext.GetType(context.MethodContext.CFG.NormalExit, (Variable)array.UnderlyingVariable); if (type.IsNormal && this.metaDataDecoder.IsArray(type.Value)) { var arrayRef = ExpressionInPostStateHelper(array, replaceReturnValue, overrideAccessModifiers, allowReturnValue, ref details); if (arrayRef != null) { var indexRef = ExpressionInPostStateHelper(index, replaceReturnValue, overrideAccessModifiers, allowReturnValue, ref details); if (indexRef != null) { return(new BoxedExpression.ArrayIndexExpression <Typ>(arrayRef, indexRef, (Typ)t)); } } } } return(null); } // Unreachable? return(null); }
public IEnumerable <LispList <PathElement> > AccessPaths(APC at, SymValue value, AccessPathFilter <Method> filter) { Domain domain; if (!this.parent.PreStateLookup(at, out domain)) { throw new ArgumentException("pc wasn't visited"); } return(domain.GetAccessPathsFiltered(value, filter, true).Select(path => path.Coerce <PathElementBase, PathElement> ())); }