private static TypeName TranslateToTypeName <Local, Parameter, Method, Field, Property, Event, Type, Attribute, Assembly>(Type type, IOutput output, IDecodeMetaData <Local, Parameter, Method, Field, Property, Event, Type, Attribute, Assembly> mdDecoder) { // case analysis over kind of type we have here. if (mdDecoder.IsArray(type)) { TypeName elementType = TranslateToTypeName(mdDecoder.ElementType(type), output, mdDecoder); return(elementType.SzArrayType); } if (mdDecoder.IsManagedPointer(type)) { TypeName elementType = TranslateToTypeName(mdDecoder.ElementType(type), output, mdDecoder); return(elementType.ManagedPointerType); } if (mdDecoder.IsUnmanagedPointer(type)) { TypeName elementType = TranslateToTypeName(mdDecoder.ElementType(type), output, mdDecoder); return(elementType.PointerType); } if (mdDecoder.IsFormalTypeParameter(type)) { return(TypeName.MakeGenericTypeParameter(mdDecoder.NormalizedFormalTypeParameterIndex(type))); } if (mdDecoder.IsMethodFormalTypeParameter(type)) { return(TypeName.MakeGenericMethodParameter(mdDecoder.MethodFormalTypeParameterIndex(type))); } Microsoft.Research.DataStructures.IIndexable <Type> typeArgs; if (mdDecoder.IsSpecialized(type, out typeArgs)) { TypeDefinitionName genericType = Translate(mdDecoder.Unspecialized(type), output, mdDecoder); TypeName[] typeArgNames = Translate(typeArgs, output, mdDecoder); return(genericType.Instantiate(typeArgNames)); } // TODO: handle optional/required modifiers and generic type instances and type parameters TypeDefinitionName tdef = Translate(type, output, mdDecoder); return(tdef.Instantiate()); }
private static void CanonicalTypeRefName(Type type, StringBuilder sb, IDecodeMetaData <Local, Parameter, Method, Field, Property, Event, Type, Attribute, Assembly> decoder) { if (decoder.IsArray(type)) { CanonicalTypeRefName(decoder.ElementType(type), sb, decoder); sb.Append("[]"); return; } if (decoder.IsManagedPointer(type)) { sb.Append("ref "); CanonicalTypeRefName(decoder.ElementType(type), sb, decoder); return; } if (decoder.IsFormalTypeParameter(type)) { sb.Append(decoder.Name(type)); return; } if (decoder.IsMethodFormalTypeParameter(type)) { sb.Append(decoder.Name(type)); return; } IIndexable <Type> typeArgs; if (decoder.IsSpecialized(type, out typeArgs)) { CanonicalTypeRefName(decoder.Unspecialized(type), sb, decoder); sb.Append('<'); for (int i = 0; i < typeArgs.Count; i++) { CanonicalTypeRefName(typeArgs[i], sb, decoder); if (i < typeArgs.Count - 1) { sb.Append(','); } } return; } if (decoder.IsUnmanagedPointer(type)) { CanonicalTypeRefName(decoder.ElementType(type), sb, decoder); sb.Append("*"); return; } Type modified; IIndexable <Pair <bool, Type> > modifiers; if (decoder.IsModified(type, out modified, out modifiers)) { CanonicalTypeRefName(modified, sb, decoder); for (int i = 0; i < modifiers.Count; i++) { if (modifiers[i].One) { sb.Append(" opt("); } else { sb.Append(" req("); } CanonicalTypeRefName(modifiers[i].Two, sb, decoder); sb.Append(')'); } return; } CanonicalTypeDefName(type, sb, decoder); }
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, metaDataDecoder.System_Object, 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 && returnVariable.IsValid && var.Equals(returnVariable.Value)) { details.HasVariables = true; details.HasReturnVariable = true; return(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(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 = context.ValueContext.GetType(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 (extendedRefiner != null) { BoxedExpression refined; if (extendedRefiner.TryRefineExpression(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, context, metaDataDecoder) && recRight.IsConstantInt(out value) && value == 0) || (exp.BinaryOp == BinaryOperator.Cle && recLeft.IsConstantInt(out value) && value == 0 && recRight.IsArrayLengthOrThisDotCount(context.MethodContext.CFG.NormalExit, context, 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 = context.ValueContext.GetType(context.MethodContext.CFG.NormalExit, (Variable)array.UnderlyingVariable); if (type.IsNormal && 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); }