/// <summary> /// /// </summary> /// <param name="e"></param> /// <returns> /// true if 1) current method deos not contain a delayed parameter /// or 2) the type of concern does not contain a constructor that accepts delayed parameters otherthan /// "this" /// </returns> private bool delayedParametersNoEffect(TypeNode type, InitializedVariables ivs, PreDAStatus nns, Statement s) { if (type == null) return false; bool result = false; // see if this element type can possibly // have a constructor that accepts delayed parameters result = result || (!hasConstructorAcceptingDelay(type)); result = result || nns.OKToCommit(s); return result; }
public DefiniteAssignmentInstructionVisitor(Analyzer analyzer, MethodDefiniteAssignmentChecker m, PreDAStatus preResult){ mpc=m; //reportedErrors=new Hashtable(); this.analyzer = analyzer; nns = preResult; }
/// <summary> /// Entry point of the check. /// /// It create a new instance of the checker, and run the checker on the given method. /// </summary> /// <param name="t"></param> /// <param name="method"></param> public static IDelayInfo Check(TypeSystem t, Method method, Analyzer analyzer, PreDAStatus preResult) { Debug.Assert(method!=null && analyzer != null); MethodDefiniteAssignmentChecker checker= new MethodDefiniteAssignmentChecker(t, analyzer, preResult); checker.currentMethod=method; ControlFlowGraph cfg=analyzer.GetCFG(method); if(cfg==null) return null; InitializedVariables iv = new InitializedVariables(analyzer); checker.Run(cfg,iv); if (checker.exitState == null) { // Method has no normal return. We should consider having such method as annotated with [NoReturn]. return checker.NodeExistentialTable; } InitializedVariables onExit = new InitializedVariables((InitializedVariables)checker.exitState); // check for unassigned Out parameters. ParameterList pl=checker.currentMethod.Parameters; if(pl!=null){ for(int i=0; i < pl.Count; i++){ Parameter p = pl[i]; if(p.Type is Reference && p.IsOut && !onExit.IsAssignedRef(p, ((Reference)p.Type).ElementType as Struct)) checker.typeSystem.HandleError(method.Name,Error.ParamUnassigned,p.Name.Name); } } // check for struct fields in constructor if (method is InstanceInitializer && method.DeclaringType != null && method.DeclaringType.IsValueType) { Field unassignedfield = onExit.NonAssignedRefField(method.ThisParameter, (Struct)method.DeclaringType); if (unassignedfield != null) { checker.typeSystem.HandleError(method, Error.UnassignedThis, checker.typeSystem.GetTypeName(unassignedfield.DeclaringType)+"."+unassignedfield.Name.Name); } } // if delayed constructor, check for field initializations here if (method is InstanceInitializer && checker.iVisitor.IsUniversallyDelayed(method.ThisParameter)) { checker.iVisitor.CheckCtorNonNullFieldInitialization(method.ThisParameter, method.Name, onExit, Error.NonNullFieldNotInitializedAtEndOfDelayedConstructor); } // Check for uninitialized base class if (method is InstanceInitializer && method.DeclaringType is Class && method.DeclaringType.BaseType != null && method.DeclaringType.BaseType != SystemTypes.MulticastDelegate && !onExit.IsBaseAssigned()) checker.typeSystem.HandleError(method, Error.BaseNotInitialized); // Check for assigned but unreferenced variables. //TODO: this check should be moved to Looker so that constant folding does not affect it onExit.EmitAssignedButNotReferencedErrors(checker.typeSystem); return (checker.NodeExistentialTable); }
protected MethodDefiniteAssignmentChecker(TypeSystem t, Analyzer analyzer, PreDAStatus preResult) { typeSystem=t; iVisitor=new DefiniteAssignmentInstructionVisitor(analyzer, this, preResult); reportedErrors=new Hashtable(); this.analyzer = analyzer; this.nodeExistentialTable = new NodeMaybeExistentialDelayInfo (); }
/// <summary> /// Put general analysis targeting to general IL properties. /// </summary> /// <param name="method"></param> protected void GeneralAnalysis(Method method) { nonNullInfo = null; if (!this.CodeIsWellFormed) { return; } if (debug) { ControlFlowGraph cfg = GetCFG(method); if (cfg != null) { cfg.Display(Console.Out); } } if (!method.Name.Name.StartsWith("Microsoft.Contracts")) { // Definite assignment checking //System.Console.WriteLine("--------------- Analyzing Method: {0}", method.Name); if (this.DefiniteAssignmentChecking) { // For every statement, three things are returned from this pre- stage analysis // 1) which program vars (that represent NN arrays) are created but not committed // 2) which program vars (that represent NN arrays) are created and committed between // the creation and commitment of current array. // 3) if the statement is a commitment call for an NN array, whether it // is ok to lift the array to be non-delayed. PreDAStatus preAnalysisResult = MethodReachingDefNNArrayChecker.Check(typeSystem, method, this); if (preAnalysisResult != null) { delayInfo = MethodDefiniteAssignmentChecker.Check(typeSystem, method, this, preAnalysisResult); } } if (Analyzer.Debug) { if (delayInfo != null) { System.Console.WriteLine("----- delay info count: {0}", delayInfo.Count()); } } if (this.ExposureChecking) { ExposureChecker.Check(typeSystem, method, this); } // NonNull checking if (this.NonNullChecking) { nonNullInfo = NonNullChecker.Check(typeSystem, method, this); } //System.Console.WriteLine("---------------- Finished Analyzing Method:{0}", method.Name); } }