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());
        }
Exemple #2
0
        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);
        }