/** * Check that the set of <code>LocalInstance</code>s <code>localsUsed</code>, which is the set of * locals used in the inner class declared by <code>cb</code> are initialized before the class * declaration. */ protected void checkLocalsUsedByInnerClass( FlowGraph graph, ClassBody cb, Set localsUsed, DataFlowItem dfIn, DataFlowItem dfOut) throws SemanticException { for (Iterator iter = localsUsed.iterator(); iter.hasNext(); ) { LocalInstance li = (LocalInstance) iter.next(); MinMaxInitCount initCount = (MinMaxInitCount) dfOut.initStatus.get(li); if (!currCBI.localDeclarations.contains(li)) { // the local wasn't defined in this scope. currCBI.outerLocalsUsed.add(li); } else if (initCount == null || InitCount.ZERO.equals(initCount.getMin())) { // initCount will in general not be null, as the local variable // li is declared in the current class; however, if the inner // class is declared in the initializer of the local variable // declaration, then initCount could in fact be null, as we // leave the inner class before we have performed flowLocalDecl // for the local variable declaration. throw new SemanticException( "Local variable \"" + li.name() + "\" must be initialized before the class " + "declaration.", cb.position()); } } }
/** Check that the assignment to a local variable is correct. */ protected void checkLocalAssign( FlowGraph graph, LocalAssign a, DataFlowItem dfIn, DataFlowItem dfOut) throws SemanticException { LocalInstance li = ((Local) a.left()).localInstance(); if (!currCBI.localDeclarations.contains(li)) { throw new SemanticException( "Final local variable \"" + li.name() + "\" cannot be assigned to in an inner class.", a.position()); } MinMaxInitCount initCount = (MinMaxInitCount) dfOut.initStatus.get(li); if (li.flags().isFinal() && InitCount.MANY.equals(initCount.getMax())) { throw new SemanticException( "variable \"" + li.name() + "\" might already have been assigned to", a.position()); } }
@Override public Node labelCheckLHS(LabelChecker lc) throws SemanticException { final Assign assign = (Assign) node(); Local lve = (Local) assign.left(); JifTypeSystem ts = lc.jifTypeSystem(); JifContext A = lc.jifContext(); A = (JifContext) lve.del().enterScope(A); List throwTypes = new ArrayList(assign.del().throwTypes(ts)); final LocalInstance li = lve.localInstance(); Label L = ts.labelOfLocal(li, A.pc()); Expr rhs = (Expr) lc.context(A).labelCheck(assign.right()); PathMap Xr = rhsPathMap(lc.context(A), rhs, throwTypes); PathMap X; if (assign.operator() != Assign.ASSIGN) { PathMap Xv = ts.pathMap(); Xv = Xv.N(A.pc()); Xv = Xv.NV(lc.upperBound(L, A.pc())); if (assign.throwsArithmeticException()) { Type arithExc = ts.ArithmeticException(); checkAndRemoveThrowType(throwTypes, arithExc); X = Xv.join(Xr).exc(Xr.NV(), arithExc); } else { X = Xv.join(Xr); } } else { X = Xr; } lc.constrain( new NamedLabel( "rhs.nv", "label of successful evaluation of right hand of assignment", X.NV()), LabelConstraint.LEQ, new NamedLabel("label of var " + li.name(), L), A.labelEnv(), lve.position(), new LabelConstraintMessage() { @Override public String msg() { return "Label of right hand side not less " + "restrictive than the label for local variable " + li.name(); } @Override public String detailMsg() { return "More information is revealed by the successful " + "evaluation of the right hand side of the " + "assignment than is allowed to flow to " + "the local variable " + li.name() + "."; } @Override public String technicalMsg() { return "Invalid assignment: path NV of rhs is " + "not less restrictive than the declared label " + "of the local variable <" + li.name() + ">."; } }); if (JLiftOptions.getInstance().safeMutateConstraintSet) { // also constrain PC label lc.constrain( new NamedLabel("pc", "program counter label for assignment", A.pc()), LabelConstraint.LEQ, new NamedLabel("label of var " + li.name(), L), A.labelEnv(), lve.position(), new LabelConstraintMessage() { @Override public String msg() { return "Program counter not less " + "restrictive than the label for local variable " + li.name(); } }); } Expr lhs = (Expr) updatePathMap(lve, X); checkThrowTypes(throwTypes); return updatePathMap(assign.right(rhs).left(lhs), X); }
private Node translateExtForArray(ExtendedFor n, List<String> labels) throws SemanticException { Position pos = Position.compilerGenerated(); Type iteratedType = n.decl().type().type(); // translate "L1,...,Ln: for (C x: e) b" to // "{ C[] arr = e; int iter = 0; L1,...,Ln: while (iter < arr.length) { C x = arr[iter]; b ; // iter = iter + 1; }" List<Stmt> stmts = new ArrayList<Stmt>(); // add the declaration of arr: "C[] arr = e" Id arrID = freshName("arr"); LocalInstance arrLI = ts.localInstance(pos, Flags.NONE, n.expr().type(), arrID.id()); { LocalDecl ld = nodeFactory() .LocalDecl( pos, Flags.NONE, nodeFactory().CanonicalTypeNode(pos, arrLI.type()), arrID); ld = ld.localInstance(arrLI); ld = ld.init(n.expr()); stmts.add(ld); } // add the declaration of iterator: "int iter = 0" Id iterID = freshName("iter"); LocalInstance iterLI = ts.localInstance(pos, Flags.NONE, ts.Int(), iterID.id()); { LocalDecl ld = nodeFactory() .LocalDecl( pos, Flags.NONE, nodeFactory().CanonicalTypeNode(pos, iterLI.type()), iterID); ld = ld.localInstance(iterLI); ld = ld.init(nodeFactory().IntLit(pos, IntLit.INT, 0).type(ts.Int())); stmts.add(ld); } // build the conditional "iter < arr.length" Expr cond; { Local iterLocal = (Local) nodeFactory().Local(pos, iterID).localInstance(iterLI).type(ts.Int()); Local arrLocal = (Local) nodeFactory().Local(pos, arrID).localInstance(arrLI).type(arrLI.type()); Id id = nodeFactory().Id(pos, "length"); Field field = (Field) nodeFactory().Field(pos, arrLocal, id).type(ts.Int()); field = field.fieldInstance(ts.findField(arrLI.type().toReference(), "length")); cond = nodeFactory().Binary(pos, iterLocal, Binary.LT, field).type(ts.Boolean()); } // build the initlizer for the local decl: arr[iter] Expr init; { Local iterLocal = (Local) nodeFactory().Local(pos, iterID).localInstance(iterLI).type(ts.Int()); Local arrLocal = (Local) nodeFactory().Local(pos, arrID).localInstance(arrLI).type(arrLI.type()); init = nodeFactory().ArrayAccess(pos, arrLocal, iterLocal); init = init.type(iteratedType); } // build the increment for iter (iter = iter + 1;) Stmt inc; { Local iterLocal = (Local) nodeFactory().Local(pos, iterID).localInstance(iterLI).type(ts.Int()); Expr incExpr = nodeFactory() .Binary( pos, iterLocal.type(ts.Int()), Binary.ADD, nodeFactory().IntLit(pos, IntLit.INT, 1).type(ts.Int())) .type(ts.Int()); Assign incStore = (Assign) nodeFactory().Assign(pos, iterLocal, Assign.ASSIGN, incExpr).type(ts.Int()); inc = nodeFactory().Eval(pos, incStore); } // build the while loop { // Create a new loop body from the old body followed by the increment Block loopBody = nodeFactory().Block(pos, n.decl().init(init), n.body(), inc); While loop = nodeFactory().While(pos, cond, loopBody); stmts.add(labelStmt(loop, labels)); } return nodeFactory().Block(pos, stmts); }