Example #1
0
        /// <summary>
        /// Replaces any MemberBindings of the form (this,x) in the methodContract with a method call where the method
        /// being called is P where x is a private field of the source type that has been marked as [ContractPublicPropertyName("P")].
        /// </summary>
        /// <param name="targetType"></param>
        /// <param name="sourceType"></param>
        /// <param name="methodContract"></param>
        internal static void ReplacePrivateFieldsThatHavePublicProperties(TypeNode targetType,
                                                                          TypeNode sourceType,
                                                                          MethodContract methodContract,
                                                                          ContractNodes contractNodes
                                                                          )
        {
            Contract.Requires(sourceType != null);

            Dictionary <Field, Method> field2Getter = new Dictionary <Field, Method>();

            for (int i = 0, n = /*sourceType.Members == null ? 0 : */ sourceType.Members.Count; i < n; i++)
            {
                Field f = sourceType.Members[i] as Field;
                if (f == null)
                {
                    continue;
                }
                string propertyName = HelperMethods.GetStringFromAttribute(f, ContractNodes.SpecPublicAttributeName);
                if (propertyName != null)
                {
                    Property p = sourceType.GetProperty(Identifier.For(propertyName));
                    if (p != null)
                    {
                        field2Getter.Add(f, p.Getter);
                    }
                }
            }
            if (0 < field2Getter.Count)
            {
                SubstitutePropertyGetterForField s = new SubstitutePropertyGetterForField(field2Getter);
                s.Visit(methodContract);
            }
            return;
        }
        public ExtractorVisitor(ContractNodes /*!*/ contractNodes,
            AssemblyNode ultimateTargetAssembly,
            AssemblyNode realAssembly,
            bool verbose,
            bool fSharp)
        {
            Contract.Requires(contractNodes != null);
            Contract.Requires(realAssembly != null);

            this.contractNodes = contractNodes;
            this.verbose = verbose;
            this.fSharp = fSharp;
            this.visibility = new VisibilityHelper();
            this.errorFound = false;
            this.extractionFinalizer = new ExtractionFinalizer(contractNodes);
            this.ultimateTargetAssembly = ultimateTargetAssembly;
            this.realAssembly = realAssembly;

            this.contractNodes.ErrorFound += delegate(CompilerError error)
            {
                // Commented out because the ErrorFound event already had a handler that was printing out a message
                // and so error messages were getting printed out twice
                //if (!error.IsWarning || warningLevel > 0) {
                //  Console.WriteLine(error.ToString());
                //}
                errorFound |= !error.IsWarning;
            };

            this.TaskType = new Cache<TypeNode>(() => HelperMethods.FindType(realAssembly, Identifier.For("System.Threading.Tasks"), Identifier.For("Task")));

            this.GenericTaskType = new Cache<TypeNode>(() =>
                HelperMethods.FindType(realAssembly, Identifier.For("System.Threading.Tasks"),
                    Identifier.For("Task" + TargetPlatform.GenericTypeNamesMangleChar + "1")));
        }
 public GenerateDocumentationFromPDB(ContractNodes contracts, int tabWidth, bool writeOutput)
 {
     this.contracts   = contracts;
     this.tabWidth    = tabWidth;
     this.tabStops    = 0;
     this.writeOutput = writeOutput;
 }
 public ClousotExtractor(ContractNodes contractNodes, AssemblyNode ultimateTargetAssembly,
                         AssemblyNode realAssembly, Action <System.CodeDom.Compiler.CompilerError> errorHandler)
     : base(contractNodes, ultimateTargetAssembly, realAssembly)
 {
     Contract.Requires(contractNodes != null);
     Contract.Requires(realAssembly != null);
 }
 public CollectOldExpressions(Module module, Method method, ContractNodes contractNodes, Dictionary <TypeNode, Local> closureLocals,
                              int localCounterStart, Class initialClosureClass)
     : this(module, method, contractNodes, closureLocals, localCounterStart)
 {
     this.topLevelClosureClass = initialClosureClass;
     this.currentClosureClass  = initialClosureClass;
 }
 public CollectOldExpressions(Module module, Method method, ContractNodes contractNodes, Dictionary<TypeNode, Local> closureLocals, 
     int localCounterStart, Class initialClosureClass)
     : this(module, method, contractNodes, closureLocals, localCounterStart)
 {
     this.topLevelClosureClass = initialClosureClass;
     this.currentClosureClass = initialClosureClass;
 }
 public ClousotExtractor(ContractNodes contractNodes, AssemblyNode ultimateTargetAssembly,
     AssemblyNode realAssembly, Action<System.CodeDom.Compiler.CompilerError> errorHandler)
     : base(contractNodes, ultimateTargetAssembly, realAssembly)
 {
     Contract.Requires(contractNodes != null);
     Contract.Requires(realAssembly != null);
 }
        public DuplicatorForContractsAndClosures(Module module, Method sourceMethod, Method targetMethod,
                                                 ContractNodes contractNodes, bool mapParameters)
            : base(module, targetMethod.DeclaringType)
        {
            this.sourceMethod = sourceMethod;
            this.targetMethod = targetMethod;

            this.RemoveNameForLocals = true;

            Duplicator dup = this;

            if (mapParameters)
            {
                if (sourceMethod.ThisParameter != null)
                {
                    if (targetMethod.ThisParameter != null)
                    {
                        dup.DuplicateFor[sourceMethod.ThisParameter.UniqueKey] = targetMethod.ThisParameter;
                    }
                    else
                    {
                        // target is a static wrapper. But duplicator cannot handle This -> Parameter conversion
                        // so we handle it explicitly here in this visitor.
                        replaceThisWithParameter = targetMethod.Parameters[0];
                    }
                }

                if (sourceMethod.Parameters != null && targetMethod.Parameters != null &&
                    sourceMethod.Parameters.Count == targetMethod.Parameters.Count)
                {
                    for (int i = 0, n = sourceMethod.Parameters.Count; i < n; i++)
                    {
                        dup.DuplicateFor[sourceMethod.Parameters[i].UniqueKey] = targetMethod.Parameters[i];
                    }
                }
            }

            var originalType = HelperMethods.IsContractTypeForSomeOtherType(sourceMethod.DeclaringType, contractNodes);

            if (originalType != null)
            {
                var contractType = this.contractClass = sourceMethod.DeclaringType;
                while (contractType.Template != null)
                {
                    contractType = contractType.Template;
                }

                while (originalType.Template != null)
                {
                    originalType = originalType.Template;
                }

                // forward ContractType<A,B> -> originalType<A',B'>
                this.contractClassToForward = contractType;
                this.targetTypeToForwardTo  = originalType;

                //dup.DuplicateFor[contractType.UniqueKey] = originalType;
            }
        }
Example #9
0
        public static bool UsesModel(Node node, ContractNodes contractNodes)
        {
            CodeInspector ifrv = new CodeInspector(ContractNodes.ModelAttributeName, contractNodes, null, false);

            ifrv.Visit(node);

            return(ifrv.foundAttribute);
        }
 public static bool UsesModel(Node node, ContractNodes contractNodes)
 {
     CodeInspector ifrv = new CodeInspector(ContractNodes.ModelAttributeName, contractNodes, null, false);
     
     ifrv.Visit(node);
     
     return ifrv.foundAttribute;
 }
        public DuplicatorForContractsAndClosures(Module module, Method sourceMethod, Method targetMethod,
            ContractNodes contractNodes, bool mapParameters)
            : base(module, targetMethod.DeclaringType)
        {
            this.sourceMethod = sourceMethod;
            this.targetMethod = targetMethod;

            this.RemoveNameForLocals = true;

            Duplicator dup = this;

            if (mapParameters)
            {
                if (sourceMethod.ThisParameter != null)
                {
                    if (targetMethod.ThisParameter != null)
                    {
                        dup.DuplicateFor[sourceMethod.ThisParameter.UniqueKey] = targetMethod.ThisParameter;
                    }
                    else
                    {
                        // target is a static wrapper. But duplicator cannot handle This -> Parameter conversion
                        // so we handle it explicitly here in this visitor.
                        replaceThisWithParameter = targetMethod.Parameters[0];
                    }
                }

                if (sourceMethod.Parameters != null && targetMethod.Parameters != null
                    && sourceMethod.Parameters.Count == targetMethod.Parameters.Count)
                {
                    for (int i = 0, n = sourceMethod.Parameters.Count; i < n; i++)
                    {
                        dup.DuplicateFor[sourceMethod.Parameters[i].UniqueKey] = targetMethod.Parameters[i];
                    }
                }
            }

            var originalType = HelperMethods.IsContractTypeForSomeOtherType(sourceMethod.DeclaringType, contractNodes);
            if (originalType != null)
            {
                var contractType = this.contractClass = sourceMethod.DeclaringType;
                while (contractType.Template != null)
                {
                    contractType = contractType.Template;
                }
                    
                while (originalType.Template != null)
                {
                    originalType = originalType.Template;
                }

                // forward ContractType<A,B> -> originalType<A',B'>
                this.contractClassToForward = contractType;
                this.targetTypeToForwardTo = originalType;

                //dup.DuplicateFor[contractType.UniqueKey] = originalType;
            }
        }
        /// <summary>
        /// actualReturn type is null if Task is not generic, otherwise ,the Task result type.
        /// </summary>
        public static bool Contains(Node node, ContractNodes contractNodes, Method currentMethod,
            TypeNode actualReturnType)
        {
            var v = new AsyncReturnValueQuery(contractNodes, currentMethod, actualReturnType);

            v.Visit(node);

            return v.foundReturnValueTaskResult;
        }
Example #13
0
        public static bool IsRuntimeIgnored(Node node, ContractNodes contractNodes, TypeNode referencingType, bool skipQuantifiers)
        {
            CodeInspector ifrv = new CodeInspector(
                ContractNodes.RuntimeIgnoredAttributeName, contractNodes, referencingType, skipQuantifiers);

            ifrv.Visit(node);

            return(ifrv.foundAttribute);
        }
Example #14
0
        /// <summary>
        /// actualReturn type is null if Task is not generic, otherwise ,the Task result type.
        /// </summary>
        public static bool Contains(Node node, ContractNodes contractNodes, Method currentMethod,
                                    TypeNode actualReturnType)
        {
            var v = new AsyncReturnValueQuery(contractNodes, currentMethod, actualReturnType);

            v.Visit(node);

            return(v.foundReturnValueTaskResult);
        }
        public static bool IsRuntimeIgnored(Node node, ContractNodes contractNodes, TypeNode referencingType, bool skipQuantifiers)
        {
            CodeInspector ifrv = new CodeInspector(
                ContractNodes.RuntimeIgnoredAttributeName, contractNodes, referencingType, skipQuantifiers);
            
            ifrv.Visit(node);

            return ifrv.foundAttribute;
        }
Example #16
0
        /// <summary>
        /// If <paramref name="assembly"/> is null then this looks for the contract class in mscorlib.
        /// If it isn't null then it searches in <paramref name="assembly"/> for the contract class.
        /// Returns null if the contract class is not found.
        /// </summary>
        public static ContractNodes GetContractNodes(AssemblyNode assembly, Action <System.CodeDom.Compiler.CompilerError> errorHandler)
        {
            ContractNodes contractNodes = new ContractNodes(assembly, errorHandler);

            if (contractNodes.ContractClass == null)
            {
                return(null);
            }
            return(contractNodes);
        }
        public AbbreviationDuplicator(Method sourceMethod, Method targetMethod, ContractNodes contractNodes,
                                      Method abbreviation, Expression targetObject, ExpressionList actuals)
            : base(targetMethod.DeclaringType.DeclaringModule, sourceMethod, targetMethod, contractNodes, false)
        {
            this.targetObject = targetObject;
            this.abbreviation = abbreviation;
            this.actuals      = actuals;

            this.localsInActuals = new TrivialHashtable();

            PopulateLocalsInActuals();
        }
        public AbbreviationDuplicator(Method sourceMethod, Method targetMethod, ContractNodes contractNodes,
            Method abbreviation, Expression targetObject, ExpressionList actuals)
            : base(targetMethod.DeclaringType.DeclaringModule, sourceMethod, targetMethod, contractNodes, false)
        {
            this.targetObject = targetObject;
            this.abbreviation = abbreviation;
            this.actuals = actuals;

            this.localsInActuals = new TrivialHashtable();

            PopulateLocalsInActuals();
        }
        private CodeInspector(Identifier attributeToFind, ContractNodes contractNodes, TypeNode referencingType, bool skipQuantifiers)
        {
            this.foundAttribute = false;
            
            this.attributeToFind = attributeToFind;
            this.contractNodes = contractNodes;
            this.skipQuantifiers = skipQuantifiers;
            this.referencingType = new Stack<TypeNode>();

            if (referencingType != null)
            {
                this.referencingType.Push(referencingType);
            }
        }
        public CollectOldExpressions(Module module, Method method, ContractNodes contractNodes, Dictionary <TypeNode, Local> closureLocals,
                                     int localCounterStart)
        {
            this.contractNodes = contractNodes;
            this.prestateValuesOfOldExpressions = new Block(new StatementList());
            this.closureLocals = closureLocals;

            this.stackOfMethods        = new List <MethodCall>();
            this.stackOfBoundVariables = new List <Parameter>();

            this.module        = module;
            this.currentMethod = method;
            this.counter       = localCounterStart;
        }
        public CollectOldExpressions(Module module, Method method, ContractNodes contractNodes, Dictionary<TypeNode, Local> closureLocals,
            int localCounterStart)
        {
            this.contractNodes = contractNodes;
            this.prestateValuesOfOldExpressions = new Block(new StatementList());
            this.closureLocals = closureLocals;

            this.stackOfMethods = new List<MethodCall>();
            this.stackOfBoundVariables = new List<Parameter>();

            this.module = module;
            this.currentMethod = method;
            this.counter = localCounterStart;
        }
Example #22
0
        private CodeInspector(Identifier attributeToFind, ContractNodes contractNodes, TypeNode referencingType, bool skipQuantifiers)
        {
            this.foundAttribute = false;

            this.attributeToFind = attributeToFind;
            this.contractNodes   = contractNodes;
            this.skipQuantifiers = skipQuantifiers;
            this.referencingType = new Stack <TypeNode>();

            if (referencingType != null)
            {
                this.referencingType.Push(referencingType);
            }
        }
        public CopyOutOfBandContracts(AssemblyNode targetAssembly, AssemblyNode sourceAssembly,
            ContractNodes contractNodes, ContractNodes targetContractNodes)
        {
            Contract.Requires(targetAssembly != null);
            Contract.Requires(sourceAssembly != null);
            Contract.Requires(contractNodes != null);

            if (targetAssembly == sourceAssembly)
            {
                // this happened when a reference assembly for mscorlib had the assembly name "mscorlib"
                // instead of "mscorlib.Contracts" because only one assembly named "mscorlib" can be
                // loaded
                throw new ExtractorException("CopyOutOfBandContracts was given the same assembly as both the source and target!");
            }

            this.outOfBandDuplicator = new ForwardingDuplicator(targetAssembly, null, contractNodes, targetContractNodes);
            this.targetAssembly = targetAssembly;

            FuzzilyForwardReferencesFromSource2Target(targetAssembly, sourceAssembly);

            CopyMissingMembers();

            // FixupMissingProperties(); shouldn't be needed with new duplicator
        }
        public CopyOutOfBandContracts(AssemblyNode targetAssembly, AssemblyNode sourceAssembly,
                                      ContractNodes contractNodes, ContractNodes targetContractNodes)
        {
            Contract.Requires(targetAssembly != null);
            Contract.Requires(sourceAssembly != null);
            Contract.Requires(contractNodes != null);

            if (targetAssembly == sourceAssembly)
            {
                // this happened when a reference assembly for mscorlib had the assembly name "mscorlib"
                // instead of "mscorlib.Contracts" because only one assembly named "mscorlib" can be
                // loaded
                throw new ExtractorException("CopyOutOfBandContracts was given the same assembly as both the source and target!");
            }

            this.outOfBandDuplicator = new ForwardingDuplicator(targetAssembly, null, contractNodes, targetContractNodes);
            this.targetAssembly      = targetAssembly;

            FuzzilyForwardReferencesFromSource2Target(targetAssembly, sourceAssembly);

            CopyMissingMembers();

            // FixupMissingProperties(); shouldn't be needed with new duplicator
        }
Example #25
0
        private static ContractNodes IdentifyContractAssemblyIfReferenced(ContractNodes contracts, AssemblyNode assemblyToVisit)
        {
            Contract.Requires(assemblyToVisit != null);

            if (contracts != null)
            {
                AssemblyNode assemblyContractsLiveIn = contracts.ContractClass == null
                    ? null
                    : contracts.ContractClass.DeclaringModule as AssemblyNode;

                if (assemblyContractsLiveIn != null)
                {
                    if (assemblyContractsLiveIn == assemblyToVisit)
                    {
                        return(contracts);
                    }

                    string nameOfAssemblyContainingContracts = assemblyContractsLiveIn.Name;

                    Contract.Assume(assemblyToVisit.AssemblyReferences != null);

                    foreach (var ar in assemblyToVisit.AssemblyReferences)
                    {
                        Contract.Assume(ar != null);

                        if (ar.Name == nameOfAssemblyContainingContracts)
                        {
                            // just do name matching to avoid loading the referenced assembly
                            return(contracts);
                        }
                    }
                }
            }

            return(null);
        }
Example #26
0
 public Decompiler(ContractNodes cns, Local l)
 {
     this.contractNodes       = cns;
     this.localToUseForResult = l;
 }
 public PreconditionChecker(Action<CompilerError> errorHandler, ContractNodes usedToExtract)
     : base(errorHandler, usedToExtract)
 {
     // F:
     Contract.Requires(errorHandler != null);
     Contract.Requires(usedToExtract != null);
 }
            public BasicChecker(Action<CompilerError> errorHandler, ContractNodes usedToExtract)
            {
                Contract.Requires(errorHandler != null);
                Contract.Requires(usedToExtract != null);

                this.errorHandler = errorHandler;
                this.usedToExtract = usedToExtract;
            }
Example #29
0
        public static TypeNode IsContractTypeForSomeOtherType(TypeNode t, ContractNodes contractNodes)
        {
            var unspecializedType = IsContractTypeForSomeOtherTypeUnspecialized(t, contractNodes);

            if (unspecializedType == null) return null;
            
            // else go search t's list of interfaces/base classes to find the specialized type
            // (which might be specialized only with a type parameter, but that's better than
            // returning the unspecialized one from the attribute, because the unspecialized one
            // will never be pointer equal to any specialized type.
            for (int i = 0, n = t.Interfaces == null ? 0 : t.Interfaces.Count; i < n; i++)
            {
                if (unspecializedType == t.Interfaces[i] || unspecializedType == t.Interfaces[i].Template)
                    return t.Interfaces[i];
            }

            if (unspecializedType == t.BaseType || unspecializedType == t.BaseType.Template) return t.BaseType;
            
            return null;
        }
Example #30
0
        internal static Local ExtractPreamble(Method m, ContractNodes contractNodes, Block contractInitializer,
            out Block postPreamble, ref StackDepthTracker dupStackTracker, bool isVB)
        {
            postPreamble = null;

            if (m == null || m.Body == null || m.Body.Statements == null || !(m.Body.Statements.Count > 0)) return null;
            
            Block firstBlock = m.Body.Statements[0] as Block;
            if (firstBlock == null) return null;
            
            Block preambleBlock = new PreambleBlock(new StatementList(0));

            Local result;
            
            int nextInstructionInFirstBlock = ExtractClosureInitializationAndLocalThis(m, firstBlock, contractNodes,
                contractInitializer, preambleBlock, 0, out result, ref dupStackTracker);

            // Type (2): Base ctor or deferring ctor call

            if (m is InstanceInitializer)
            {
                int i, j;
                bool found;

                // Type (2a): Assignments to fields of class that had initializers

                // Just extract the statements for (2a) as part of what gets extracted for (2b)

                // Type (2b): base or deferring ctor call

                found = SearchClump(m.Body.Statements, 
                    delegate(Statement s)
                    {
                        if (s == null) return false;

                        ExpressionStatement es = s as ExpressionStatement;
                        if (es == null) return false;
                    
                        MethodCall mc = es.Expression as MethodCall;
                        if (mc == null) return false;
                    
                        MemberBinding mb = mc.Callee as MemberBinding;
                        if (mb == null) return false;
                    
                        Method callee = mb.BoundMember as Method;
                    
                        // can't depend on the TargetObject being "this": it could be "pop" if
                        // the arguments to the call had any control flow
                        // e.g., a boolean short-circuit expression or a ternary expression.
                        //if (mb.TargetObject is This && callee is InstanceInitializer) return true;
                        if (callee is InstanceInitializer
                            &&
                            ((callee.DeclaringType == m.DeclaringType || callee.DeclaringType.Template == m.DeclaringType)
                             // deferring ctor call
                             ||
                             (callee.DeclaringType == m.DeclaringType.BaseType ||
                              // base ctor call
                              callee.DeclaringType.Template == m.DeclaringType.BaseType.Template)))
                        {
                            return true;
                        }

                        return false;

                    }, 
                    out i, out j);

                if (found)
                {
                    // for VB constructors and C# constructors with closures, we need to extend the scope to include field initializers

                    Block b = (Block) m.Body.Statements[i];
                    int k = j + 1;
                    Local extraClosureLocal = null;
                    int stackDepth = 0;

                    for (; k < b.Statements.Count; k++)
                    {
                        // skip over auxiliary closure creation
                        if (extraClosureLocal == null && IsClosureCreation(m, b.Statements[k], out extraClosureLocal))
                        {
                            continue;
                        }

                        switch (b.Statements[k].NodeType)
                        {
                            case NodeType.Nop:
                                continue;

                            case NodeType.AssignmentStatement:
                            {
                                AssignmentStatement assgmt = (AssignmentStatement) b.Statements[k];
                                MemberBinding mb = assgmt.Target as MemberBinding;
                                if (mb == null)
                                {
                                    // we might be initializing locals for default values etc
                                    if (stackDepth > 0) continue;
                                    
                                    goto doneWithFieldInits;
                                }

                                if (!(mb.BoundMember is Field))
                                {
                                    // we might be initializing locals for default values etc
                                    if (stackDepth > 0) continue;
                                    goto doneWithFieldInits;
                                }

                                if (mb.TargetObject == null)
                                {
                                    // we might be initializing locals for default values etc
                                    if (stackDepth > 0) continue;
                                    goto doneWithFieldInits;
                                }

                                // there are 2 cases here. Either we are assigning to this.f = ..., which is a field initialization,
                                // or it is initializing the closure field for "this" with this.
                                if (mb.TargetObject.NodeType == NodeType.This)
                                {
                                    // okay field initialization
                                    continue;
                                }

                                if (mb.TargetObject.NodeType == NodeType.Pop)
                                {
                                    // okay field initialization (popping this)
                                    stackDepth--;
                                    continue;
                                }

                                // we might also be initializing the extra closure fields, if the target is the extraClosureLocal.
                                if (mb.TargetObject == extraClosureLocal)
                                {
                                    continue;
                                }

                                if (mb.TargetObject.NodeType == NodeType.Local && assgmt.Source != null &&
                                    assgmt.Source.NodeType == NodeType.This && mb.BoundMember.Name != null &&
                                    (mb.BoundMember.Name.Name.EndsWith("_this") || mb.BoundMember.Name.Name == "$VB$Me"))
                                {
                                    // closure initialization (storing this)
                                    // add it to postPreamble, since it needs to be inserted for duplicate closure object
                                    postPreamble = new Block(new StatementList(1));
                                    postPreamble.Statements.Add((Statement) b.Statements[k].Clone());
                                    continue;
                                }

                                goto doneWithFieldInits;
                            }

                            case NodeType.ExpressionStatement:
                            {
                                ExpressionStatement estmt = (ExpressionStatement) b.Statements[k];
                                if (estmt.Expression != null && estmt.Expression is This)
                                {
                                    // handle special push/pop pattern occurring occasionally
                                    stackDepth++;
                                    continue;
                                }

                                // handle ctor calls on addresses of value types
                                // NOTE: this could be mistakenly the first user statement.
                                MethodCall mc = estmt.Expression as MethodCall;
                                if (mc == null) goto doneWithFieldInits;

                                MemberBinding mb = mc.Callee as MemberBinding;
                                if (mb == null) goto doneWithFieldInits;
                                
                                if (!(mb.BoundMember is InstanceInitializer)) goto doneWithFieldInits;
                                
                                if (!mb.BoundMember.DeclaringType.IsValueType) goto doneWithFieldInits;
                                
                                if (mb.TargetObject.NodeType != NodeType.AddressOf) goto doneWithFieldInits;
                                
                                continue;
                            }

                            default:
                                goto doneWithFieldInits;
                        }
                    }

                    doneWithFieldInits:

                    StatementList sl2 = ExtractClump(m.Body.Statements, 0, 0, i, k - 1);
                    preambleBlock.Statements.Add(new Block(sl2));

                    ExtractVB_ENCCallToPreamble(m.Body.Statements[i] as Block, k, preambleBlock.Statements);
                }
                else
                {
                    // for struct ctors, we may not have a "this" call

                    // for C# constructors with closures, we need to extend the scope

                    Block b = firstBlock;
                    int k = nextInstructionInFirstBlock;
                    Local extraClosureLocal = null;

                    for (; k < b.Statements.Count; k++)
                    {
                        // skip over auxiliary closure creation and initialization
                        if (extraClosureLocal == null && IsClosureCreation(m, b.Statements[k], out extraClosureLocal))
                        {
                            continue;
                        }

                        switch (b.Statements[k].NodeType)
                        {
                            case NodeType.Nop:
                                continue;

                            case NodeType.AssignmentStatement:
                            {
                                AssignmentStatement assgmt = (AssignmentStatement) b.Statements[k];
                                MemberBinding mb = assgmt.Target as MemberBinding;
                                
                                if (mb == null) goto doneWithFieldInits;

                                if (!(mb.BoundMember is Field)) goto doneWithFieldInits;
                                
                                if (mb.TargetObject == null) goto doneWithFieldInits;
                                
                                // we might be initializing the extra closure fields, if the target is the extraClosureLocal.
                                if (mb.TargetObject == extraClosureLocal)
                                {
                                    continue;
                                }

                                goto doneWithFieldInits;
                            }

                            default:
                                goto doneWithFieldInits;
                        }
                    }

                    doneWithFieldInits:
                    
                    for (int toCopy = nextInstructionInFirstBlock; toCopy < k; toCopy++)
                    {
                        preambleBlock.Statements.Add(firstBlock.Statements[toCopy]);
                        firstBlock.Statements[toCopy] = null;
                    }
                }
            }

            // Create a new body, add the preamble block, then all of the other blocks

            StatementList sl = new StatementList(m.Body.Statements.Count);
            sl.Add(preambleBlock);

            if (m.Body != null)
            {
                foreach (Block b in m.Body.Statements)
                {
                    if (b != null) sl.Add(b);
                }
            }

            m.Body.Statements = sl;

            return result;
        }
Example #31
0
        internal static MethodContract DuplicateContractAndClosureParts(
            DuplicatorForContractsAndClosures dup, Method targetMethod, Method sourceMethod,
            ContractNodes contractNodes, bool copyValidations)
        {
            Contract.Ensures(Contract.Result<MethodContract>() != null);

            //System.Console.WriteLine(">>>" + sourceMethod.FullName);

            // materialize source contract:
            var sourceContract = sourceMethod.Contract;
            ForceSideEffect(sourceContract.ContractInitializer);
            TypeNode targetType = targetMethod.DeclaringType;
            TypeNode sourceType = sourceMethod.DeclaringType;

            // need to null out ProvideNestedTypes so the NestedTypes property doesn't use
            // metadata to fill in the list of nested types. Because maybe sourceType has
            // had nested types added to it in memory and those nested types don't exist
            // in the assembly that sourceType is defined in.

            // The source type itself shouldn't be duplicated, because any references to its
            // members (e.g., method calls) in a contract should remain as references to that
            // member. I.e., a contract on virtual method B.M might contain a call to "this.P()". When copying
            // the contract from B.M to an override C.M, "this" of type B should become "this" of type C (which
            // is why the self parameter is mapped below), but the member B.P() should remain B.P().
            // However, any nested types within the source type, such as any closure classes, *should* be
            // duplicated.
            sourceType.ProvideNestedTypes = null;
            targetType.ProvideNestedTypes = null;

            // HACK

            // For some reason, it is important to materialize the name of the targetType here!!!
            // Otherwise the duplicator will fail.
            ForceSideEffect(targetType.Name.Name);

            Local closureLocal;
            FindClosureInitialization(sourceMethod, sourceContract.ContractInitializer, out closureLocal);

            // Duplicate anonymous delegates that turn into static methods (and their caching fields)
            FindClosurePartsToDuplicate fmd = new FindClosurePartsToDuplicate(sourceType, sourceMethod);
            fmd.VisitMethodContract(sourceContract);

            // special handling of closures that are not used.
            if (closureLocal != null)
            {
                var closureType = Unspecialize(closureLocal.Type);
                if (!fmd.MembersToDuplicate.Contains(closureType))
                {
                    // contracts do not depend on closure and won't copy it, so remove the initialization, otherwise debugger gets confused
                    DeleteClosureInitialization(sourceMethod, sourceContract, closureLocal);
                }
            }

            // !Very important!
            // To get appropriate types mapping for duplicated members we have to have two steps approach.
            // First we need to copy all static closures (they're exists only for roslyn-based compiler)
            // Second we need to copy all other members (including closures).
            // The reason why the members are traversed backwards is following:
            // Nested scope can introduced nested closures. In this case, top level closures can reference
            // low level closures. Traversing them in backward order will allow to fill type mapping appropriately.

            for (var memindex = fmd.MembersToDuplicate.Count - 1; memindex >= 0; memindex--)
            {
                Member member = fmd.MembersToDuplicate[memindex];

                if (IsRoslynBasedStaticClosure(member))
                {
                    DuplicateMember(dup, fmd, memindex, targetType);
                }
            }

            for (var memindex = fmd.MembersToDuplicate.Count - 1; memindex >= 0; memindex--)
            {
                var member = fmd.MembersToDuplicate[memindex];
                if (IsRoslynBasedStaticClosure(member))
                {
                    continue;
                }

                DuplicateMember(dup, fmd, memindex, targetType);
            }

            var duplicateContract = dup.VisitMethodContract(sourceContract);
            if (copyValidations)
            {
                duplicateContract.Validations = dup.VisitRequiresList(sourceContract.Validations);
            }

            foreach (Member mem in sourceType.Members)
            {
                if (mem == null) continue;
                Member newMember = (Member) dup.DuplicateFor[mem.UniqueKey];
                if (newMember != null && mem != (Member) targetType && newMember.DeclaringType == targetType &&
                    !targetType.Members.Contains(newMember))
                {
                    TypeNode nestedType = mem as TypeNode;
                    if (nestedType != null && nestedType.Template != null)
                    {
                        // don't add instantiations
                        continue;
                    }

                    Method nestedMethod = mem as Method;
                    if (nestedMethod != null && nestedMethod.Template != null)
                    {
                        // don't add instantiations
                        continue;
                    }
                    
                    // second conjunct is to make sure we don't recursively add a nested type to itself
                    // e.g., ArrayList+IListWrapper extends ArrayList and so inherits contracts from it
                    // so this method could be called with sourceMethod "ArrayList.M" and targetMethod "ArrayList+IListWrapper.M"

                    // But need to make sure that there isn't already a type with the same name!!!
                    TypeNode possibleClash = targetType.GetNestedType(newMember.Name);
                    if (possibleClash != null)
                    {
                        newMember.Name = Identifier.For(newMember.Name.Name + "_1");
                    }

                    // System.Console.WriteLine("found nested member that wasn't there before closure and contract duplication: {0}", newMember.FullName);
                    dup.SafeAddMember(targetType, newMember, mem);
                    //targetType.Members.Add(newMember);
                }
            }

            return duplicateContract;
        }
Example #32
0
        public static bool ExtractContracts(AssemblyNode /*!*/ assembly,
            AssemblyNode /*?*/ referenceAssembly,
            ContractNodes /*?*/ contracts,
            ContractNodes /*?*/ backupContracts,
            ContractNodes /*?*/ targetContractNodes,
            out ContractNodes /*?*/ contractNodesUsedToExtract,
            Action<CompilerError> /*?*/ errorHandler,
            bool useClousotExtractor)
        {
            Contract.Requires(assembly != null);

            AssemblyNode assemblyToVisit = referenceAssembly ?? assembly;

            // Try to use supplied contracts, if present. But don't just try extracting and somehow
            // figuring out if any contracts had been present. Instead, see if:
            //   a) the contract methods are defined in the assembly we are extracting from, or
            //   b) the assembly reference microsoft.contracts.dll (the backup contracts and we found that assembly)
            //   c) the assembly we are extracting from has an external reference to the assembly
            //      the supplied contract methods came from.
            //   d) the contracts found in mscorlib
            //

            // see if the assembly references the backup contracts (Microsoft.Contracts.dll)
            contractNodesUsedToExtract = IdentifyContractAssemblyIfReferenced(backupContracts, assemblyToVisit);

            // see if assembly defines the contracts itself
            if (contractNodesUsedToExtract == null)
            {
                contractNodesUsedToExtract = ContractNodes.GetContractNodes(assemblyToVisit, errorHandler);
            }

            // see if the assembly references the supplied contract assembly
            if (contractNodesUsedToExtract == null)
            {
                contractNodesUsedToExtract = IdentifyContractAssemblyIfReferenced(contracts, assemblyToVisit);
            }

            // see if the contracts are in the system assembly
            if (contractNodesUsedToExtract == null && assemblyToVisit != SystemTypes.SystemAssembly)
            {
                contractNodesUsedToExtract = ContractNodes.GetContractNodes(SystemTypes.SystemAssembly, errorHandler);
            }

            if (contractNodesUsedToExtract == null) return false;

            var fSharp = false;

            // TODO: Thread the program options through here somehow and let this be specified as an option
            Contract.Assume(assemblyToVisit.Attributes != null);
            foreach (var attr in assemblyToVisit.Attributes)
            {
                Contract.Assume(attr != null);
                Contract.Assume(attr.Type != null);
                Contract.Assume(attr.Type.Name != null);
                Contract.Assume(attr.Type.Name.Name != null);

                if (attr.Type.Name.Name.Contains("FSharpInterfaceDataVersionAttribute"))
                {
                    fSharp = true;
                    break;
                }
            }

            var ultimateTarget = (referenceAssembly != null) ? assembly : null;

            Contract.Assert(assembly != null);

            ExtractorVisitor ev = useClousotExtractor
                ? new ClousotExtractor(contractNodesUsedToExtract, ultimateTarget, assembly, errorHandler)
                : new ExtractorVisitor(contractNodesUsedToExtract, ultimateTarget, assembly, false, fSharp);

            ev.Visit(assemblyToVisit);

            if (!useClousotExtractor)
            {
                FilterForRuntime eoar = new FilterForRuntime(contractNodesUsedToExtract, targetContractNodes);
                assemblyToVisit = eoar.TransformForTarget(assemblyToVisit);
            }

            if (referenceAssembly != null)
            {
                CopyOutOfBandContracts coob = new CopyOutOfBandContracts(assembly, referenceAssembly,
                    contractNodesUsedToExtract, targetContractNodes);
                coob.VisitAssembly(referenceAssembly);
            }

            return true;
        }
 public GenerateDocumentationFromPDB(ContractNodes contracts) : this(contracts, 2, false)
 {
 }
 internal LookForBadStuff(ContractNodes contractNodes)
 {
     this.contractNodes = contractNodes;
 }
Example #35
0
 public AsyncReturnValueQuery(ContractNodes contractNodes, Method currentMethod, TypeNode actualResultType)
 {
     this.contractNodes    = contractNodes;
     this.CurrentMethod    = currentMethod;
     this.actualResultType = actualResultType;
 }
 public DuplicatorForContractsAndClosures(Module module, Method sourceMethod, Method targetMethod,
                                          ContractNodes contractNodes)
     : this(module, sourceMethod, targetMethod, contractNodes, true)
 {
 }
            /// <summary>
            /// Creates a new instance of this class.
            /// </summary>
            /// <param name="owner">Parent checker that is used to report errors.</param>
            public PurityChecker(Action<System.CodeDom.Compiler.CompilerError> errorHandler, bool fSharp, ContractNodes contractNodes)
            {
                Contract.Requires(errorHandler != null);
                Contract.Requires(contractNodes != null);

                this.errorHandler = errorHandler;
                this.fSharp = fSharp;
                this.contractNodes = contractNodes;
            }
Example #38
0
 public Decompiler(AssemblyNode assemblyNode)
 {
     this.contractNodes = ContractNodes.GetContractNodes(assemblyNode, null);
 }
Example #39
0
        /// <summary>
        /// Extract prefix code prior to contracts such as closure initialization and locals
        /// </summary>
        internal static int ExtractClosureInitializationAndLocalThis(
            Method m,
            Block firstBlock,
            ContractNodes contractNodes,
            Block contractInitializer,
            Block preambleBlock,
            int currentIndex,
            out Local localAliasingThis,
            ref StackDepthTracker dupStackTracker)
        {
            localAliasingThis = null;

            // Any prefix of null statements and nops should go into the preamble block

            //      In addition, for VB structure ctors, they start with initobj this
            //      ------------------------------------------------------------------------
            Contract.Assert(currentIndex <= firstBlock.Statements.Count);

            while (currentIndex < firstBlock.Statements.Count)
            {
                Statement s = firstBlock.Statements[currentIndex];

                if (s != null && s.NodeType != NodeType.Nop)
                {
                    // check for VB "initobj this"
                    if (!m.DeclaringType.IsValueType) break;

                    if (!(m is InstanceInitializer)) break;

                    AssignmentStatement initObj = s as AssignmentStatement;
                    if (initObj == null) break;
                    
                    AddressDereference addrderef = initObj.Target as AddressDereference;
                    if (addrderef == null) break;
                    
                    if (addrderef.Address != m.ThisParameter) break;
                    
                    Literal initObjArg = initObj.Source as Literal;
                    if (initObjArg == null) break;
                    
                    if (initObjArg.Value != null) break;
                }
                
                preambleBlock.Statements.Add(s);

                var oldCount = firstBlock.Statements.Count;
                var oldStats = firstBlock.Statements;
                
                firstBlock.Statements[currentIndex] = null;

                Contract.Assert(oldStats == firstBlock.Statements);
                Contract.Assert(oldCount == firstBlock.Statements.Count);
                
                currentIndex++;
                
                Contract.Assert(currentIndex <= firstBlock.Statements.Count);
            }

            Contract.Assert(currentIndex <= firstBlock.Statements.Count);

            // Type (1): Closure creation and initialization

            //      ---------------------------------------------
            TypeNode closureType;
            currentIndex = MovePastClosureInit(m, firstBlock, contractNodes, contractInitializer.Statements,
                preambleBlock, currentIndex, ref dupStackTracker, out closureType);

            // Local @this in contract classes

            //      -------------------------------
            // For contract classes, since we require that they use explicit interface implementation,
            // allow the single assignment statement "J this_j = this;" as part of the prelude so that
            // explicit casts are not needed all over the contracts.
            Interface iface = HelperMethods.IsContractTypeForSomeOtherType(m.DeclaringType, contractNodes) as Interface;
            if (iface != null && currentIndex < firstBlock.Statements.Count)
            {
                AssignmentStatement assgn = firstBlock.Statements[currentIndex] as AssignmentStatement;
                if (assgn != null)
                {
                    if (assgn.Target is Local && assgn.Target.Type == iface && assgn.Source is This)
                    {
                        // we currently keep the local initializer in both "contractLocalsInitializer" for static decoding
                        // AND in the preamble block for runtime checking code generation.
                        localAliasingThis = (Local) assgn.Target;

                        //        contractInitializer.Statements.Add((Statement)(firstBlock.Statements[currentIndex].Clone()));

                        //        preambleBlock.Statements.Add(firstBlock.Statements[currentIndex]);
                        firstBlock.Statements[currentIndex] = null;

                        currentIndex++;
                    }
                }
            }

            // VB hoists some other literal assignments to the start of the method.

            while (currentIndex < firstBlock.Statements.Count)
            {
                Statement s = firstBlock.Statements[currentIndex];
                if (s != null && s.NodeType != NodeType.Nop)
                {
                    // check for VB literal assignments
                    if (!s.SourceContext.Hidden) break;

                    AssignmentStatement litAssgn = s as AssignmentStatement;
                    
                    if (litAssgn == null) break;
                    var local = litAssgn.Target as Local;
                    
                    if (local == null) break;
                    
                    if (local.Name == null) break;
                    
                    if (!local.Name.Name.StartsWith("VB$t_ref$L")) break;
                    // okay, we are assigning one of these locals. Put it into the preamble.
                }

                preambleBlock.Statements.Add(s);
                
                var oldCount = firstBlock.Statements.Count;
                var oldStats = firstBlock.Statements;
                
                firstBlock.Statements[currentIndex] = null;
                
                Contract.Assert(oldStats == firstBlock.Statements);
                Contract.Assert(oldCount == firstBlock.Statements.Count);
                
                currentIndex++;
                
                Contract.Assert(currentIndex <= firstBlock.Statements.Count);
            }
            
            Contract.Assert(currentIndex <= firstBlock.Statements.Count);

            return currentIndex;
        }
        public DuplicatorForContractsAndClosures(Module module, Method sourceMethod, Method targetMethod,
                                                 ContractNodes contractNodes, bool mapParameters)
            : base(module, targetMethod.DeclaringType)
        {
            this.sourceMethod = sourceMethod;
            this.targetMethod = targetMethod;

            this.RemoveNameForLocals = true;

            Duplicator dup = this;

            if (mapParameters)
            {
                if (sourceMethod.ThisParameter != null)
                {
                    if (targetMethod.ThisParameter != null)
                    {
                        dup.DuplicateFor[sourceMethod.ThisParameter.UniqueKey] = targetMethod.ThisParameter;
                    }
                    else
                    {
                        // target is a static wrapper. But duplicator cannot handle This -> Parameter conversion
                        // so we handle it explicitly here in this visitor.
                        replaceThisWithParameter = targetMethod.Parameters[0];
                    }
                }

                if (sourceMethod.Parameters != null && targetMethod.Parameters != null &&
                    sourceMethod.Parameters.Count == targetMethod.Parameters.Count)
                {
                    for (int i = 0, n = sourceMethod.Parameters.Count; i < n; i++)
                    {
                        dup.DuplicateFor[sourceMethod.Parameters[i].UniqueKey] = targetMethod.Parameters[i];
                    }
                }

                // This code makes sure that generic method parameters used by contracts inherited from contract class
                // are correctly replaced by the one defined in the target method.
                // Without this mapping <c>CheckPost</c> method in generated async closure class would contain an invalid
                // reference to a generic contract method parameter instead of generic async closure type parameter.
                // For more about this problem see comments for Microsoft.Contracts.Foxtrot.EmitAsyncClosure.GenericTypeMapper class
                // and issue #380.
                if (sourceMethod.TemplateParameters != null && targetMethod.TemplateParameters != null &&
                    sourceMethod.TemplateParameters.Count == targetMethod.TemplateParameters.Count)
                {
                    for (int i = 0, n = sourceMethod.TemplateParameters.Count; i < n; i++)
                    {
                        dup.DuplicateFor[sourceMethod.TemplateParameters[i].UniqueKey] = targetMethod.TemplateParameters[i];
                    }
                }
            }

            var originalType = HelperMethods.IsContractTypeForSomeOtherType(sourceMethod.DeclaringType, contractNodes);

            if (originalType != null)
            {
                var contractType = this.contractClass = sourceMethod.DeclaringType;
                while (contractType.Template != null)
                {
                    contractType = contractType.Template;
                }

                while (originalType.Template != null)
                {
                    originalType = originalType.Template;
                }

                // forward ContractType<A,B> -> originalType<A',B'>
                this.contractClassToForward = contractType;
                this.targetTypeToForwardTo  = originalType;

                //dup.DuplicateFor[contractType.UniqueKey] = originalType;
            }
        }
Example #41
0
        /// <summary>
        /// Copies the closure initialization into the contractinitializer and preambleBlock (if non-null)
        /// </summary>
        internal static int MovePastClosureInit(Method m, Block firstBlock, ContractNodes contractNodes,
            StatementList contractInitializer, Block preambleBlock, int currentIndex,
            ref StackDepthTracker dupStackTracker, out TypeNode closureType)
        {
            int indexForClosureCreationStatement = currentIndex;
            
            closureType = null;
            Local introducedClosureLocal = null;
            
            while (indexForClosureCreationStatement < firstBlock.Statements.Count)
            {
                var closureCreationCandidate = firstBlock.Statements[indexForClosureCreationStatement];
                closureType = IsClosureCreation(m, closureCreationCandidate);
                
                if (closureType != null) break;
                
                if (contractNodes.IsContractOrValidatorOrAbbreviatorCall(closureCreationCandidate))
                {
                    // found contracts before closure creation, so get out
                    return currentIndex;
                }

                if (closureCreationCandidate != null && closureCreationCandidate.SourceContext.IsValid)
                    return currentIndex;
                
                indexForClosureCreationStatement++;
            }

            if (closureType != null && indexForClosureCreationStatement < firstBlock.Statements.Count)
            {
                // then there is a set of statements to add to the preamble block
                // up to and including "local := new ClosureClass();"
                for (int i = currentIndex; i <= indexForClosureCreationStatement; i++)
                {
                    if (firstBlock.Statements[i] == null) continue;

                    if (preambleBlock != null)
                    {
                        preambleBlock.Statements.Add(firstBlock.Statements[i]);
                    }

                    Local existingClosureLocal;
                    if (IsClosureCreation(m, firstBlock.Statements[i], out existingClosureLocal))
                    {
                        if (existingClosureLocal == null)
                        {
                            // introduce one
                            ExpressionStatement estmt = firstBlock.Statements[i] as ExpressionStatement;
                            if (estmt != null)
                            {
                                introducedClosureLocal = new Local(closureType);
                                contractInitializer.Add(
                                    new AssignmentStatement(introducedClosureLocal, (Expression) estmt.Expression.Clone()));
                            }
                            else
                            {
                                contractInitializer.Add((Statement) firstBlock.Statements[i].Clone());
                            }
                        }
                        else
                        {
                            contractInitializer.Add((Statement) firstBlock.Statements[i].Clone());
                        }
                    }
                    else
                    {
                        contractInitializer.Add((Statement) firstBlock.Statements[i].Clone());
                    }

                    if (preambleBlock != null)
                    {
                        firstBlock.Statements[i] = null;
                        // need to null them out so search below can be done starting at beginning of m's body
                    }
                }

                // Some number of assignment statements of the form "local.f := f;" where "f" is a parameter
                // that is captured by the closure.
                //
                // Roslyn generates code as follows:
                //   new Closure()
                //   dup
                //   ldarg f
                //   stfld f
                //   dup
                //   ldarg q
                //   stfld q
                //   dup...
                // 

                int endOfAssignmentsToClosureFields = indexForClosureCreationStatement + 1;
                for (; endOfAssignmentsToClosureFields < firstBlock.Statements.Count; endOfAssignmentsToClosureFields++)
                {
                    Statement s = firstBlock.Statements[endOfAssignmentsToClosureFields];
                    if (s == null) continue;

                    if (s.NodeType == NodeType.Nop) continue;
                    
                    if (s.SourceContext.IsValid) break; // end of closure
                    
                    if (s is Return) break; // Return is also an ExpressionStatement
                    
                    ExpressionStatement exprSt = s as ExpressionStatement;
                    if (exprSt != null && exprSt.Expression.NodeType == NodeType.Dup)
                    {
                        // dup of closure node
                        continue;
                    }

                    AssignmentStatement assign = s as AssignmentStatement;
                    if (assign == null) break;
                    
                    MemberBinding mb = assign.Target as MemberBinding;
                    
                    if (mb == null) break;
                    
                    if (mb.TargetObject == null ||
                        (mb.TargetObject.Type != closureType && mb.TargetObject.NodeType != NodeType.Pop)) break;
                }

                if (endOfAssignmentsToClosureFields - 1 < firstBlock.Statements.Count &&
                    endOfAssignmentsToClosureFields >= 1 &&
                    IsDup(firstBlock.Statements[endOfAssignmentsToClosureFields - 1]))
                {
                    endOfAssignmentsToClosureFields--; // last dup is not part of closure init
                }

                dupStackTracker = new StackDepthTracker(introducedClosureLocal);
                for (int i = indexForClosureCreationStatement + 1; i < endOfAssignmentsToClosureFields; i++)
                {
                    var stmt = firstBlock.Statements[i];
                    
                    if (stmt == null) continue;
                    
                    if (preambleBlock != null)
                    {
                        preambleBlock.Statements.Add(stmt);
                    }

                    if (stmt.NodeType != NodeType.Nop)
                    {
                        // don't add nop's to contract initializer
                        if (dupStackTracker.IsValid)
                        {
                            contractInitializer.Add(dupStackTracker.Visit(stmt));
                        }
                        else
                        {
                            contractInitializer.Add((Statement) stmt.Clone());
                        }
                    }

                    if (preambleBlock != null)
                    {
                        firstBlock.Statements[i] = null;
                        // need to null them out so search below can be done starting at beginning of m's body
                    }
                }

                currentIndex = endOfAssignmentsToClosureFields;
            }

            return currentIndex;
        }
 public ExtractionFinalizer(ContractNodes contractNodes)
 {
     this.contractNodes = contractNodes;
 }
Example #43
0
        public static MethodContract DuplicateContractAndClosureParts(Method targetMethod, Method sourceMethod,
            ContractNodes contractNodes, bool copyValidations)
        {
            Module targetModule = targetMethod.DeclaringType.DeclaringModule;

            var dup = new DuplicatorForContractsAndClosures(targetModule, sourceMethod, targetMethod, contractNodes);

            if (sourceMethod.Contract.AsyncEnsuresCount != 0)
            {
                // Removing the name lead to NRE for async method that uses Contract.Ensures(Contract.ForAll)
                // with a capturing lambda.
                // To preserve as much of backward compatible behavior as possible the fix will affect
                // only method contracts with async closures. It still possible that this fix will break existing code
                // and it is possible that there is no any issues by preserving name of the locals.
                // This fix could be enhanced in the future when this issue would be clear.
                dup.RemoveNameForLocals = false;
            }

            return DuplicateContractAndClosureParts(dup, targetMethod, sourceMethod, contractNodes, copyValidations);
        }
Example #44
0
        private StatementList GetContractClumpFromMoveNext(Method iteratorMethod, Method moveNext,
            ContractNodes contractNodes, StatementList contractInitializer, out SourceContext defaultSourceContext,
            ref HelperMethods.StackDepthTracker dupStackTracker,
            out AssumeBlock originalContractPosition)
        {
            Contract.Requires(moveNext != null);
            Contract.Requires(moveNext.Body != null);
            Contract.Requires(moveNext.Body.Statements != null);
            Contract.Requires(contractInitializer != null);
            Contract.Requires(iteratorMethod != null);

            var linkerVersion = 0;
            if (iteratorMethod.DeclaringType != null && iteratorMethod.DeclaringType.DeclaringModule != null)
            {
                linkerVersion = iteratorMethod.DeclaringType.DeclaringModule.LinkerMajorVersion;
            }

            var initialState = moveNext.IsAsync ? -1 : 0;
            moveNext.MoveNextStartState = initialState;
            originalContractPosition = null;
            int statementIndex;

            Contract.Assume(moveNext.Body != null);
            Contract.Assume(moveNext.Body.Statements != null);

            int blockIndex = ContractStartInMoveNext(this.contractNodes, moveNext, out statementIndex, iteratorMethod);

            Contract.Assert(statementIndex >= 0, "should follow from the postcondiiton");

            if (blockIndex < 0)
            {
                // Couldn't find state 0 in MoveNext method
                // This can happen if the iterator is trivial (like yield break; )
                defaultSourceContext = default(SourceContext);
                return null;
            }

            int beginning = blockIndex; // the block number in the body of movenext
            int sbeginning = statementIndex; // the statement no. in the beginnning block after the preamble
            int blast = -1;

            // the block number in the body of movenext, of the last block where there is a contract call
            int slast = -1; // the statement no. in the blast block

            // Next we move sbeginning past the preamble area
            sbeginning = MovePastPreamble(iteratorMethod, moveNext, beginning, sbeginning, contractInitializer,
                contractNodes, ref dupStackTracker);

            Contract.Assert(moveNext.Body != null, "should be provable");
            Contract.Assert(moveNext.Body.Statements != null, "should be provable");

            if (sbeginning < 0 ||
                !this.FindLastBlockWithContracts(moveNext.Body.Statements, beginning, out blast, out slast))
            {
                if (verbose)
                {
                    if (moveNext.Name != null)
                    {
                        Console.WriteLine("Method {0} doesnt have a contract method invocation at the right place.", moveNext.Name.Name);
                    }
                }

                defaultSourceContext = default(SourceContext);
                return null;
            }

            Block methodBody = moveNext.Body;
            Block lastBlock = methodBody.Statements[blast] as Block;
            SourceContext lastContractSourceContext;

            if (lastBlock != null)
            {
                lastContractSourceContext = lastBlock.SourceContext;
                // probably not a good context, what to do if one can't be found?
                if (lastBlock.Statements != null && 0 <= slast && slast < lastBlock.Statements.Count)
                {
                    if (lastBlock.Statements[slast] != null)
                    {
                        lastContractSourceContext = lastBlock.Statements[slast].SourceContext;
                    }
                }
            }
            else
            {
                lastContractSourceContext = default(SourceContext);
            }

            // TODO: check the clump is not in a try-catch block. 

            originalContractPosition = new AssumeBlock(new StatementList());
            StatementList result = HelperMethods.ExtractClump(
                moveNext.Body.Statements, beginning, sbeginning, blast,
                slast, assumeBlock: originalContractPosition);

            defaultSourceContext = lastContractSourceContext;
            return result;
        }
Example #45
0
 public static TypeNode IsContractTypeForSomeOtherTypeUnspecialized(TypeNode t, ContractNodes contractNodes)
 {
     TypeNode unspecializedType = GetTypeFromAttribute(t, ContractNodes.ContractClassForAttributeName);
     
     return unspecializedType;
 }
Example #46
0
        private static int MovePastPreamble([Pure] Method iteratorMethod, [Pure] Method moveNext, int beginning,
            int currentIndex, StatementList contractInitializer, ContractNodes contractNodes,
            ref HelperMethods.StackDepthTracker dupStackTracker)
        {
            Contract.Requires(moveNext != null);
            Contract.Requires(moveNext.Body != null);
            Contract.Requires(moveNext.Body.Statements != null);
            Contract.Requires(beginning >= 0);
            Contract.Requires(beginning < moveNext.Body.Statements.Count);
            Contract.Requires(currentIndex >= 0);
            Contract.Requires(contractInitializer != null);

            var state0Block = moveNext.Body.Statements[beginning] as Block;
            while (state0Block == null && beginning + 1 < moveNext.Body.Statements.Count)
            {
                state0Block = moveNext.Body.Statements[++beginning] as Block;
                if (state0Block != null && (state0Block.Statements == null || state0Block.Statements.Count == 0))
                {
                    // skip empty blocks
                    state0Block = null;
                }
            }

            if (state0Block == null) return -1;

            if (state0Block.Statements == null) return -1;

#if true
            TypeNode closureType;
            currentIndex = HelperMethods.MovePastClosureInit(iteratorMethod, state0Block, contractNodes,
                contractInitializer, null, currentIndex, ref dupStackTracker, out closureType);
#else
      int indexForClosureCreationStatement = currentIndex;
      TypeNode closureType = null;
      while (indexForClosureCreationStatement < state0Block.Statements.Count)
      {
        closureType = HelperMethods.IsClosureCreation(iteratorMethod, state0Block.Statements[indexForClosureCreationStatement]);
        if (closureType != null)
        {
          break;
        }
        indexForClosureCreationStatement++;
      }
      if (closureType != null && indexForClosureCreationStatement < state0Block.Statements.Count)
      { // then there is a set of statements to add to the preamble block
        // up to and including "this.<>local := new ClosureClass();"
        for (int i = currentIndex; i <= indexForClosureCreationStatement; i++)
        {
          // preambleBlock.Statements.Add(state0Block.Statements[i]);
          if (state0Block.Statements[i] == null) continue;
          contractInitializer.Add((Statement)state0Block.Statements[i].Clone());
          // state0Block.Statements[i] = null; 
        }
        // Some number of assignment statements of the form "this.local.f := f;" where "f" is a parameter
        // Or of the form local.f := f;
        // that is captured by the closure.
        int endOfAssignmentsToClosureFields = indexForClosureCreationStatement + 1;
        for (; endOfAssignmentsToClosureFields < state0Block.Statements.Count; endOfAssignmentsToClosureFields++)
        {
          Statement s = state0Block.Statements[endOfAssignmentsToClosureFields];
          if (s == null) continue;
          if (s.NodeType == NodeType.Nop) continue;
          AssignmentStatement assign = s as AssignmentStatement;
          if (assign == null) break;
          MemberBinding mb = assign.Target as MemberBinding;
          if (mb == null) break;
          if (mb.TargetObject == null) break;
          if (mb.TargetObject.Type != closureType) break;
        }
        for (int i = indexForClosureCreationStatement + 1; i < endOfAssignmentsToClosureFields; i++)
        {
          // preambleBlock.Statements.Add(state0Block.Statements[i]);
          if (state0Block.Statements[i] == null) continue;
          contractInitializer.Add((Statement)state0Block.Statements[i].Clone());
          // state0Block.Statements[i] = null; // need to null them out so search below can be done starting at beginning of m's body
        }
        currentIndex = endOfAssignmentsToClosureFields;
      }
#endif
            return currentIndex;
        }
Example #47
0
        /// <summary>
        /// Replaces any MemberBindings of the form (this,x) in the methodContract with a method call where the method
        /// being called is P where x is a private field of the source type that has been marked as [ContractPublicPropertyName("P")].
        /// </summary>
        /// <param name="targetType"></param>
        /// <param name="sourceType"></param>
        /// <param name="methodContract"></param>
        internal static void ReplacePrivateFieldsThatHavePublicProperties(TypeNode targetType,
          TypeNode sourceType,
          MethodContract methodContract,
          ContractNodes contractNodes
          )
        {
          Contract.Requires(sourceType != null);

            Dictionary<Field, Method> field2Getter = new Dictionary<Field, Method>();

            for (int i = 0, n = /*sourceType.Members == null ? 0 : */ sourceType.Members.Count; i < n; i++)
            {
                Field f = sourceType.Members[i] as Field;
                if (f == null) continue;
                string propertyName = HelperMethods.GetStringFromAttribute(f, ContractNodes.SpecPublicAttributeName);
                if (propertyName != null)
                {
                    Property p = sourceType.GetProperty(Identifier.For(propertyName));
                    if (p != null)
                    {
                        field2Getter.Add(f, p.Getter);
                    }
                }
            }
            if (0 < field2Getter.Count)
            {
                SubstitutePropertyGetterForField s = new SubstitutePropertyGetterForField(field2Getter);
                s.Visit(methodContract);
            }
            return;
        }
Example #48
0
        private static int ContractStartInMoveNext(ContractNodes contractNodes, Method moveNext, out int statementIndex,
            Method origMethod)
        {
            Contract.Requires(contractNodes != null);
            Contract.Requires(moveNext != null);
            Contract.Requires(moveNext.Body != null);
            Contract.Requires(moveNext.Body.Statements != null);
            Contract.Ensures(Contract.ValueAtReturn(out statementIndex) >= 0);
            Contract.Ensures(Contract.Result<int>() >= -1);
            Contract.Ensures(Contract.Result<int>() < moveNext.Body.Statements.Count);

            Block body = moveNext.Body;
            bool isAsync = moveNext.IsAsync;
            statementIndex = 0;
            var blocks = body.Statements;

            bool stateIsRead = false;

            var fieldScanner = new HelperMethods.ExpressionScanner((field, isStore) =>
            {
                if (isStore) return;
                if (field != null && field.Name != null && field.Name.Name.Contains("<>") &&
                    field.Name.Name.Contains("__state"))
                {
                    stateIsRead = true;
                }
            });

            fieldScanner.Visit(body.Statements);

            // Dictionary tracks local variable values and a bit saying if the value is the state (in that case it is 0).
            Dictionary<Variable, Pair<int, EvalKind>> env = new Dictionary<Variable, Pair<int, EvalKind>>();
            int currentBlockIndex = 0;
            bool seenFinalCompare = false;
            bool lastBranchNonConditional = false;

            while (currentBlockIndex >= 0 && currentBlockIndex < blocks.Count)
            {
                var block = blocks[currentBlockIndex] as Block;
                if (block == null || block.Statements == null) continue;

                for (int i = 0; i < block.Statements.Count; i++)
                {
                    var stmt = block.Statements[i];
                    if (stmt == null) continue;

                    if (contractNodes.IsContractOrValidatorOrAbbreviatorCall(stmt))
                    {
                        statementIndex = i;
                        return currentBlockIndex;
                    }

                    Branch branch = stmt as Branch;
                    if (branch != null)
                    {
                        if (branch.Condition == null)
                        {
                            currentBlockIndex = FindTargetBlock(blocks, branch.Target, currentBlockIndex);
                            lastBranchNonConditional = true;
                            goto OuterLoop;
                        }

                        var value = EvaluateExpression(branch.Condition, env, seenFinalCompare, isAsync);
                        if (value.Two == EvalKind.IsDisposingTest)
                        {
                            if (value.One != 0)
                            {
                                return FindTargetBlock(blocks, branch.Target, currentBlockIndex);
                            }
                            
                            if (i + 1 < block.Statements.Count)
                            {
                                statementIndex = i + 1;
                                return currentBlockIndex;
                            }
                            
                            if (currentBlockIndex + 1 < body.Statements.Count)
                            {
                                return currentBlockIndex + 1;
                            }

                            return -1;
                        }

                        if (seenFinalCompare)
                        {
                            // must be the end.
                            statementIndex = i;
                            return currentBlockIndex;
                        }

                        seenFinalCompare = (value.Two == EvalKind.IsFinalCompare || value.Two == EvalKind.IsStateValue);

                        if (value.One != 0)
                        {
                            currentBlockIndex = FindTargetBlock(blocks, branch.Target, currentBlockIndex);
                            goto OuterLoop;
                        }
                        
                        continue;
                    }

                    if (isAsync && lastBranchNonConditional)
                    {
                        // not a branch and last one was non-conditional
                        // must be the end.
                        statementIndex = i;
                        return currentBlockIndex;
                    }

                    var swtch = stmt as SwitchInstruction;
                    if (swtch != null)
                    {
                        if (seenFinalCompare)
                        {
                            // must be the end.
                            statementIndex = i;
                            return currentBlockIndex;
                        }

                        var value = EvaluateExpression(swtch.Expression, env, seenFinalCompare, isAsync);
                        if (value.One < 0 || swtch.Targets == null || value.One >= swtch.Targets.Count)
                        {
                            // fall through
                            if (isAsync)
                            {
                                seenFinalCompare = true;
                            }

                            continue;
                        }

                        currentBlockIndex = FindTargetBlock(blocks, swtch.Targets[value.One], currentBlockIndex);
                        // assume seen final compare
                        seenFinalCompare = true;
                        goto OuterLoop;
                    }

                    if (HelperMethods.IsClosureCreation(origMethod, stmt) != null)
                    {
                        // end of trace
                        statementIndex = i;
                        return currentBlockIndex;
                    }

                    AssignmentStatement assign = stmt as AssignmentStatement;
                    if (assign != null)
                    {
                        if (assign.Source is ConstructArray)
                        {
                            // treat as beginning of contract (typically a params array)
                            statementIndex = i;
                            return currentBlockIndex;
                        }

                        var value = EvaluateExpression(assign.Source, env, seenFinalCompare, isAsync);
                        if (IsThisDotState(assign.Target))
                        {
                            // end of trace
                            if (i + 1 < block.Statements.Count)
                            {
                                statementIndex = i + 1;
                                return currentBlockIndex;
                            }

                            if (currentBlockIndex + 1 < body.Statements.Count)
                            {
                                return currentBlockIndex + 1;
                            }

                            return -1;
                        }

                        if (IsDoFinallyBodies(assign.Target) && !stateIsRead)
                        {
                            // end of trace
                            if (i + 1 < block.Statements.Count)
                            {
                                statementIndex = i + 1;
                                return currentBlockIndex;
                            }

                            if (currentBlockIndex + 1 < body.Statements.Count)
                            {
                                return currentBlockIndex + 1;
                            }

                            return -1;
                        }

                        var target = assign.Target as Variable;
                        if (target != null) env[target] = value;
                        if (seenFinalCompare && !(value.Two == EvalKind.IsDisposingTest))
                        {
                            // must be the end.
                            statementIndex = i;
                            return currentBlockIndex;
                        }

                        continue;
                    }

                    if (seenFinalCompare)
                    {
                        // must be the end.
                        statementIndex = i;
                        return currentBlockIndex;
                    }

                    switch (stmt.NodeType)
                    {
                        case NodeType.Nop:
                        case NodeType.ExpressionStatement:
                            // skip: C# compiler emits funky pushes then pops
                            break;

                        default:
                            Contract.Assume(false, string.Format("Unexpected node type '{0}'", stmt.NodeType));
                            return -1;
                    }
                }

                // next block in body
                currentBlockIndex++;
                OuterLoop:
                ;
            }

            return -1;
        }
Example #49
0
        // Public API

        /// <summary>
        /// Modifies <paramref name="assembly"/> by extracting any Code Contracts
        /// from the method bodies in the assembly.
        /// <param name="assembly">
        /// The assembly to which the contracts will be added (i.e., the AST for the assembly
        /// will be enriched with method contracts and object invariants).
        /// </param>
        /// <param name="referenceAssembly">
        /// When not null, then the contracts are extracted from this assembly and then copied over
        /// to <paramref name="assembly"/>. Note that in that case, no contracts are extracted
        /// directly from <paramref name="assembly"/>: all of the contracts in <paramref name="assembly"/>
        /// after this method returns came from this assembly.
        /// </param>
        /// <param name="contracts">
        /// When not null, this will be used for the definitions of the contract methods (and
        /// attributes) in <paramref name="assembly"/> (or <paramref name="referenceAssembly"/>, if that
        /// is not null). When null, then we will make an effort to find the contract methods. In
        /// either case, the definitions might be found within <paramref name="assembly"/> (or
        /// <paramref name="referenceAssembly"/>) anyway.
        /// </param>
        /// <param name="targetContractNodes">
        /// This parameter is used for the definitions of the contract methods (and
        /// attributes) that are the definitions that are embedded within the contracts,
        /// e.g., the definition of the ForAll method are found in the return value.
        /// It may be the same as <paramref name="contracts"/>. If it is passed in as null,
        /// then it will be filled in with the nodes used by the Extractor.
        /// </param>
        /// <param name="useClousotExtractor">
        /// When true, use a "Clousot" extractor, which does some extra processing needed for static
        /// analysis.
        /// </param>
        /// <returns>
        /// True iff extraction was possible. (I.e., a set of contractNodes was found to use for
        /// the extraction --- it does *not* guarantee that any contracts were found in the assembly.)
        /// </returns>
        /// </summary>
        ///
        public static bool ExtractContracts(AssemblyNode /*!*/ assembly,
                                            AssemblyNode /*?*/ referenceAssembly,
                                            ContractNodes /*?*/ contracts,
                                            ContractNodes /*?*/ backupContracts,
                                            ContractNodes /*?*/ targetContractNodes,
                                            out ContractNodes /*?*/ contractNodesUsedToExtract,
                                            Action <CompilerError> /*?*/ errorHandler,
                                            bool useClousotExtractor)
        {
            Contract.Requires(assembly != null);

            AssemblyNode assemblyToVisit = referenceAssembly ?? assembly;

            // Try to use supplied contracts, if present. But don't just try extracting and somehow
            // figuring out if any contracts had been present. Instead, see if:
            //   a) the contract methods are defined in the assembly we are extracting from, or
            //   b) the assembly reference microsoft.contracts.dll (the backup contracts and we found that assembly)
            //   c) the assembly we are extracting from has an external reference to the assembly
            //      the supplied contract methods came from.
            //   d) the contracts found in mscorlib
            //

            // see if the assembly references the backup contracts (Microsoft.Contracts.dll)
            contractNodesUsedToExtract = IdentifyContractAssemblyIfReferenced(backupContracts, assemblyToVisit);

            // see if assembly defines the contracts itself
            if (contractNodesUsedToExtract == null)
            {
                contractNodesUsedToExtract = ContractNodes.GetContractNodes(assemblyToVisit, errorHandler);
            }

            // see if the assembly references the supplied contract assembly
            if (contractNodesUsedToExtract == null)
            {
                contractNodesUsedToExtract = IdentifyContractAssemblyIfReferenced(contracts, assemblyToVisit);
            }

            // see if the contracts are in the system assembly
            if (contractNodesUsedToExtract == null && assemblyToVisit != SystemTypes.SystemAssembly)
            {
                contractNodesUsedToExtract = ContractNodes.GetContractNodes(SystemTypes.SystemAssembly, errorHandler);
            }

            if (contractNodesUsedToExtract == null)
            {
                return(false);
            }

            var fSharp = false;

            // TODO: Thread the program options through here somehow and let this be specified as an option
            Contract.Assume(assemblyToVisit.Attributes != null);
            foreach (var attr in assemblyToVisit.Attributes)
            {
                Contract.Assume(attr != null);
                Contract.Assume(attr.Type != null);
                Contract.Assume(attr.Type.Name != null);
                Contract.Assume(attr.Type.Name.Name != null);

                if (attr.Type.Name.Name.Contains("FSharpInterfaceDataVersionAttribute"))
                {
                    fSharp = true;
                    break;
                }
            }

            var ultimateTarget = (referenceAssembly != null) ? assembly : null;

            Contract.Assert(assembly != null);

            ExtractorVisitor ev = useClousotExtractor
                ? new ClousotExtractor(contractNodesUsedToExtract, ultimateTarget, assembly, errorHandler)
                : new ExtractorVisitor(contractNodesUsedToExtract, ultimateTarget, assembly, false, fSharp);

            ev.Visit(assemblyToVisit);

            if (!useClousotExtractor)
            {
                FilterForRuntime eoar = new FilterForRuntime(contractNodesUsedToExtract, targetContractNodes);
                assemblyToVisit = eoar.TransformForTarget(assemblyToVisit);
            }

            if (referenceAssembly != null)
            {
                CopyOutOfBandContracts coob = new CopyOutOfBandContracts(assembly, referenceAssembly,
                                                                         contractNodesUsedToExtract, targetContractNodes);
                coob.VisitAssembly(referenceAssembly);
            }

            return(true);
        }
Example #50
0
        // Constructors

        /// <summary>
        /// 
        /// </summary>
        /// <param name="contractNodes"></param>
        /// <param name="targetContractNodes"></param>
        /// <param name="ultimateTargetAssembly">specify X if extracting from X.Contracts.dll, otherwise null</param>
        public ExtractorVisitor(ContractNodes /*!*/ contractNodes, AssemblyNode ultimateTargetAssembly, AssemblyNode realAssembly)
            : this(contractNodes, ultimateTargetAssembly, realAssembly, false, false)
        {
            Contract.Requires(contractNodes != null);
            Contract.Requires(realAssembly != null);
        }
 public MethodBodyChecker(Action<CompilerError> handleError, ContractNodes usedToExtract)
     : base(handleError, usedToExtract)
 {
     // F:
     Contract.Requires(handleError != null);
     Contract.Requires(usedToExtract != null);
 }
 public ForwardingDuplicator(Module /*!*/ module, TypeNode type, ContractNodes contractNodes,
                             ContractNodes targetContractNodes) : base(module, type)
 {
     this.contractNodes       = contractNodes;
     this.targetContractNodes = targetContractNodes;
 }
            public VisibilityChecker(Action<CompilerError> errorHandler, ContractNodes usedToExtract)
            {
                Contract.Requires(errorHandler != null);

                this.errorHandler = errorHandler;
                this.contractNodes = usedToExtract;
            }
Example #54
0
 public Decompiler(ContractNodes cns)
 {
     this.contractNodes = cns;
 }
        public PostExtractorChecker(
            ContractNodes usedToExtract,
            Action<System.CodeDom.Compiler.CompilerError> errorHandler,
            bool allowPreconditionsInOverrides, bool fSharp, bool explicitUserValidations,
            bool addInterfaceWrappersWhenNeeded, int runtimeCheckingLevel)
        {
            Contract.Requires(errorHandler != null);
            Contract.Requires(usedToExtract != null);

            this.m_errorHandler = errorHandler;
            this.allowPreconditionsInOverrides = allowPreconditionsInOverrides;
            this.explicitUserValidations = explicitUserValidations;
            this.addInterfaceWrappersWhenNeeded = addInterfaceWrappersWhenNeeded;
            this.runtimeCheckingLevel = runtimeCheckingLevel;

            this.purityChecker = new PurityChecker(this.HandleError, fSharp, usedToExtract);
            this.preconditionChecker = new PreconditionChecker(this.HandleError, usedToExtract);
            this.postconditionChecker = new PostconditionChecker(this.HandleError, fSharp);
            this.invariantCallChecker = new CheckForCallsToInvariantMethods(this);
            this.methodBodyChecker = new MethodBodyChecker(this.HandleError, usedToExtract);
            this.invariantChecker = new InvariantChecker(this.HandleError, usedToExtract);
            this.contractNodes = usedToExtract;
            this.visibilityChecker = new VisibilityChecker(this.HandleError, usedToExtract);
            this.invariantMethods = new TrivialHashtable(0);
        }
Example #56
0
 public FilterForRuntime(ContractNodes contractNodes, ContractNodes targetContractNodes)
 {
     this.contractNodes       = contractNodes;
     this.targetContractNodes = targetContractNodes;
 }