public Warning(int errorCode, string error, SourceContext context) : base(errorCode, error, context) { // F: Contract.Requires(error != null); this.IsWarning = true; }
public override void VisitStatementList(StatementList statements) { if (statements == null) return; for (int i = 0; i < statements.Count; i++) { var stmt = statements[i]; if (stmt == null) continue; if (stmt.SourceContext.IsValid) { this.currentSourceContext = stmt.SourceContext; } this.Visit(stmt); } }
public override Compilation GetDummyCompilationFor(string fileName){ if (this.dummyCompilationFor == null) this.dummyCompilationFor = new Hashtable(); WeakReference wref = (WeakReference)this.dummyCompilationFor[fileName]; if (wref != null && wref.IsAlive) return (Compilation)wref.Target; string fContents = null; if (File.Exists(fileName)){ StreamReader sr = new StreamReader(fileName); fContents = sr.ReadToEnd(); sr.Close(); } Compilation compilation = new Compilation(); compilation.CompilerParameters = this.GetDummyCompilerParameters(); compilation.TargetModule = new Module(); DocumentText docText = new DocumentText(new StringSourceText(fContents, true)); SourceContext sctx = new SourceContext(Compiler.CreateSpecSharpDocument(fileName, 0, docText)); compilation.CompilationUnits = new CompilationUnitList(new CompilationUnitSnippet(new Identifier(fileName), new ParserFactory(), sctx)); compilation.CompilationUnits[0].Compilation = compilation; this.dummyCompilationFor[fileName] = new WeakReference(compilation); return compilation; }
public Error(int errorCode, string error, SourceContext context) { Contract.Requires(error != null); if (context.IsValid) { // F: Why context.Document != null? Added the assumption Contract.Assume(context.Document != null); this.FileName = context.Document.Name; } else { this.FileName = " "; // non-empty to prevent VS/msbuild from prepending EXEC } this.Line = context.StartLine; this.Column = context.StartColumn; this.ErrorNumber = "CC" + errorCode; this.ErrorText = error; }
//public override Block VisitBlock(Block block) { // if(block.Statements != null && block.Statements.Count == 1) { // Return r = block.Statements[0] as Return; // if(r != null) { // Statement s = this.VisitReturn(r); // Block retBlock = s as Block; // if(retBlock != null) { // block.Statements = retBlock.Statements; // return block; // } else { // return base.VisitBlock(block); // } // } else { // return base.VisitBlock(block); // } // } else { // return base.VisitBlock(block); // } //} public override Statement VisitReturn(Return Return) { if (Return == null) { return null; } returnCount++; this.lastReturnSourceContext = Return.SourceContext; StatementList stmts = new StatementList(); Return.Expression = this.VisitExpression(Return.Expression); if (Return.Expression != null) { MethodCall mc = Return.Expression as MethodCall; if (mc != null && mc.IsTailCall) { mc.IsTailCall = false; } var assgnmt = new AssignmentStatement(result, Return.Expression); assgnmt.SourceContext = Return.SourceContext; stmts.Add(assgnmt); } // the branch is a "leave" out of the try block that the body will be // in. var branch = new Branch(null, newExit, false, false, this.leaveExceptionBody); branch.SourceContext = Return.SourceContext; stmts.Add(branch); return new Block(stmts); }
private void CopyValidatorContracts(Method targetMethod, Method validatorMethodInstance, Expression targetObject, ExpressionList actuals, RequiresList Preconditions, SourceContext useSite, Block validatorPrefix) { // make sure to have extracted contracts from the validator method prior if (validatorMethodInstance.DeclaringType.DeclaringModule == targetMethod.DeclaringType.DeclaringModule) { var validatorMethod = validatorMethodInstance; while (validatorMethod.Template != null) { validatorMethod = validatorMethod.Template; } this.VisitMethod(validatorMethod); } if (validatorMethodInstance.Contract == null) return; var copier = new AbbreviationDuplicator(validatorMethodInstance, targetMethod, this.contractNodes, validatorMethodInstance, targetObject, actuals); var validatorContract = HelperMethods.DuplicateContractAndClosureParts(copier, targetMethod, validatorMethodInstance, this.contractNodes, false); if (validatorContract == null) return; MoveValidatorRequires(targetMethod, validatorContract.Requires, Preconditions, useSite, validatorContract.ContractInitializer, validatorPrefix); }
private void ExtractContractsForMethod(Method method, object dummy) { Contract.Requires(method != null); RequiresList preconditions = null; EnsuresList postconditions = null; RequiresList validations = null; EnsuresList modelPostconditions = null; //Console.WriteLine("Extracting contract for method {0}", method.FullName); // set its contract so pure is properly handled. var methodContract = method.Contract = new MethodContract(method); try { if (method.IsAbstract /* && contractClass == null */) { // Abstract methods cannot have a body, so nothing to extract return; } TypeNode /*?*/ closure = null; bool possiblyAsync; if (IsIteratorOrAsyncMethodCandidate(method, out possiblyAsync)) { closure = FindClosureClass(method); if (closure != null) { this.ProcessClosureClass(method, closure, possiblyAsync); return; } } if (method.Body == null || method.Body.Statements == null) return; // Find first source context, use it if no better one is found on errors // if (method.Body != null && method.Body.Statements != null) { if (this.verbose) { Console.WriteLine(method.FullName); } bool found = false; for (int i = 0, n = method.Body.Statements.Count; i < n && !found; i++) { Block b = method.Body.Statements[i] as Block; if (b != null) { for (int j2 = 0, m = b.Statements == null ? 0 : b.Statements.Count; j2 < m; j2++) { Contract.Assert(m == b.Statements.Count, "loop invariant not inferred"); Statement s = b.Statements[j2]; if (s != null) { SourceContext sctx = s.SourceContext; if (sctx.IsValid) { found = true; // s.SourceContext = new SourceContext(); // wipe out the source context because this statement will no longer be the first one in the method body if there are any contract calls this.currentMethodSourceContext = sctx; if (this.verbose) { Console.WriteLine("block {0}, statement {1}: ({2},{3})", i, j2, sctx.StartLine, sctx.StartColumn); } break; } } } } } } Block contractInitializerBlock = new Block(new StatementList()); Block postPreamble = null; HelperMethods.StackDepthTracker dupStackTracker = new HelperMethods.StackDepthTracker(); var contractLocalAliasingThis = HelperMethods.ExtractPreamble(method, this.contractNodes, contractInitializerBlock, out postPreamble, ref dupStackTracker, this.isVB); bool saveErrorFound = this.errorFound; this.errorFound = false; // Extract pre- and postconditions if (method.Body != null && method.Body.Statements != null) { this.CheapAndDirty(method, ref preconditions, ref postconditions, ref validations, ref modelPostconditions, contractInitializerBlock, ref dupStackTracker); if (this.errorFound) { method.ClearBody(); this.errorFound = saveErrorFound; return; } this.errorFound = saveErrorFound; } // Sanitize contract by renaming local aliasing "this" to This if (contractLocalAliasingThis != null && method.ThisParameter != null) { var renamer = new ContractLocalToThis(contractLocalAliasingThis, method.ThisParameter); renamer.Visit(preconditions); renamer.Visit(postconditions); renamer.Visit(modelPostconditions); } // Split out async ensures var asyncPostconditions = SplitAsyncEnsures(ref postconditions, method); // Store contracts into the appropriate slots Contract.Assume(methodContract.RequiresCount == 0); Contract.Assume(methodContract.EnsuresCount == 0); Contract.Assume(methodContract.ModelEnsuresCount == 0); methodContract.ContractInitializer = contractInitializerBlock; methodContract.PostPreamble = postPreamble; methodContract.Requires = preconditions; methodContract.Ensures = postconditions; methodContract.AsyncEnsures = asyncPostconditions; methodContract.ModelEnsures = modelPostconditions; methodContract.Validations = validations; return; } catch (NotImplementedException ni) { // indicates a problem this.HandleError(method, 1099, "Contract extraction failed: " + ni.Message, default(SourceContext)); } finally { // normalize contract by forcing IsPure to look at attributes and removing contract it is empty var isPure = methodContract.IsPure; if (!isPure && methodContract.RequiresCount == 0 && methodContract.EnsuresCount == 0 && methodContract.ModelEnsuresCount == 0 && methodContract.AsyncEnsuresCount == 0 && methodContract.ValidationsCount == 0) { method.Contract = null; } else { // turn helper method calls to Result, OldValue, ValueAtReturn into proper AST nodes. this.extractionFinalizer.VisitMethodContract(methodContract); } } }
private bool ExtractFromClump(StatementList contractClump, Method method, GatherLocals gatherLocals, RequiresList Preconditions, EnsuresList Postconditions, RequiresList validations, EnsuresList modelPostconditions, SourceContext defaultContext, Method originalMethod, Block contractInitializer, ref HelperMethods.StackDepthTracker dupStackTracker) { // set the state so that the contract clump is used for extraction (as opposed to the method body as it used to) StatementList stmts = contractClump; int beginning = 0; int n = stmts.Count; int seginning = HelperMethods.FindNextRealStatement(((Block) stmts[beginning]).Statements, 0); bool endContractFound = false; bool postConditionFound = false; SourceContext currentSourceContext; for (int i = beginning; i < n; i++) { Block b = (Block) stmts[i]; if (b == null) continue; for (int j = 0, m = b.Statements == null ? 0 : b.Statements.Count; j < m; j++) { if (dupStackTracker.IsValid && dupStackTracker.Depth >= 0) { b.Statements[j] = dupStackTracker.Visit(b.Statements[j]); } Statement s = b.Statements[j]; if (s == null) continue; Block currentClump; Throw t = null; t = s as Throw; Method calledMethod = HelperMethods.IsMethodCall(s); if ((t != null || (calledMethod != null && calledMethod.DeclaringType != null && calledMethod.DeclaringType != this.contractNodes.ContractClass && HelperMethods.IsVoidType(calledMethod.ReturnType) && !this.contractNodes.IsContractOrValidatorOrAbbreviatorMethod(calledMethod)))) { // Treat throw statements as (part of) a precondition // don't accept "throw ..." unless it comes in the "precondition section" // then treat the current clump as a precondition, but need to massage it a bit: // all branches to the block just after the throw should be modified to be branches to // a new manufactured block that sets a fresh local to "true". The // throw itself should be changed to set the same local to "false". That way the // clump can be treated as the value of precondition (because the branch polarity has // already been negated as part of the code gen). // This test was supposed to be a sanity check that the current block contained // only "throw ..." or else "nop; throw ...". But I've also seen "ThrowHelper.Throw(...); nop", // so I'm just going to comment this out for now. //if (!((m == 1 && j == 0) || (m == 2 && j == 1))) { // Preconditions = new RequiresList(); // Postconditions = new EnsuresList(); // return; // throw new ExtractorException(); //} Expression exception; // The clump being extracted may contain code/blocks that represent (part of) // the expression that is being thrown (if the original throw expression had // control flow in it from boolean expressions and/or ternary expressions). b.Statements[j] = null; // wipe out throw statement currentClump = new Block(HelperMethods.ExtractClump(stmts, beginning, seginning, i, j)); int currentClumpLength = i - beginning + 1; // there better be a next block because that must have been the target for all of the branches // that didn't cause the throw to happen if (!(i < n - 1)) { this.HandleError(method, 1027, "Malformed contract.", s.SourceContext); return false; } Block nextBlock = (Block) stmts[i + 1]; // cast succeeds because body is clump Local valueOfPrecondition = new Local(Identifier.For("_preConditionHolds"), SystemTypes.Boolean); Block preconditionHolds = new Block(new StatementList(new AssignmentStatement(valueOfPrecondition, Literal.True))); ReplaceBranchTarget rbt = new ReplaceBranchTarget(nextBlock, preconditionHolds); rbt.VisitBlock(currentClump); int ILOffset; CountPopExpressions cpe = new CountPopExpressions(); currentSourceContext = s.SourceContext; cpe.Visit(s); if (0 < cpe.PopOccurrences) { // then there is a set of blocks that represent the exception: the Reader // was not able to decompile it back into an expression. Extract the set // from the current clump and make it into a block expression // Find the last block that has a branch to "preconditionHolds". After that are all of the blocks // that represent the evaluation of the exception int branchBlockIndex = currentClumpLength - 2; // can't be the current block: that has the throw in it while (0 <= branchBlockIndex) { Block possibleBranchBlock = currentClump.Statements[branchBlockIndex] as Block; Branch br = possibleBranchBlock.Statements[possibleBranchBlock.Statements.Count - 1] as Branch; if (br != null && br.Target == preconditionHolds) { break; } branchBlockIndex--; } if (branchBlockIndex < 0) { this.HandleError(method, 1028, "Malformed exception constructor in contract.", defaultContext); return false; } Block exceptionBlock = new Block(HelperMethods.ExtractClump(currentClump.Statements, branchBlockIndex + 1, 0, currentClumpLength - 1, ((Block) currentClump.Statements[currentClumpLength - 1]).Statements.Count - 1)); exceptionBlock.Statements.Add(new ExpressionStatement(t.Expression)); SourceContext sctx = ((Block) exceptionBlock.Statements[0]).Statements[0].SourceContext; if (sctx.IsValid) { currentSourceContext = sctx; } else { SourceContext tmp; bool foundContext = HelperMethods.GetLastSourceContext(exceptionBlock.Statements, out tmp); if (foundContext) currentSourceContext = tmp; } if (!CheckClump(method, gatherLocals, currentSourceContext, exceptionBlock)) return false; exception = new BlockExpression(exceptionBlock, SystemTypes.Exception); ILOffset = t.ILOffset; } else { currentSourceContext = s.SourceContext; if (t != null) { // then the statement is "throw ..." exception = t.Expression; ILOffset = t.ILOffset; } else { ExpressionStatement throwHelperCall = s as ExpressionStatement; Debug.Assert(throwHelperCall != null); exception = throwHelperCall.Expression; ILOffset = s.ILOffset; } exception.SourceContext = currentSourceContext; SourceContext tmp; bool foundContext = HelperMethods.GetLastSourceContext(currentClump.Statements, out tmp); if (foundContext) currentSourceContext = tmp; } Block returnValueOfPrecondition = new Block(new StatementList(new ExpressionStatement(valueOfPrecondition))); Statement extraAssumeFalse = this.ExtraAssumeFalseOnThrow(); Block preconditionFails = new Block(new StatementList(new AssignmentStatement(valueOfPrecondition, Literal.False), extraAssumeFalse, new Branch(null, returnValueOfPrecondition, true, false, false))); //Block preconditionFails = new Block(new StatementList(new AssignmentStatement(valueOfPrecondition, Literal.False), new Branch(null, returnValueOfPrecondition, true, false, false))); currentClump.Statements.Add(preconditionFails); // replace throw statement currentClump.Statements.Add(preconditionHolds); currentClump.Statements.Add(returnValueOfPrecondition); if (!CheckClump(originalMethod, gatherLocals, currentSourceContext, currentClump)) return false; BlockExpression be = new BlockExpression(currentClump, SystemTypes.Boolean); be.SourceContext = currentSourceContext; var ro = new RequiresOtherwise(be, exception); ro.ILOffset = ILOffset; ro.SourceContext = currentSourceContext; if (postConditionFound) { HandleError(originalMethod, 1013, "Precondition found after postcondition.", currentSourceContext); return false; } validations.Add(ro); var req = new RequiresPlain(be, FindExceptionThrown.Find(exception)); req.IsFromValidation = true; req.ILOffset = ro.ILOffset; req.SourceContext = ro.SourceContext; Preconditions.Add(req); } else { if (contractNodes.IsContractMethod(calledMethod)) { // Treat calls to contract methods if (endContractFound) { HandleError(originalMethod, 1012, "Contract call found after prior EndContractBlock.", s.SourceContext); break; } if (contractNodes.IsEndContract(calledMethod)) { endContractFound = true; continue; } MethodCall mc = ((ExpressionStatement) s).Expression as MethodCall; Expression arg = mc.Operands[0]; arg.SourceContext = s.SourceContext; MethodContractElement mce; currentSourceContext = s.SourceContext; Expression condition; if (beginning == i && seginning == j) { // Deal with the simple case: the reader decompiled the call into a single statement condition = arg; } else { b.Statements[j] = new ExpressionStatement(arg); // construct a clump from // methodBody.Statements[beginning].Statements[seginning] to // methodBody.Statements[i].Statements[j] currentClump = new Block(HelperMethods.ExtractClump(stmts, beginning, seginning, i, j)); if (!currentSourceContext.IsValid) { // then a good source context has not been found yet. Grovel around in the clump // to see if there is a better one SourceContext sctx; if (HelperMethods.FindContext(currentClump, currentSourceContext, out sctx)) currentSourceContext = sctx; } if (!CheckClump(originalMethod, gatherLocals, currentSourceContext, currentClump)) return false; BlockExpression be = new BlockExpression(currentClump); condition = be; } condition.SourceContext = currentSourceContext; if (contractNodes.IsPlainPrecondition(calledMethod)) { var req = new RequiresPlain(condition); contractNodes.IsRequiresWithException(calledMethod, out req.ExceptionType); mce = req; } else if (this.contractNodes.IsPostcondition(calledMethod)) { mce = new EnsuresNormal(condition); } else if (contractNodes.IsExceptionalPostcondition(calledMethod)) { EnsuresExceptional ee = new EnsuresExceptional(condition); // Extract the type of exception. ee.Type = calledMethod.TemplateArguments[0]; mce = ee; } else { throw new InvalidOperationException("Cannot recognize contract method"); } mce.SourceContext = currentSourceContext; mce.ILOffset = mc.ILOffset; if (1 < mc.Operands.Count) { var candidate = SanitizeUserMessage(method, mc.Operands[1], currentSourceContext); mce.UserMessage = candidate; } if (2 < mc.Operands.Count) { Literal lit = mc.Operands[2] as Literal; if (lit != null) { mce.SourceConditionText = lit; } } // determine Model status mce.UsesModels = CodeInspector.UsesModel(mce.Assertion, this.contractNodes); // Check context rules switch (mce.NodeType) { case NodeType.RequiresPlain: if (postConditionFound) { this.HandleError(originalMethod, 1014, "Precondition found after postcondition.", currentSourceContext); return false; } if (mce.UsesModels) { this.HandleError(originalMethod, 1073, "Preconditions may not refer to model members.", currentSourceContext); return false; } var rp = (RequiresPlain) mce; Preconditions.Add(rp); validations.Add(rp); // also add to the internal validation list break; // TODO: check visibility of post conditions based on visibility of possible implementation case NodeType.EnsuresNormal: case NodeType.EnsuresExceptional: Ensures ensures = (Ensures) mce; if (mce.UsesModels) { if (this.IncludeModels) { modelPostconditions.Add(ensures); } } else { Postconditions.Add(ensures); } postConditionFound = true; break; } } else if (ContractNodes.IsValidatorMethod(calledMethod)) { // Treat calls to Contract validators if (endContractFound) { this.HandleError(originalMethod, 1012, "Contract call found after prior EndContractBlock.", s.SourceContext); break; } MethodCall mc = ((ExpressionStatement) s).Expression as MethodCall; var memberBinding = (MemberBinding) mc.Callee; currentSourceContext = s.SourceContext; Statement validation; Block validationPrefix; if (beginning == i && seginning == j) { // Deal with the simple case: the reader decompiled the call into a single statement validation = s; validationPrefix = null; } else { // The clump may contain multiple statements ending in the validator call. // to extract the code as Requires<E>, we need to keep the statements preceeding // the validator call, as they may contain local initialization etc. These should go // into the first Requires<E> that the validator expands to. This way, if there are // no Requires<E> expanded from the validator, then the statements can be omitted. // At the same time, the statements won't be duplicated when validations are emitted. // // If the validator call contains any pops, then the extraction must fail saying it // is too complicated. // must null out statement with call before extract clump b.Statements[j] = null; // we have a copy in mc, s validationPrefix = new Block(HelperMethods.ExtractClump(stmts, beginning, seginning, i, j)); if (!currentSourceContext.IsValid) { // then a good source context has not been found yet. Grovel around in the clump // to see if there is a better one SourceContext sctx; if (HelperMethods.FindContext(validationPrefix, currentSourceContext, out sctx)) currentSourceContext = sctx; } if (CountPopExpressions.Count(mc) > 0) { this.HandleError(method, 1071, "Arguments to contract validator call are too complicated. Please simplify.", currentSourceContext); return false; } if (!CheckClump(originalMethod, gatherLocals, currentSourceContext, validationPrefix)) return false; validation = new Block(new StatementList(validationPrefix, s)); validation.SourceContext = currentSourceContext; } var ro = new RequiresOtherwise(null, new BlockExpression(new Block(new StatementList(validation)))); validations.Add(ro); CopyValidatorContracts( method, calledMethod, memberBinding.TargetObject, mc.Operands, Preconditions, currentSourceContext, validationPrefix); } else if (ContractNodes.IsAbbreviatorMethod(calledMethod)) { // Treat calls to Contract abbreviators if (endContractFound) { this.HandleError(originalMethod, 1012, "Contract call found after prior EndContractBlock.", s.SourceContext); break; } MethodCall mc = ((ExpressionStatement) s).Expression as MethodCall; var memberBinding = (MemberBinding) mc.Callee; currentSourceContext = s.SourceContext; if (beginning == i && seginning == j) { // Deal with the simple case: the reader decompiled the call into a single statement // nothing to do. All is in the call and its arguments } else { // The clump may contain multiple statements ending in the abbreviator call. // We need to keep the statements preceeding the abbreviator call and add them to the // contract initializer block. The reason we cannot add them to the first expansion contract // of the abbreviator is that the abbreviator may give rise to closure initialization which will // be hoisted into the closure initializer block. This closure initializer may refer to the // locals initialized by the present statement sequence, so it must precede it. // // If the abbreviator call contains any pops, then the extraction must fail saying it // is too complicated. // grab prefix of clump minus last call statement. // must null out current call statement before we extract clump (ow. it stays in body) b.Statements[j] = null; currentClump = new Block(HelperMethods.ExtractClump(stmts, beginning, seginning, i, j)); if (!currentSourceContext.IsValid) { // then a good source context has not been found yet. Grovel around in the clump // to see if there is a better one SourceContext sctx; if (HelperMethods.FindContext(currentClump, currentSourceContext, out sctx)) currentSourceContext = sctx; } if (CountPopExpressions.Count(mc) > 0) { this.HandleError(method, 1070, "Arguments to contract abbreviator call are too complicated. Please simplify.", currentSourceContext); return false; } if (!CheckClump(originalMethod, gatherLocals, currentSourceContext, currentClump)) return false; if (HelperMethods.IsNonTrivial(currentClump)) { contractInitializer.Statements.Add(currentClump); } } CopyAbbreviatorContracts(method, calledMethod, memberBinding.TargetObject, mc.Operands, Preconditions, Postconditions, currentSourceContext, validations, contractInitializer); } else { // important to continue here and accumulate blocks/statements for next contract! if (i == beginning && j == seginning && s.NodeType == NodeType.Nop) { // nop following contract is often associated with previous code, so skip it seginning = j + 1; } continue; } } // Re-initialize current state after contract has been found beginning = i; seginning = j + 1; //seginning = HelperMethods.FindNextRealStatement(((Block)stmts[i]).Statements, j + 1); if (seginning < 0) seginning = 0; //b = (Block)stmts[i]; // IMPORTANT! Need this to keep "b" in sync } } if (this.verbose) { Console.WriteLine("\tNumber of Preconditions: " + Preconditions.Count); Console.WriteLine("\tNumber of Postconditions: " + Postconditions.Count); } return true; }
public void HandleError(Method method, int errorCode, string s, SourceContext context) { if (context.IsValid) { CallErrorFound(new Error(errorCode, s, context)); } else { CallErrorFound(new Error(errorCode, string.Format("{0}: In method {1}, assembly {2}", s, method.FullName, method.DeclaringType.DeclaringModule.Location), context)); } }
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; }
public void CheckInvariants(TypeNode t, InvariantList invariants) { Contract.Requires(invariants != null); this.assignmentFound = false; foreach (var i in invariants) { if (i == null) continue; this.lastSourceContext = i.SourceContext; this.CurrentMethod = i; this.Visit(i); Contract.Assume(this.CurrentMethod != null); if (this.assignmentFound) { this.errorHandler( new Error(1003, "Malformed contract. Found Invariant after assignment in method '" + this.CurrentMethod.FullName + "'.", i.SourceContext)); break; } } }
public override void StartTemplateParameters(System.Compiler.SourceContext context) { this.vsAuthoringSink.StartTemplateParameters(new SourceContext(context)); }
private bool ParseStatement(Block/*!*/ block) { //parse instructions and put in expression tree until an assignment, void call, branch target, or branch is encountered StatementList statementList = block.Statements; Expression expr = null; Statement statement = null; bool transferStatement = false; int startingAddress = 0; #if !FxCop SourceContext sourceContext = new SourceContext(); sourceContext.StartPos = this.counter; #endif #if !ROTOR if (this.method.contextForOffset != null){ object sctx = this.method.contextForOffset[this.counter+1]; if (sctx != null) sourceContext = (SourceContext)sctx; } #endif while (true){ bool isStatement = false; startingAddress = this.counter+1; //Add one so that it is never zero (the latter means no entry to the TrivialHashtable) #if FxCop || ILOFFSETS this.ilOffset = this.counter; this.opCode = this.GetOpCode(); #else OpCode opCode = this.GetOpCode(); #endif #if FxCop if (this.handlerMap.TryGetValue(this.ilOffset, out expr)){ expr.sourceContext = sourceContext; expr.ILOffset = this.ilOffset; this.operandStack.Push(expr); } #endif switch (opCode){ case OpCode.Nop: statement = new Statement(NodeType.Nop); goto done; case OpCode.Break: statement = new Statement(NodeType.DebugBreak); goto done; case OpCode.Ldarg_0: expr = this.Parameters(0); break; case OpCode.Ldarg_1: expr = this.Parameters(1); break; case OpCode.Ldarg_2: expr = this.Parameters(2); break; case OpCode.Ldarg_3: expr = this.Parameters(3); break; case OpCode.Ldloc_0: expr = this.locals[0]; break; case OpCode.Ldloc_1: expr = this.locals[1]; break; case OpCode.Ldloc_2: expr = this.locals[2]; break; case OpCode.Ldloc_3: expr = this.locals[3]; break; case OpCode.Stloc_0: statement = new AssignmentStatement(this.locals[0], PopOperand()); goto done; case OpCode.Stloc_1: statement = new AssignmentStatement(this.locals[1], PopOperand()); goto done; case OpCode.Stloc_2: statement = new AssignmentStatement(this.locals[2], PopOperand()); goto done; case OpCode.Stloc_3: statement = new AssignmentStatement(this.locals[3], PopOperand()); goto done; case OpCode.Ldarg_S: expr = this.Parameters(this.GetByte()); break; case OpCode.Ldarga_S: expr = SetType(new UnaryExpression(this.Parameters(this.GetByte()), NodeType.AddressOf)); break; case OpCode.Starg_S: statement = new AssignmentStatement(this.Parameters(this.GetByte()), PopOperand()); goto done; case OpCode.Ldloc_S: expr = this.locals[this.GetByte()]; break; case OpCode.Ldloca_S: expr = SetType(new UnaryExpression(this.locals[this.GetByte()], NodeType.AddressOf)); break; case OpCode.Stloc_S: statement = new AssignmentStatement(this.locals[this.GetByte()], PopOperand()); goto done; case OpCode.Ldnull: expr = new Literal(null, CoreSystemTypes.Object); break; case OpCode.Ldc_I4_M1: expr = new Literal(-1, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_0: expr = new Literal(0, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_1: expr = new Literal(1, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_2: expr = new Literal(2, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_3: expr = new Literal(3, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_4: expr = new Literal(4, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_5: expr = new Literal(5, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_6: expr = new Literal(6, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_7: expr = new Literal(7, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_8: expr = new Literal(8, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_S: expr = new Literal((int)this.GetSByte(), CoreSystemTypes.Int32); break; case OpCode.Ldc_I4: expr = new Literal(this.GetInt32(), CoreSystemTypes.Int32); break; case OpCode.Ldc_I8: expr = new Literal(this.GetInt64(), CoreSystemTypes.Int64); break; case OpCode.Ldc_R4: expr = new Literal(this.GetSingle(), CoreSystemTypes.Single); break; case OpCode.Ldc_R8: expr = new Literal(this.GetDouble(), CoreSystemTypes.Double); break; case OpCode.Dup: statement = new ExpressionStatement(new Expression(NodeType.Dup)); goto done; case OpCode.Pop: statement = new ExpressionStatement(new UnaryExpression(PopOperand(), NodeType.Pop)); goto done; case OpCode.Jmp: expr = this.ParseCall(NodeType.Jmp, out isStatement); if (isStatement) goto done; break; case OpCode.Call: expr = this.ParseCall(NodeType.Call, out isStatement); if (isStatement) goto done; break; case OpCode.Calli: expr = this.ParseCalli(out isStatement); if (isStatement) goto done; break; case OpCode.Ret: Expression retVal = BodyParser.TypeIsVoid(this.method.ReturnType) ? null : PopOperand(); statement = new Return(retVal); transferStatement = true; goto done; case OpCode.Br_S: statement = this.ParseBranch(NodeType.Nop, 0, true, false); transferStatement = true; goto done; case OpCode.Brfalse_S: statement = this.ParseBranch(NodeType.LogicalNot, 1, true, false); transferStatement = true; goto done; case OpCode.Brtrue_S: statement = this.ParseBranch(NodeType.Nop, 1, true, false); transferStatement = true; goto done; case OpCode.Beq_S: statement = this.ParseBranch(NodeType.Eq, 2, true, false); transferStatement = true; goto done; case OpCode.Bge_S: statement = this.ParseBranch(NodeType.Ge, 2, true, false); transferStatement = true; goto done; case OpCode.Bgt_S: statement = this.ParseBranch(NodeType.Gt, 2, true, false); transferStatement = true; goto done; case OpCode.Ble_S: statement = this.ParseBranch(NodeType.Le, 2, true, false); transferStatement = true; goto done; case OpCode.Blt_S: statement = this.ParseBranch(NodeType.Lt, 2, true, false); transferStatement = true; goto done; case OpCode.Bne_Un_S: statement = this.ParseBranch(NodeType.Ne, 2, true, true); transferStatement = true; goto done; case OpCode.Bge_Un_S: statement = this.ParseBranch(NodeType.Ge, 2, true, true); transferStatement = true; goto done; case OpCode.Bgt_Un_S: statement = this.ParseBranch(NodeType.Gt, 2, true, true); transferStatement = true; goto done; case OpCode.Ble_Un_S: statement = this.ParseBranch(NodeType.Le, 2, true, true); transferStatement = true; goto done; case OpCode.Blt_Un_S: statement = this.ParseBranch(NodeType.Lt, 2, true, true); transferStatement = true; goto done; case OpCode.Br: statement = this.ParseBranch(NodeType.Nop, 0, false, false); transferStatement = true; goto done; case OpCode.Brfalse: statement = this.ParseBranch(NodeType.LogicalNot, 1, false, false); transferStatement = true; goto done; case OpCode.Brtrue: statement = this.ParseBranch(NodeType.Nop, 1, false, false); transferStatement = true; goto done; case OpCode.Beq: statement = this.ParseBranch(NodeType.Eq, 2, false, false); transferStatement = true; goto done; case OpCode.Bge: statement = this.ParseBranch(NodeType.Ge, 2, false, false); transferStatement = true; goto done; case OpCode.Bgt: statement = this.ParseBranch(NodeType.Gt, 2, false, false); transferStatement = true; goto done; case OpCode.Ble: statement = this.ParseBranch(NodeType.Le, 2, false, false); transferStatement = true; goto done; case OpCode.Blt: statement = this.ParseBranch(NodeType.Lt, 2, false, false); transferStatement = true; goto done; case OpCode.Bne_Un: statement = this.ParseBranch(NodeType.Ne, 2, false, true); transferStatement = true; goto done; case OpCode.Bge_Un: statement = this.ParseBranch(NodeType.Ge, 2, false, true); transferStatement = true; goto done; case OpCode.Bgt_Un: statement = this.ParseBranch(NodeType.Gt, 2, false, true); transferStatement = true; goto done; case OpCode.Ble_Un: statement = this.ParseBranch(NodeType.Le, 2, false, true); transferStatement = true; goto done; case OpCode.Blt_Un: statement = this.ParseBranch(NodeType.Lt, 2, false, true); transferStatement = true; goto done; case OpCode.Switch: statement = this.ParseSwitchInstruction(); transferStatement = true; goto done; case OpCode.Ldind_I1: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int8, this.isVolatile, this.alignment); break; case OpCode.Ldind_U1: expr = new AddressDereference(PopOperand(), CoreSystemTypes.UInt8, this.isVolatile, this.alignment); break; case OpCode.Ldind_I2: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int16, this.isVolatile, this.alignment); break; case OpCode.Ldind_U2: expr = new AddressDereference(PopOperand(), CoreSystemTypes.UInt16, this.isVolatile, this.alignment); break; case OpCode.Ldind_I4: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int32, this.isVolatile, this.alignment); break; case OpCode.Ldind_U4: expr = new AddressDereference(PopOperand(), CoreSystemTypes.UInt32, this.isVolatile, this.alignment); break; case OpCode.Ldind_I8: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int64, this.isVolatile, this.alignment); break; case OpCode.Ldind_I: expr = new AddressDereference(PopOperand(), CoreSystemTypes.IntPtr, this.isVolatile, this.alignment); break; case OpCode.Ldind_R4: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Single, this.isVolatile, this.alignment); break; case OpCode.Ldind_R8: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Double, this.isVolatile, this.alignment); break; case OpCode.Ldind_Ref: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Object, this.isVolatile, this.alignment); break; case OpCode.Stind_Ref: statement = this.ParseStoreIndirect(CoreSystemTypes.Object); goto done; case OpCode.Stind_I1: statement = this.ParseStoreIndirect(CoreSystemTypes.Int8); goto done; case OpCode.Stind_I2: statement = this.ParseStoreIndirect(CoreSystemTypes.Int16); goto done; case OpCode.Stind_I4: statement = this.ParseStoreIndirect(CoreSystemTypes.Int32); goto done; case OpCode.Stind_I8: statement = this.ParseStoreIndirect(CoreSystemTypes.Int64); goto done; case OpCode.Stind_R4: statement = this.ParseStoreIndirect(CoreSystemTypes.Single); goto done; case OpCode.Stind_R8: statement = this.ParseStoreIndirect(CoreSystemTypes.Double); goto done; case OpCode.Add: expr = this.ParseBinaryOperation(NodeType.Add); break; case OpCode.Sub: expr = this.ParseBinaryOperation(NodeType.Sub); break; case OpCode.Mul: expr = this.ParseBinaryOperation(NodeType.Mul); break; case OpCode.Div: expr = this.ParseBinaryOperation(NodeType.Div); break; case OpCode.Div_Un: expr = this.ParseBinaryOperation(NodeType.Div_Un); break; case OpCode.Rem: expr = this.ParseBinaryOperation(NodeType.Rem); break; case OpCode.Rem_Un: expr = this.ParseBinaryOperation(NodeType.Rem_Un); break; case OpCode.And: expr = this.ParseBinaryOperation(NodeType.And); break; case OpCode.Or: expr = this.ParseBinaryOperation(NodeType.Or); break; case OpCode.Xor: expr = this.ParseBinaryOperation(NodeType.Xor); break; case OpCode.Shl: expr = this.ParseBinaryOperation(NodeType.Shl); break; case OpCode.Shr: expr = this.ParseBinaryOperation(NodeType.Shr); break; case OpCode.Shr_Un: expr = this.ParseBinaryOperation(NodeType.Shr_Un); break; case OpCode.Neg: expr = this.ParseUnaryOperation(NodeType.Neg); break; case OpCode.Not: expr = this.ParseUnaryOperation(NodeType.Not); break; case OpCode.Conv_I1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I1, CoreSystemTypes.Int8); break; case OpCode.Conv_I2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I2, CoreSystemTypes.Int16); break; case OpCode.Conv_I4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I4, CoreSystemTypes.Int32); break; case OpCode.Conv_I8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I8, CoreSystemTypes.Int64); break; case OpCode.Conv_R4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_R4, CoreSystemTypes.Single); break; case OpCode.Conv_R8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_R8, CoreSystemTypes.Double); break; case OpCode.Conv_U4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U4, CoreSystemTypes.UInt32); break; case OpCode.Conv_U8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U8, CoreSystemTypes.UInt64); break; case OpCode.Callvirt: expr = this.ParseCall(NodeType.Callvirt, out isStatement); if (isStatement) goto done; break; case OpCode.Cpobj: statement = this.ParseCopyObject(); goto done; case OpCode.Ldobj: expr = new AddressDereference(PopOperand(), (TypeNode)this.GetMemberFromToken(), this.isVolatile, this.alignment); break; case OpCode.Ldstr: expr = new Literal(this.GetStringFromToken(), CoreSystemTypes.String); break; case OpCode.Newobj: expr = this.ParseConstruct(); break; case OpCode.Castclass: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.Castclass); break; case OpCode.Isinst: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.Isinst); break; case OpCode.Conv_R_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_R_Un, CoreSystemTypes.Double); break; case OpCode.Unbox: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.Unbox); break; case OpCode.Throw: statement = new Throw(PopOperand()); transferStatement = true; goto done; case OpCode.Ldfld: expr = new MemberBinding(PopOperand(), this.GetMemberFromToken(), this.isVolatile, this.alignment); break; case OpCode.Ldflda: expr = SetType(new UnaryExpression(new MemberBinding(PopOperand(), this.GetMemberFromToken(), this.isVolatile, this.alignment), NodeType.AddressOf)); break; case OpCode.Stfld: statement = this.ParseStoreField(); goto done; case OpCode.Ldsfld: expr = new MemberBinding(null, this.GetMemberFromToken(), this.isVolatile, this.alignment); break; case OpCode.Ldsflda: expr = SetType(new UnaryExpression(new MemberBinding(null, this.GetMemberFromToken(), this.isVolatile, this.alignment), NodeType.AddressOf)); break; case OpCode.Stsfld: statement = new AssignmentStatement(new MemberBinding(null, this.GetMemberFromToken(), this.isVolatile, this.alignment), PopOperand()); goto done; case OpCode.Stobj: statement = this.ParseStoreIndirect((TypeNode)this.GetMemberFromToken()); goto done; case OpCode.Conv_Ovf_I1_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I1_Un, CoreSystemTypes.Int8); break; case OpCode.Conv_Ovf_I2_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I2_Un, CoreSystemTypes.Int16); break; case OpCode.Conv_Ovf_I4_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I4_Un, CoreSystemTypes.Int32); break; case OpCode.Conv_Ovf_I8_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I8_Un, CoreSystemTypes.Int64); break; case OpCode.Conv_Ovf_U1_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U1_Un, CoreSystemTypes.UInt8); break; case OpCode.Conv_Ovf_U2_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U2_Un, CoreSystemTypes.UInt16); break; case OpCode.Conv_Ovf_U4_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U4_Un, CoreSystemTypes.UInt32); break; case OpCode.Conv_Ovf_U8_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U8_Un, CoreSystemTypes.UInt64); break; case OpCode.Conv_Ovf_I_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I_Un, CoreSystemTypes.IntPtr); break; case OpCode.Conv_Ovf_U_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U_Un, CoreSystemTypes.UIntPtr); break; case OpCode.Box: TypeNode t = (TypeNode)this.GetMemberFromToken(); TypeNode bt = t is EnumNode ? CoreSystemTypes.Enum : CoreSystemTypes.ValueType; expr = new BinaryExpression(PopOperand(), new Literal(t, CoreSystemTypes.Type), NodeType.Box, bt); break; case OpCode.Newarr: expr = this.ParseNewArray(); break; case OpCode.Ldlen: expr = new UnaryExpression(PopOperand(), NodeType.Ldlen, CoreSystemTypes.UIntPtr); break; case OpCode.Ldelema: expr = this.ParseArrayElementLoadAddress(); break; case OpCode.Ldelem_I1: case OpCode.Ldelem_U1: case OpCode.Ldelem_I2: case OpCode.Ldelem_U2: case OpCode.Ldelem_I4: case OpCode.Ldelem_U4: case OpCode.Ldelem_I8: case OpCode.Ldelem_I: case OpCode.Ldelem_R4: case OpCode.Ldelem_R8: case OpCode.Ldelem_Ref: expr = this.ParseArrayElementLoad(opCode, null); break; case OpCode.Stelem_I: case OpCode.Stelem_I1: case OpCode.Stelem_I2: case OpCode.Stelem_I4: case OpCode.Stelem_I8: case OpCode.Stelem_R4: case OpCode.Stelem_R8: case OpCode.Stelem_Ref: statement = this.ParseArrayElementAssignment(opCode); goto done; case OpCode.Ldelem: expr = this.ParseArrayElementLoad(opCode, null); break; case OpCode.Stelem: statement = this.ParseArrayElementAssignment(opCode); goto done; case OpCode.Unbox_Any: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.UnboxAny); break; case OpCode.Conv_Ovf_I1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I1, CoreSystemTypes.Int8); break; case OpCode.Conv_Ovf_U1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U1, CoreSystemTypes.UInt8); break; case OpCode.Conv_Ovf_I2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I2, CoreSystemTypes.Int16); break; case OpCode.Conv_Ovf_U2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U2, CoreSystemTypes.UInt16); break; case OpCode.Conv_Ovf_I4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I4, CoreSystemTypes.Int32); break; case OpCode.Conv_Ovf_U4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U4, CoreSystemTypes.UInt32); break; case OpCode.Conv_Ovf_I8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I8, CoreSystemTypes.Int64); break; case OpCode.Conv_Ovf_U8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U8, CoreSystemTypes.UInt64); break; case OpCode.Refanyval: expr = new BinaryExpression(PopOperand(), new Literal(this.GetMemberFromToken(), CoreSystemTypes.Type), NodeType.Refanyval, CoreSystemTypes.IntPtr); break; case OpCode.Ckfinite: expr = this.ParseUnaryOperation(NodeType.Ckfinite); break; case OpCode.Mkrefany: expr = new BinaryExpression(PopOperand(), new Literal(this.GetMemberFromToken(), CoreSystemTypes.Type), NodeType.Mkrefany, CoreSystemTypes.DynamicallyTypedReference); break; case OpCode.Ldtoken: expr = ParseLoadRuntimeMetadataToken(); break; case OpCode.Conv_U2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U2, CoreSystemTypes.UInt16); break; case OpCode.Conv_U1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U1, CoreSystemTypes.UInt8); break; case OpCode.Conv_I: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I, CoreSystemTypes.IntPtr); break; case OpCode.Conv_Ovf_I: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I, CoreSystemTypes.IntPtr); break; case OpCode.Conv_Ovf_U: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U, CoreSystemTypes.UIntPtr); break; case OpCode.Add_Ovf: expr = this.ParseBinaryOperation(NodeType.Add_Ovf); break; case OpCode.Add_Ovf_Un: expr = this.ParseBinaryOperation(NodeType.Add_Ovf_Un); break; case OpCode.Mul_Ovf: expr = this.ParseBinaryOperation(NodeType.Mul_Ovf); break; case OpCode.Mul_Ovf_Un: expr = this.ParseBinaryOperation(NodeType.Mul_Ovf_Un); break; case OpCode.Sub_Ovf: expr = this.ParseBinaryOperation(NodeType.Sub_Ovf); break; case OpCode.Sub_Ovf_Un: expr = this.ParseBinaryOperation(NodeType.Sub_Ovf_Un); break; case OpCode.Endfinally: statement = new EndFinally(); transferStatement = true; goto done; case OpCode.Leave: statement = this.ParseBranch(NodeType.Nop, 0, false, false, true); transferStatement = true; goto done; case OpCode.Leave_S: statement = this.ParseBranch(NodeType.Nop, 0, true, false, true); transferStatement = true; goto done; case OpCode.Stind_I: statement = this.ParseStoreIndirect(CoreSystemTypes.IntPtr); goto done; case OpCode.Conv_U: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U, CoreSystemTypes.UIntPtr); break; case OpCode.Arglist: expr = new Expression(NodeType.Arglist, CoreSystemTypes.ArgIterator); break; case OpCode.Ceq: expr = this.ParseBinaryComparison(NodeType.Ceq); break; case OpCode.Cgt: expr = this.ParseBinaryComparison(NodeType.Cgt); break; case OpCode.Cgt_Un: expr = this.ParseBinaryComparison(NodeType.Cgt_Un); break; case OpCode.Clt: expr = this.ParseBinaryComparison(NodeType.Clt); break; case OpCode.Clt_Un: expr = this.ParseBinaryComparison(NodeType.Clt_Un); break; case OpCode.Ldftn: expr = new UnaryExpression(new MemberBinding(null, this.GetMemberFromToken()), NodeType.Ldftn, CoreSystemTypes.IntPtr); break; case OpCode.Ldvirtftn: expr = new BinaryExpression(PopOperand(), new MemberBinding(null, this.GetMemberFromToken()), NodeType.Ldvirtftn, CoreSystemTypes.IntPtr); break; case OpCode.Ldarg: expr = this.Parameters((ushort)this.GetInt16()); break; case OpCode.Ldarga: expr = SetType(new UnaryExpression(this.Parameters((ushort)this.GetInt16()), NodeType.AddressOf)); break; case OpCode.Starg: statement = new AssignmentStatement(this.Parameters((ushort)this.GetInt16()), PopOperand()); goto done; case OpCode.Ldloc: expr = this.locals[(ushort)this.GetInt16()]; break; case OpCode.Ldloca: expr = SetType(new UnaryExpression(this.locals[(ushort)this.GetInt16()], NodeType.AddressOf)); break; case OpCode.Stloc: statement = new AssignmentStatement(this.locals[(ushort)this.GetInt16()], PopOperand()); goto done; case OpCode.Localloc: expr = new UnaryExpression(PopOperand(), NodeType.Localloc, CoreSystemTypes.Void); break; case OpCode.Endfilter: statement = new EndFilter(PopOperand()); transferStatement = true; goto done; case OpCode.Unaligned_: this.alignment = this.GetByte(); continue; case OpCode.Volatile_: this.isVolatile = true; continue; case OpCode.Tail_: this.isTailCall = true; continue; case OpCode.Initobj: statement = this.ParseInitObject(); goto done; case OpCode.Constrained_: this.constraint = this.GetMemberFromToken() as TypeNode; continue; case OpCode.Cpblk: expr = this.ParseTernaryOperation(NodeType.Cpblk); goto done; case OpCode.Initblk: expr = this.ParseTernaryOperation(NodeType.Initblk); goto done; case OpCode.Rethrow: statement = new Throw(null); statement.NodeType = NodeType.Rethrow; transferStatement = true; goto done; case OpCode.Sizeof: expr = new UnaryExpression(new Literal(this.GetMemberFromToken(), CoreSystemTypes.Type), NodeType.Sizeof, CoreSystemTypes.Int32); break; case OpCode.Refanytype: expr = new UnaryExpression(PopOperand(), NodeType.Refanytype, CoreSystemTypes.RuntimeTypeHandle); break; case OpCode.Readonly_: this.isReadOnly = true; continue; default: throw new InvalidMetadataException(ExceptionStrings.UnknownOpCode); } if (this.blockMap[this.counter+1] != null){ transferStatement = true; //Falls through to the next basic block, so implicitly a "transfer" statement goto done; } //^ assume expr != null; #if FxCop expr.sourceContext = sourceContext; #endif #if FxCop || ILOFFSETS expr.ILOffset = this.ilOffset; #endif this.operandStack.Push(expr); this.isReadOnly = false; this.isVolatile = false; this.isTailCall = false; this.alignment = -1; } done: for (int i = 0; i <= this.operandStack.top; i++){ Expression e = this.operandStack.elements[i]; //^ assume e != null; Statement s = new ExpressionStatement(e); #if FxCop s.SourceContext = this.sourceContext; #endif #if FxCop || ILOFFSETS s.ILOffset = this.ilOffset; #endif statementList.Add(s); } this.operandStack.top = -1; if (statement == null) { statement = new ExpressionStatement(expr); #if FxCop expr.sourceContext = this.sourceContext; #endif #if FxCop || ILOFFSETS expr.ILOffset = this.ilOffset; #endif } statement.SourceContext = sourceContext; #if FxCop || ILOFFSETS statement.ILOffset = this.ilOffset; #endif #if ILOFFSETS this.lastSourceContext = sourceContext; #endif statementList.Add(statement); if (transferStatement) return true; return this.blockMap[this.counter+1] != null; }
internal Instruction ParseInstruction(){ if (this.counter >= this.size) return null; int offset = this.counter; #if !ROTOR if (this.method.contextForOffset != null){ object sctx = this.method.contextForOffset[offset+1]; if (sctx != null) this.sourceContext = (SourceContext)sctx; } #endif object value = null; OpCode opCode = this.GetOpCode(); switch(opCode){ case OpCode.Nop: case OpCode.Break: break; case OpCode.Ldarg_0: value = this.Parameters(0); break; case OpCode.Ldarg_1: value = this.Parameters(1); break; case OpCode.Ldarg_2: value = this.Parameters(2); break; case OpCode.Ldarg_3: value = this.Parameters(3); break; case OpCode.Ldloc_0: value = this.locals[0]; break; case OpCode.Ldloc_1: value = this.locals[1]; break; case OpCode.Ldloc_2: value = this.locals[2]; break; case OpCode.Ldloc_3: value = this.locals[3]; break; case OpCode.Stloc_0: value = this.locals[0]; break; case OpCode.Stloc_1: value = this.locals[1]; break; case OpCode.Stloc_2: value = this.locals[2]; break; case OpCode.Stloc_3: value = this.locals[3]; break; case OpCode.Ldarg_S: case OpCode.Ldarga_S: case OpCode.Starg_S: value = this.Parameters(this.GetByte()); break; case OpCode.Ldloc_S: case OpCode.Ldloca_S: case OpCode.Stloc_S: value = this.locals[this.GetByte()]; break; case OpCode.Ldnull: break; case OpCode.Ldc_I4_M1: value = (Int32)(-1); break; case OpCode.Ldc_I4_0: value = (Int32)0; break; case OpCode.Ldc_I4_1: value = (Int32)1; break; case OpCode.Ldc_I4_2: value = (Int32)2; break; case OpCode.Ldc_I4_3: value = (Int32)3; break; case OpCode.Ldc_I4_4: value = (Int32)4; break; case OpCode.Ldc_I4_5: value = (Int32)5; break; case OpCode.Ldc_I4_6: value = (Int32)6; break; case OpCode.Ldc_I4_7: value = (Int32)7; break; case OpCode.Ldc_I4_8: value = (Int32)8; break; case OpCode.Ldc_I4_S: value = (Int32)this.GetSByte(); break; case OpCode.Ldc_I4: value = this.GetInt32(); break; case OpCode.Ldc_I8: value = this.GetInt64(); break; case OpCode.Ldc_R4: value = this.GetSingle(); break; case OpCode.Ldc_R8: value = this.GetDouble(); break; case OpCode.Dup: case OpCode.Pop: break; case OpCode.Jmp: case OpCode.Call: value = (Method)this.GetMemberFromToken(); break; case OpCode.Calli: value = (FunctionPointer)this.reader.GetCalliSignature(this.GetInt32()); break; case OpCode.Ret: break; case OpCode.Br_S: case OpCode.Brfalse_S: case OpCode.Brtrue_S: case OpCode.Beq_S: case OpCode.Bge_S: case OpCode.Bgt_S: case OpCode.Ble_S: case OpCode.Blt_S: case OpCode.Bne_Un_S: case OpCode.Bge_Un_S: case OpCode.Bgt_Un_S: case OpCode.Ble_Un_S: case OpCode.Blt_Un_S: value = this.counter + 1 + this.GetSByte(); break; case OpCode.Br: case OpCode.Brfalse: case OpCode.Brtrue: case OpCode.Beq: case OpCode.Bge: case OpCode.Bgt: case OpCode.Ble: case OpCode.Blt: case OpCode.Bne_Un: case OpCode.Bge_Un: case OpCode.Bgt_Un: case OpCode.Ble_Un: case OpCode.Blt_Un: value = this.counter + 4 + this.GetInt32(); break; case OpCode.Switch: value = this.ParseSwitchInstruction(); break; case OpCode.Ldind_I1: case OpCode.Ldind_U1: case OpCode.Ldind_I2: case OpCode.Ldind_U2: case OpCode.Ldind_I4: case OpCode.Ldind_U4: case OpCode.Ldind_I8: case OpCode.Ldind_I: case OpCode.Ldind_R4: case OpCode.Ldind_R8: case OpCode.Ldind_Ref: case OpCode.Stind_Ref: case OpCode.Stind_I1: case OpCode.Stind_I2: case OpCode.Stind_I4: case OpCode.Stind_I8: case OpCode.Stind_R4: case OpCode.Stind_R8: case OpCode.Add: case OpCode.Sub: case OpCode.Mul: case OpCode.Div: case OpCode.Div_Un: case OpCode.Rem: case OpCode.Rem_Un: case OpCode.And: case OpCode.Or: case OpCode.Xor: case OpCode.Shl: case OpCode.Shr: case OpCode.Shr_Un: case OpCode.Neg: case OpCode.Not: case OpCode.Conv_I1: case OpCode.Conv_I2: case OpCode.Conv_I4: case OpCode.Conv_I8: case OpCode.Conv_R4: case OpCode.Conv_R8: case OpCode.Conv_U4: case OpCode.Conv_U8: break; case OpCode.Callvirt: value = (Method)this.GetMemberFromToken(); break; case OpCode.Cpobj: case OpCode.Ldobj: value = (TypeNode)this.GetMemberFromToken(); break; case OpCode.Ldstr: value = this.GetStringFromToken(); break; case OpCode.Newobj: value = (Method)this.GetMemberFromToken();break; case OpCode.Castclass: case OpCode.Isinst: value = (TypeNode)this.GetMemberFromToken(); break; case OpCode.Conv_R_Un: break; case OpCode.Unbox: value = (TypeNode)this.GetMemberFromToken(); break; case OpCode.Throw: break; case OpCode.Ldfld: case OpCode.Ldflda: case OpCode.Stfld: case OpCode.Ldsfld: case OpCode.Ldsflda: case OpCode.Stsfld: case OpCode.Stobj: value = this.GetMemberFromToken(); break; case OpCode.Conv_Ovf_I1_Un: case OpCode.Conv_Ovf_I2_Un: case OpCode.Conv_Ovf_I4_Un: case OpCode.Conv_Ovf_I8_Un: case OpCode.Conv_Ovf_U1_Un: case OpCode.Conv_Ovf_U2_Un: case OpCode.Conv_Ovf_U4_Un: case OpCode.Conv_Ovf_U8_Un: case OpCode.Conv_Ovf_I_Un: case OpCode.Conv_Ovf_U_Un: break; case OpCode.Box: case OpCode.Newarr: value = (TypeNode)this.GetMemberFromToken(); break; case OpCode.Ldlen: break; case OpCode.Ldelema: value = (TypeNode)this.GetMemberFromToken(); break; case OpCode.Ldelem_I1: case OpCode.Ldelem_U1: case OpCode.Ldelem_I2: case OpCode.Ldelem_U2: case OpCode.Ldelem_I4: case OpCode.Ldelem_U4: case OpCode.Ldelem_I8: case OpCode.Ldelem_I: case OpCode.Ldelem_R4: case OpCode.Ldelem_R8: case OpCode.Ldelem_Ref: case OpCode.Stelem_I: case OpCode.Stelem_I1: case OpCode.Stelem_I2: case OpCode.Stelem_I4: case OpCode.Stelem_I8: case OpCode.Stelem_R4: case OpCode.Stelem_R8: case OpCode.Stelem_Ref: break; case OpCode.Ldelem: value = (TypeNode)this.GetMemberFromToken(); break; case OpCode.Stelem: value = (TypeNode)this.GetMemberFromToken(); break; case OpCode.Unbox_Any: value = this.GetMemberFromToken(); break; case OpCode.Conv_Ovf_I1: case OpCode.Conv_Ovf_U1: case OpCode.Conv_Ovf_I2: case OpCode.Conv_Ovf_U2: case OpCode.Conv_Ovf_I4: case OpCode.Conv_Ovf_U4: case OpCode.Conv_Ovf_I8: case OpCode.Conv_Ovf_U8: break; case OpCode.Refanyval: value = this.GetMemberFromToken(); break; case OpCode.Ckfinite: break; case OpCode.Mkrefany: value = this.GetMemberFromToken(); break; case OpCode.Ldtoken: value = this.GetMemberFromToken(); break; case OpCode.Conv_U2: case OpCode.Conv_U1: case OpCode.Conv_I: case OpCode.Conv_Ovf_I: case OpCode.Conv_Ovf_U: case OpCode.Add_Ovf: case OpCode.Add_Ovf_Un: case OpCode.Mul_Ovf: case OpCode.Mul_Ovf_Un: case OpCode.Sub_Ovf: case OpCode.Sub_Ovf_Un: case OpCode.Endfinally: break; case OpCode.Leave: value = this.counter + 4 + this.GetInt32(); break; case OpCode.Leave_S: value = this.counter + 1 + this.GetSByte(); break; case OpCode.Stind_I: case OpCode.Conv_U: case OpCode.Prefix7: case OpCode.Prefix6: case OpCode.Prefix5: case OpCode.Prefix4: case OpCode.Prefix3: case OpCode.Prefix2: case OpCode.Prefix1: case OpCode.Arglist: case OpCode.Ceq: case OpCode.Cgt: case OpCode.Cgt_Un: case OpCode.Clt: case OpCode.Clt_Un: break; case OpCode.Ldftn: case OpCode.Ldvirtftn: value = this.GetMemberFromToken(); break; case OpCode.Ldarg: case OpCode.Ldarga: case OpCode.Starg: value = this.Parameters(this.GetInt16()); break; case OpCode.Ldloc: case OpCode.Ldloca: case OpCode.Stloc: value = this.locals[this.GetInt16()]; break; case OpCode.Localloc: case OpCode.Endfilter: break; case OpCode.Unaligned_: value = this.GetByte(); break; case OpCode.Volatile_: case OpCode.Tail_: break; case OpCode.Initobj: value = (TypeNode)this.GetMemberFromToken(); break; case OpCode.Constrained_: value = this.GetMemberFromToken() as TypeNode; break; case OpCode.Cpblk: case OpCode.Initblk: break; case OpCode.Rethrow: break; case OpCode.Sizeof: value = this.GetMemberFromToken(); break; case OpCode.Refanytype: case OpCode.Readonly_: break; default: throw new InvalidMetadataException(String.Format(CultureInfo.CurrentCulture, ExceptionStrings.UnknownOpCodeEncountered, opCode.ToString("x"))); } Instruction instruction = new Instruction(opCode, offset, value); instruction.SourceContext = this.sourceContext; return instruction; }
private void CopyAbbreviatorContracts(Method targetMethod, Method abbreviatorMethodInstance, Expression targetObject, ExpressionList actuals, RequiresList Preconditions, EnsuresList Postconditions, SourceContext useSite, RequiresList validations, Block contractInitializer) { Contract.Requires(validations != null); // make sure to have extracted contracts from the abbreviator method prior if (abbreviatorMethodInstance.DeclaringType.DeclaringModule == targetMethod.DeclaringType.DeclaringModule) { var abbrevMethod = abbreviatorMethodInstance; while (abbrevMethod.Template != null) { abbrevMethod = abbrevMethod.Template; } this.VisitMethod(abbrevMethod); } if (abbreviatorMethodInstance.Contract == null) return; var copier = new AbbreviationDuplicator(abbreviatorMethodInstance, targetMethod, this.contractNodes, abbreviatorMethodInstance, targetObject, actuals); var abbrevContract = HelperMethods.DuplicateContractAndClosureParts(copier, targetMethod, abbreviatorMethodInstance, this.contractNodes, true); if (abbrevContract == null) return; if (HelperMethods.IsNonTrivial(abbrevContract.ContractInitializer)) { contractInitializer.Statements.Add(abbrevContract.ContractInitializer); } MoveAbbreviatorRequires(targetMethod, abbrevContract.Requires, Preconditions, validations, useSite); MoveAbbreviatorEnsures(targetMethod, abbrevContract.Ensures, Postconditions, useSite); }
internal static bool FindContext(Block currentClump, SourceContext initialSourceContext, out SourceContext sctx) { sctx = initialSourceContext; if (currentClump == null || currentClump.Statements == null || currentClump.Statements.Count <= 0) return false; for (int i = 0, n = currentClump.Statements.Count; i < n; i++) { Block b = currentClump.Statements[i] as Block; if (b == null || b.Statements == null || b.Statements.Count <= 0) continue; for (int j = 0, m = b.Statements.Count; j < m; j++) { Statement s = b.Statements[j]; if (s == null) continue; if (s.NodeType != NodeType.Nop // these are the source contexts the compiler puts in that correspond to things like method declarations, etc. && s.SourceContext.IsValid) { sctx = s.SourceContext; return true; } } } return false; }
public ContractAssumeAssertStatement(Expression expression, SourceContext sctx, string sourceText) : base(expression, sctx) { this.SourceText = sourceText; }
private Method CreateWrapperMethod(bool virtcall, TypeNode virtcallConstraint, Method templateMethod, TypeNode templateType, TypeNode wrapperType, Method methodWithContract, Method instanceMethod, SourceContext callingContext) { bool isProtected = IsProtected(templateMethod); Identifier name = templateMethod.Name; if (virtcall) { if (virtcallConstraint != null) { name = Identifier.For("CV$" + name.Name); } else { name = Identifier.For("V$" + name.Name); } } else { name = Identifier.For("NV$" + name.Name); } Duplicator dup = new Duplicator(this.assemblyBeingRewritten, wrapperType); TypeNodeList typeParameters = null; TypeNodeList typeParameterFormals = new TypeNodeList(); TypeNodeList typeParameterActuals = new TypeNodeList(); if (templateMethod.TemplateParameters != null) { dup.FindTypesToBeDuplicated(templateMethod.TemplateParameters); typeParameters = dup.VisitTypeParameterList(templateMethod.TemplateParameters); for (int i = 0; i < typeParameters.Count; i++) { typeParameterFormals.Add(typeParameters[i]); typeParameterActuals.Add(templateMethod.TemplateParameters[i]); } } ITypeParameter constraintTypeParam = null; if (virtcallConstraint != null) { if (typeParameters == null) { typeParameters = new TypeNodeList(); } var constraint = templateMethod.DeclaringType; var classConstraint = constraint as Class; if (classConstraint != null) { var classParam = new MethodClassParameter(); classParam.BaseClass = classConstraint; classParam.Name = Identifier.For("TC"); classParam.DeclaringType = wrapperType; typeParameters.Add(classParam); constraintTypeParam = classParam; } else { var mtp = new MethodTypeParameter(); Interface intf = constraint as Interface; if (intf != null) { mtp.Interfaces.Add(intf); } mtp.Name = Identifier.For("TC"); mtp.DeclaringType = wrapperType; typeParameters.Add(mtp); constraintTypeParam = mtp; } } var consolidatedTemplateTypeParameters = templateType.ConsolidatedTemplateParameters; if (consolidatedTemplateTypeParameters != null && consolidatedTemplateTypeParameters.Count > 0) { var consolidatedWrapperTypeParameters = wrapperType.ConsolidatedTemplateParameters; for (int i = 0; i < consolidatedTemplateTypeParameters.Count; i++) { typeParameterFormals.Add(consolidatedWrapperTypeParameters[i]); typeParameterActuals.Add(consolidatedTemplateTypeParameters[i]); } } Specializer spec = null; if (typeParameterActuals.Count > 0) { spec = new Specializer(this.assemblyBeingRewritten, typeParameterActuals, typeParameterFormals); } var parameters = new ParameterList(); var asTypeConstraintTypeParam = constraintTypeParam as TypeNode; if (!isProtected && !templateMethod.IsStatic) { TypeNode thisType = GetThisTypeInstance(templateType, wrapperType, asTypeConstraintTypeParam); parameters.Add(new Parameter(Identifier.For("@this"), thisType)); } for (int i = 0; i < templateMethod.Parameters.Count; i++) { parameters.Add((Parameter)dup.VisitParameter(templateMethod.Parameters[i])); } var retType = dup.VisitTypeReference(templateMethod.ReturnType); if (spec != null) { parameters = spec.VisitParameterList(parameters); retType = spec.VisitTypeReference(retType); } var wrapperMethod = new Method(wrapperType, null, name, parameters, retType, null); RewriteHelper.TryAddCompilerGeneratedAttribute(wrapperMethod); if (isProtected) { wrapperMethod.Flags = templateMethod.Flags & ~MethodFlags.Abstract; wrapperMethod.CallingConvention = templateMethod.CallingConvention; } else { wrapperMethod.Flags |= MethodFlags.Static | MethodFlags.Assembly; } if (constraintTypeParam != null) { constraintTypeParam.DeclaringMember = wrapperMethod; } if (typeParameters != null) { if (spec != null) { typeParameters = spec.VisitTypeParameterList(typeParameters); } wrapperMethod.IsGeneric = true; wrapperMethod.TemplateParameters = typeParameters; } // create body var sl = new StatementList(); Block b = new Block(sl); // insert requires AddRequiresToWrapperMethod(wrapperMethod, b, methodWithContract); // create original call var targetType = templateType; if (isProtected) { // need to use base chain instantiation of target type. targetType = instanceMethod.DeclaringType; } else { if (targetType.ConsolidatedTemplateParameters != null && targetType.ConsolidatedTemplateParameters.Count > 0) { // need selfinstantiation targetType = targetType.GetGenericTemplateInstance(this.assemblyBeingRewritten, wrapperType.ConsolidatedTemplateParameters); } } Method targetMethod = GetMatchingMethod(targetType, templateMethod, wrapperMethod); if (targetMethod.IsGeneric) { if (typeParameters.Count > targetMethod.TemplateParameters.Count) { // omit the extra constrained type arg. TypeNodeList origArgs = new TypeNodeList(); for (int i = 0; i < targetMethod.TemplateParameters.Count; i++) { origArgs.Add(typeParameters[i]); } targetMethod = targetMethod.GetTemplateInstance(wrapperType, origArgs); } else { targetMethod = targetMethod.GetTemplateInstance(wrapperType, typeParameters); } } MethodCall call; NodeType callType = virtcall ? NodeType.Callvirt : NodeType.Call; if (isProtected) { var mb = new MemberBinding(wrapperMethod.ThisParameter, targetMethod); var elist = new ExpressionList(wrapperMethod.Parameters.Count); for (int i = 0; i < wrapperMethod.Parameters.Count; i++) { elist.Add(wrapperMethod.Parameters[i]); } call = new MethodCall(mb, elist, callType); } else if (templateMethod.IsStatic) { var elist = new ExpressionList(wrapperMethod.Parameters.Count); for (int i = 0; i < wrapperMethod.Parameters.Count; i++) { elist.Add(wrapperMethod.Parameters[i]); } call = new MethodCall(new MemberBinding(null, targetMethod), elist, callType); } else { var mb = new MemberBinding(wrapperMethod.Parameters[0], targetMethod); var elist = new ExpressionList(wrapperMethod.Parameters.Count - 1); for (int i = 1; i < wrapperMethod.Parameters.Count; i++) { elist.Add(wrapperMethod.Parameters[i]); } call = new MethodCall(mb, elist, callType); } if (constraintTypeParam != null) { call.Constraint = asTypeConstraintTypeParam; } if (HelperMethods.IsVoidType(templateMethod.ReturnType)) { sl.Add(new ExpressionStatement(call,callingContext)); sl.Add(new Return(callingContext)); } else { sl.Add(new Return(call,callingContext)); } wrapperMethod.Body = b; wrapperType.Members.Add(wrapperMethod); return wrapperMethod; }
internal Method WrapperMethod(Method instanceMethod, bool virtcall, TypeNode constraint, Method methodContainingCall, Method methodWithContract, SourceContext callingContext) { // for now disable the following // - protected methods // - constructors // - base calls if (IsProtected(instanceMethod)) return null; if (instanceMethod is InstanceInitializer) return null; if (!virtcall && instanceMethod.IsVirtual) return null; var templateMethod = instanceMethod; while (templateMethod.Template != null) templateMethod = templateMethod.Template; var templateType = templateMethod.DeclaringType; TypeNode wrapperType; if (IsProtected(instanceMethod)) { // can only be called on "this" of derived type, so no wrapper class wrapperType = methodContainingCall.DeclaringType; while (wrapperType.Template != null) { wrapperType = wrapperType.Template; } } else { wrapperType = WrapperType(templateType); } var wrapperMethod = LookupWrapperMethod(virtcall, constraint, wrapperType, templateMethod); if (wrapperMethod == null) { wrapperMethod = CreateWrapperMethod(virtcall, constraint, templateMethod, templateType, wrapperType, methodWithContract, instanceMethod, callingContext); StoreWrapperMethod(virtcall, constraint, templateMethod, wrapperMethod); } return InstantiateWrapperMethod(constraint, wrapperMethod, instanceMethod); }
public override StatementList VisitStatementList(StatementList statements) { if (statements == null) return null; for (int i = 0; i < statements.Count; i++) { var stmt = statements[i]; if (stmt == null) continue; if (stmt.SourceContext.IsValid) { this.lastStmtContext = stmt.SourceContext; } statements[i] = (Statement)base.Visit(stmt); } return statements; }
private static Statement WrapTryCatch(Method method, Statement statement) { Block afterCatches = new Block(new StatementList()); Block tryBlock = new Block(new StatementList()); Block blockAfterTryBody = new Block(null); tryBlock.Statements.Add(statement); tryBlock.Statements.Add(new Branch(null, afterCatches, false, true, true)); tryBlock.Statements.Add(blockAfterTryBody); Block catchBlock = new Block(new StatementList()); // emit code that pops the exception and fools fxcop Block branchTargetToFoolFxCop = new Block(null); var branch = new Branch(new Expression(NodeType.Pop), branchTargetToFoolFxCop); SourceContext hiddenContext = new SourceContext(HiddenDocument.Document); branch.SourceContext = hiddenContext; catchBlock.Statements.Add(branch); var rethrowStatement = new Throw(); rethrowStatement.SourceContext = hiddenContext; rethrowStatement.NodeType = NodeType.Rethrow; catchBlock.Statements.Add(rethrowStatement); catchBlock.Statements.Add(branchTargetToFoolFxCop); var leave = new Branch(null, afterCatches, false, true, true); leave.SourceContext = hiddenContext; catchBlock.Statements.Add(leave); Block tryCatch = new Block(new StatementList()); tryCatch.Statements.Add(tryBlock); tryCatch.Statements.Add(catchBlock); tryCatch.Statements.Add(afterCatches); if (method.ExceptionHandlers == null) method.ExceptionHandlers = new ExceptionHandlerList(); ExceptionHandler exHandler = new ExceptionHandler(); exHandler.TryStartBlock = tryBlock; exHandler.BlockAfterTryEnd = blockAfterTryBody; exHandler.HandlerStartBlock = catchBlock; exHandler.BlockAfterHandlerEnd = afterCatches; exHandler.FilterType = SystemTypes.Exception; exHandler.HandlerType = NodeType.Catch; method.ExceptionHandlers.Add(exHandler); return tryCatch; }
private void MoveAbbreviatorEnsures(Method targetMethod, EnsuresList ensuresList, EnsuresList Postconditions, SourceContext useSite) { if (ensuresList == null) return; foreach (var ens in ensuresList) { if (!ens.DefSite.IsValid) { ens.DefSite = ens.SourceContext; } ens.SourceContext = useSite; // re-sanitize user message for this context ens.UserMessage = SanitizeUserMessage(targetMethod, ens.UserMessage, useSite); Postconditions.Add(ens); } }
/// <summary> /// </summary> /// <param name="validationContractInitializer">possibly empty initializer from closures in validators. Must be added as prefix to first requires</param> /// <param name="validationPrefix">Possibly empty statement list of code preceeding validator call. Must be added to first /// requires.</param> private void MoveValidatorRequires(Method targetMethod, RequiresList requiresList, RequiresList Preconditions, SourceContext useSite, Block validationContractInitializer, Block validationPrefix) { bool isFromValidation = true; if (requiresList == null) return; foreach (RequiresPlain req in requiresList) { if (!req.DefSite.IsValid) { req.DefSite = req.SourceContext; } req.SourceContext = useSite; req.IsFromValidation = isFromValidation; // mark that we copied this from a validator when necessary // re-sanitize user message for this context req.UserMessage = SanitizeUserMessage(targetMethod, req.UserMessage, useSite); // check if first requires and add prefixes if (HelperMethods.IsNonTrivial(validationPrefix)) { req.Condition = new BlockExpression( new Block(new StatementList(validationPrefix, new ExpressionStatement(req.Condition)))); validationPrefix = null; } if (HelperMethods.IsNonTrivial(validationContractInitializer)) { req.Condition = new BlockExpression( new Block(new StatementList(validationContractInitializer, new ExpressionStatement(req.Condition)))); validationContractInitializer = null; } Preconditions.Add(req); } }
/// <summary> /// Tries to find the last statement in the clump that has a valid source context. /// </summary> /// <param name="clump">The clump to search in</param> /// <param name="sctx">The last source context in clump</param> /// <returns>true iff there exists a non-zero source context in clump</returns> internal static bool GetLastSourceContext(StatementList clump, out SourceContext sctx) { sctx = new SourceContext(); bool found = false; if (clump == null || (!(0 < clump.Count))) return found; for (int i = clump.Count - 1; 0 <= i && !found; i--) { Block b = clump[i] as Block; if (b == null) continue; for (int j = b.Statements == null ? 0 : b.Statements.Count - 1; 0 <= j; j--) { Statement s = b.Statements[j]; if (s == null) continue; if (s.NodeType == NodeType.Nop) continue; // skip curlys sctx = s.SourceContext; if (sctx.IsValid) { found = true; break; } } } return found; }
private void MoveAbbreviatorRequires(Method targetMethod, RequiresList requiresList, RequiresList Preconditions, RequiresList validations, SourceContext useSite) { Contract.Requires(validations != null); if (requiresList == null) return; foreach (RequiresPlain req in requiresList) { if (!req.DefSite.IsValid) { req.DefSite = req.SourceContext; } req.SourceContext = useSite; req.IsFromValidation = false; // re-sanitize user message for this context req.UserMessage = SanitizeUserMessage(targetMethod, req.UserMessage, useSite); Preconditions.Add(req); validations.Add(req); // we keep everything on both lists so we can emit for validation or standard } }
internal StatementList/*!*/ ParseStatements() { this.tryMap = new Dictionary<Block, List<TryNode>>(); this.handlerMap = new Dictionary<int, Expression>(); this.ParseHeader(); this.CreateBlocksForBranchTargets(); currentBlock = null; this.sourceContext = new SourceContext(); while (this.counter < size) { if (currentBlock == null) { currentBlock = Reader.GetOrCreateBlock(this.blockMap, this.counter); } bool endOfBasicBlock = this.ParseStatement(currentBlock); if (endOfBasicBlock) { currentBlock.SourceContext = currentBlock.Statements[0].SourceContext; currentBlock = null; } } Reader.GetOrCreateBlock(this.blockMap, this.counter); int counter = 0; Block block = new Block(); block.Statements = new StatementList(); ProcessBlock(block, ref counter, this.size, null); return block.Statements; }
/// <summary> /// Only allows literal and static field reference based on visibility /// </summary> /// <param name="expression"></param> /// <returns></returns> private Expression SanitizeUserMessage(Method containing, Expression expression, SourceContext sc) { if (expression == null) return null; Member member; var result = SanitizeUserMessageInternal(containing, expression, out member); if (result != null) { // filter by visibility if (member != null && !HelperMethods.IsVisibleFrom(member, containing.DeclaringType)) return null; return result; } this.HandleError(containing, 1065, "User message to contract call can only be string literal, or a static field, or static property that is at least internally visible.", sc); return null; }
public override void VisitStatementList(StatementList statements) { if (statements == null) return; for (int i = 0; i < statements.Count; i++) { var st = statements[i]; if (st != null && st.SourceContext.IsValid) { lastSC = st.SourceContext; } this.Visit(st); } }
private void BadStuff(Method method, StatementList contractClump, SourceContext defaultSourceContext) { LookForBadStuff lfbs = new LookForBadStuff(this.contractNodes); lfbs.CheckForBadStuff(contractClump); if (lfbs.ReturnStatement != null) { SourceContext sctx = lfbs.ReturnStatement.SourceContext; if (!sctx.IsValid) sctx = defaultSourceContext; this.HandleError(method, 1015, "Return statement found in contract section.", sctx); return; } if (lfbs.BadStuffFound) { this.HandleError(method, 1016, "Contract.Assert/Contract.Assume cannot be used in contract section. Use only Requires and Ensures.", defaultSourceContext); } }
public void Check(Method currentMethod) { // F: Contract.Requires(currentMethod != null); if (currentMethod.Contract == null) return; this.CurrentMethod = currentMethod; this.assignmentFound = false; bool errorIssued = false; for (int i = 0; i < currentMethod.Contract.RequiresCount; i++) { var req = currentMethod.Contract.Requires[i]; if (req == null) continue; this.lastSourceContext = req.SourceContext; this.Visit(req); if (this.assignmentFound) { errorIssued = true; this.errorHandler(new Error(1004, "Malformed contract. Found Requires after assignment in method '" + currentMethod.FullName + "'.", req.SourceContext)); break; } } if (errorIssued) return; for (int i = 0; i < currentMethod.Contract.EnsuresCount; i++) { var ens = currentMethod.Contract.Ensures[i]; if (ens == null) continue; this.lastSourceContext = ens.SourceContext; this.Visit(ens); if (this.assignmentFound) { errorIssued = true; this.errorHandler(new Error(1005, "Malformed contract. Found Ensures after assignment in method '" + currentMethod.FullName + "'.", ens.SourceContext)); break; } } if (errorIssued) return; for (int i = 0; i < currentMethod.Contract.AsyncEnsuresCount; i++) { var ens = currentMethod.Contract.AsyncEnsures[i]; if (ens == null) continue; this.lastSourceContext = ens.SourceContext; this.Visit(ens); if (this.assignmentFound) { errorIssued = true; this.errorHandler(new Error(1005, "Malformed contract. Found Ensures after assignment in method '" + currentMethod.FullName + "'.", ens.SourceContext)); break; } } if (errorIssued) return; for (int i = 0; i < currentMethod.Contract.ModelEnsuresCount; i++) { var ens = currentMethod.Contract.ModelEnsures[i]; if (ens == null) continue; this.lastSourceContext = ens.SourceContext; this.Visit(ens); if (this.assignmentFound) { errorIssued = true; this.errorHandler(new Error(1005, "Malformed contract. Found Ensures after assignment in method '" + currentMethod.FullName + "'.", ens.SourceContext)); break; } } }
private bool CheckClump(Method method, GatherLocals gatherLocals, SourceContext sctx, Block clump) { if (!HelperMethods.ClumpIsClosed(clump.Statements)) { this.contractNodes.CallErrorFound(new Error(1017, "Malformed contract section in method '" + method.FullName + "'", sctx)); return false; // throw new ExtractorException(); } TypeNode t = method.DeclaringType; bool IsContractTypeForSomeOtherType = t == null ? false : HelperMethods.GetTypeFromAttribute(t, ContractNodes.ContractClassForAttributeName) != null; // We require that a contract class implement the interface it is holding contracts for. In addition, the methods in that class must be explicit // interface implementations. This creates a problem when the contracts need to refer to other methods in the interface. The "this" reference has // the wrong type: it needs to be the interface type. Writing an explicit cast before every reference is painful. It is better to allow the user // to create a local variable of the interface type and assign it before the contracts. This can't cause a problem with the local being used later // in the method body, because methods in contract classes don't have method bodies, just contracts. So don't check for re-use of locals for such // methods. // // Example of above comment //[ContractClass(typeof(ContractForJ))] //interface J{ // bool M(int x); // [Pure] // bool P { get; } //} //[ContractClassFor(typeof(J))] //class ContractForJ : J{ // bool J.M(int x) { // J jThis = this; // Contract.Requires(x != 3); // Contract.Requires(jThis.P); // Contract.Ensures(x != 5 || !jThis.P); // return default(bool); // } // bool J.P { // get { // Contract.Ensures(Contract.Result<bool>()); // return default(bool); // } // } //} if (!IsContractTypeForSomeOtherType) { // First, make sure the clump doesn't use any locals that were used // in any previous contract, need a new instance each time CheckLocals checkLocals = new CheckLocals(gatherLocals); checkLocals.Visit(clump); if (!this.fSharp && checkLocals.reUseOfExistingLocal != null) { this.HandleError(method, 1040, "Reuse of existing local variable '" + checkLocals.reUseOfExistingLocal.Name.Name + "' in contract.", sctx); return false; } // If that test passes, then add in the locals used in the clump into the table of locals that have been used gatherLocals.Visit(clump); } return true; }