src/share/classes/com/sun/tools/javac/comp/Lower.java

Print this page




1408     }
1409 //where
1410         JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1411             return access(v, make.at(pos).Ident(v), null, false);
1412         }
1413 
1414     /** Construct a tree simulating the expression <C.this>.
1415      *  @param pos           The source code position to be used for the tree.
1416      *  @param c             The qualifier class.
1417      */
1418     JCExpression makeThis(DiagnosticPosition pos, TypeSymbol c) {
1419         if (currentClass == c) {
1420             // in this case, `this' works fine
1421             return make.at(pos).This(c.erasure(types));
1422         } else {
1423             // need to go via this$n
1424             return makeOuterThis(pos, c);
1425         }
1426     }
1427 
1428     /** Optionally replace a try statement with an automatic resource
1429      *  management (ARM) block.






























1430      * @param tree  The try statement to inspect.
1431      * @return      An ARM block, or the original try block if there are no
1432      *              resources to manage.
1433      */
1434     JCTree makeArmTry(JCTry tree) {
1435         make_at(tree.pos());
1436         twrVars = twrVars.dup();
1437         JCBlock armBlock = makeArmBlock(tree.resources, tree.body, 0);
1438         if (tree.catchers.isEmpty() && tree.finalizer == null)
1439             result = translate(armBlock);
1440         else
1441             result = translate(make.Try(armBlock, tree.catchers, tree.finalizer));
1442         twrVars = twrVars.leave();
1443         return result;
1444     }
1445 
1446     private JCBlock makeArmBlock(List<JCTree> resources, JCBlock block, int depth) {
1447         if (resources.isEmpty())
1448             return block;
1449 
1450         // Add resource declaration or expression to block statements
1451         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
1452         JCTree resource = resources.head;
1453         JCExpression expr = null;
1454         if (resource instanceof JCVariableDecl) {
1455             JCVariableDecl var = (JCVariableDecl) resource;
1456             expr = make.Ident(var.sym).setType(resource.type);
1457             stats.add(var);
1458         } else {
1459             Assert.check(resource instanceof JCExpression);
1460             VarSymbol syntheticTwrVar =
1461             new VarSymbol(SYNTHETIC | FINAL,
1462                           makeSyntheticName(names.fromString("twrVar" +
1463                                            depth), twrVars),
1464                           (resource.type.tag == TypeTags.BOT) ?
1465                           syms.autoCloseableType : resource.type,
1466                           currentMethodSym);


1480                           currentMethodSym);
1481         twrVars.enter(primaryException);
1482         JCVariableDecl primaryExceptionTreeDecl = make.VarDef(primaryException, makeNull());
1483         stats.add(primaryExceptionTreeDecl);
1484 
1485         // Create catch clause that saves exception and then rethrows it
1486         VarSymbol param =
1487             new VarSymbol(FINAL|SYNTHETIC,
1488                           names.fromString("t" +
1489                                            target.syntheticNameChar()),
1490                           syms.throwableType,
1491                           currentMethodSym);
1492         JCVariableDecl paramTree = make.VarDef(param, null);
1493         JCStatement assign = make.Assignment(primaryException, make.Ident(param));
1494         JCStatement rethrowStat = make.Throw(make.Ident(param));
1495         JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(assign, rethrowStat));
1496         JCCatch catchClause = make.Catch(paramTree, catchBlock);
1497 
1498         int oldPos = make.pos;
1499         make.at(TreeInfo.endPos(block));
1500         JCBlock finallyClause = makeArmFinallyClause(primaryException, expr);
1501         make.at(oldPos);
1502         JCTry outerTry = make.Try(makeArmBlock(resources.tail, block, depth + 1),
1503                                   List.<JCCatch>of(catchClause),
1504                                   finallyClause);
1505         stats.add(outerTry);
1506         return make.Block(0L, stats.toList());
1507     }
1508 
1509     private JCBlock makeArmFinallyClause(Symbol primaryException, JCExpression resource) {
1510         // primaryException.addSuppressed(catchException);
1511         VarSymbol catchException =
1512             new VarSymbol(0, make.paramName(2),
1513                           syms.throwableType,
1514                           currentMethodSym);
1515         JCStatement addSuppressionStatement =
1516             make.Exec(makeCall(make.Ident(primaryException),
1517                                names.addSuppressed,
1518                                List.<JCExpression>of(make.Ident(catchException))));
1519 
1520         // try { resource.close(); } catch (e) { primaryException.addSuppressed(e); }
1521         JCBlock tryBlock =
1522             make.Block(0L, List.<JCStatement>of(makeResourceCloseInvocation(resource)));
1523         JCVariableDecl catchExceptionDecl = make.VarDef(catchException, null);
1524         JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(addSuppressionStatement));
1525         List<JCCatch> catchClauses = List.<JCCatch>of(make.Catch(catchExceptionDecl, catchBlock));
1526         JCTry tryTree = make.Try(tryBlock, catchClauses, null);
1527 
1528         // if (resource != null) resourceClose;
1529         JCExpression nullCheck = makeBinary(JCTree.NE,
1530                                             make.Ident(primaryException),
1531                                             makeNull());
1532         JCIf closeIfStatement = make.If(nullCheck,
1533                                         tryTree,
1534                                         makeResourceCloseInvocation(resource));
1535         return make.Block(0L, List.<JCStatement>of(closeIfStatement));





1536     }
1537 
1538     private JCStatement makeResourceCloseInvocation(JCExpression resource) {
1539         // create resource.close() method invocation
1540         JCExpression resourceClose = makeCall(resource, names.close, List.<JCExpression>nil());


1541         return make.Exec(resourceClose);
1542     }
1543 




1544     /** Construct a tree that represents the outer instance
1545      *  <C.this>. Never pick the current `this'.
1546      *  @param pos           The source code position to be used for the tree.
1547      *  @param c             The qualifier class.
1548      */
1549     JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {
1550         List<VarSymbol> ots = outerThisStack;
1551         if (ots.isEmpty()) {
1552             log.error(pos, "no.encl.instance.of.type.in.scope", c);
1553             Assert.error();
1554             return makeNull();
1555         }
1556         VarSymbol ot = ots.head;
1557         JCExpression tree = access(make.at(pos).Ident(ot));
1558         TypeSymbol otc = ot.type.tsym;
1559         while (otc != c) {
1560             do {
1561                 ots = ots.tail;
1562                 if (ots.isEmpty()) {
1563                     log.error(pos,


3556             result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
3557     }
3558 
3559     public void visitLetExpr(LetExpr tree) {
3560         tree.defs = translateVarDefs(tree.defs);
3561         tree.expr = translate(tree.expr, tree.type);
3562         result = tree;
3563     }
3564 
3565     // There ought to be nothing to rewrite here;
3566     // we don't generate code.
3567     public void visitAnnotation(JCAnnotation tree) {
3568         result = tree;
3569     }
3570 
3571     @Override
3572     public void visitTry(JCTry tree) {
3573         if (tree.resources.isEmpty()) {
3574             super.visitTry(tree);
3575         } else {
3576             result = makeArmTry(tree);
3577         }
3578     }
3579 
3580 /**************************************************************************
3581  * main method
3582  *************************************************************************/
3583 
3584     /** Translate a toplevel class and return a list consisting of
3585      *  the translated class and translated versions of all inner classes.
3586      *  @param env   The attribution environment current at the class definition.
3587      *               We need this for resolving some additional symbols.
3588      *  @param cdef  The tree representing the class definition.
3589      */
3590     public List<JCTree> translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) {
3591         ListBuffer<JCTree> translated = null;
3592         try {
3593             attrEnv = env;
3594             this.make = make;
3595             endPositions = env.toplevel.endPositions;
3596             currentClass = null;




1408     }
1409 //where
1410         JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1411             return access(v, make.at(pos).Ident(v), null, false);
1412         }
1413 
1414     /** Construct a tree simulating the expression <C.this>.
1415      *  @param pos           The source code position to be used for the tree.
1416      *  @param c             The qualifier class.
1417      */
1418     JCExpression makeThis(DiagnosticPosition pos, TypeSymbol c) {
1419         if (currentClass == c) {
1420             // in this case, `this' works fine
1421             return make.at(pos).This(c.erasure(types));
1422         } else {
1423             // need to go via this$n
1424             return makeOuterThis(pos, c);
1425         }
1426     }
1427 
1428     /**
1429      * Optionally replace a try statement with the desugaring of a
1430      * try-with-resources statement.  The canonical desugaring of
1431      *
1432      * try ResourceSpecification
1433      *   Block
1434      *
1435      * is
1436      *
1437      * {
1438      *   final VariableModifiers_minus_final R #resource = Expression;
1439      *   Throwable #primaryException = null;
1440      *
1441      *   try ResourceSpecificationtail
1442      *     Block
1443      *   catch (Throwable #t) {
1444      *     #primaryException = t;
1445      *     throw #t;
1446      *   } finally {
1447      *     if (#resource != null) {
1448      *       if (#primaryException != null) {
1449      *         try {
1450      *           #resource.close();
1451      *         } catch(Throwable #suppressedException) {
1452      *           #primaryException.addSuppressed(#suppressedException);
1453      *         }
1454      *       } else {
1455      *         #resource.close();
1456      *       }
1457      *     }
1458      *   }
1459      *
1460      * @param tree  The try statement to inspect.
1461      * @return A a desugared try-with-resources tree, or the original
1462      * try block if there are no resources to manage.
1463      */
1464     JCTree makeTwrTry(JCTry tree) {
1465         make_at(tree.pos());
1466         twrVars = twrVars.dup();
1467         JCBlock twrBlock = makeTwrBlock(tree.resources, tree.body, 0);
1468         if (tree.catchers.isEmpty() && tree.finalizer == null)
1469             result = translate(twrBlock);
1470         else
1471             result = translate(make.Try(twrBlock, tree.catchers, tree.finalizer));
1472         twrVars = twrVars.leave();
1473         return result;
1474     }
1475 
1476     private JCBlock makeTwrBlock(List<JCTree> resources, JCBlock block, int depth) {
1477         if (resources.isEmpty())
1478             return block;
1479 
1480         // Add resource declaration or expression to block statements
1481         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
1482         JCTree resource = resources.head;
1483         JCExpression expr = null;
1484         if (resource instanceof JCVariableDecl) {
1485             JCVariableDecl var = (JCVariableDecl) resource;
1486             expr = make.Ident(var.sym).setType(resource.type);
1487             stats.add(var);
1488         } else {
1489             Assert.check(resource instanceof JCExpression);
1490             VarSymbol syntheticTwrVar =
1491             new VarSymbol(SYNTHETIC | FINAL,
1492                           makeSyntheticName(names.fromString("twrVar" +
1493                                            depth), twrVars),
1494                           (resource.type.tag == TypeTags.BOT) ?
1495                           syms.autoCloseableType : resource.type,
1496                           currentMethodSym);


1510                           currentMethodSym);
1511         twrVars.enter(primaryException);
1512         JCVariableDecl primaryExceptionTreeDecl = make.VarDef(primaryException, makeNull());
1513         stats.add(primaryExceptionTreeDecl);
1514 
1515         // Create catch clause that saves exception and then rethrows it
1516         VarSymbol param =
1517             new VarSymbol(FINAL|SYNTHETIC,
1518                           names.fromString("t" +
1519                                            target.syntheticNameChar()),
1520                           syms.throwableType,
1521                           currentMethodSym);
1522         JCVariableDecl paramTree = make.VarDef(param, null);
1523         JCStatement assign = make.Assignment(primaryException, make.Ident(param));
1524         JCStatement rethrowStat = make.Throw(make.Ident(param));
1525         JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(assign, rethrowStat));
1526         JCCatch catchClause = make.Catch(paramTree, catchBlock);
1527 
1528         int oldPos = make.pos;
1529         make.at(TreeInfo.endPos(block));
1530         JCBlock finallyClause = makeTwrFinallyClause(primaryException, expr);
1531         make.at(oldPos);
1532         JCTry outerTry = make.Try(makeTwrBlock(resources.tail, block, depth + 1),
1533                                   List.<JCCatch>of(catchClause),
1534                                   finallyClause);
1535         stats.add(outerTry);
1536         return make.Block(0L, stats.toList());
1537     }
1538 
1539     private JCBlock makeTwrFinallyClause(Symbol primaryException, JCExpression resource) {
1540         // primaryException.addSuppressed(catchException);
1541         VarSymbol catchException =
1542             new VarSymbol(0, make.paramName(2),
1543                           syms.throwableType,
1544                           currentMethodSym);
1545         JCStatement addSuppressionStatement =
1546             make.Exec(makeCall(make.Ident(primaryException),
1547                                names.addSuppressed,
1548                                List.<JCExpression>of(make.Ident(catchException))));
1549 
1550         // try { resource.close(); } catch (e) { primaryException.addSuppressed(e); }
1551         JCBlock tryBlock =
1552             make.Block(0L, List.<JCStatement>of(makeResourceCloseInvocation(resource)));
1553         JCVariableDecl catchExceptionDecl = make.VarDef(catchException, null);
1554         JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(addSuppressionStatement));
1555         List<JCCatch> catchClauses = List.<JCCatch>of(make.Catch(catchExceptionDecl, catchBlock));
1556         JCTry tryTree = make.Try(tryBlock, catchClauses, null);
1557 
1558         // if (primaryException != null) {try...} else resourceClose;
1559         JCIf closeIfStatement = make.If(makeNonNullCheck(make.Ident(primaryException)),



1560                                         tryTree,
1561                                         makeResourceCloseInvocation(resource));
1562 
1563         // if (#resource != null) { if (primaryException ...  }
1564         return make.Block(0L,
1565                           List.<JCStatement>of(make.If(makeNonNullCheck(resource),
1566                                                        closeIfStatement,
1567                                                        null)));
1568     }
1569 
1570     private JCStatement makeResourceCloseInvocation(JCExpression resource) {
1571         // create resource.close() method invocation
1572         JCExpression resourceClose = makeCall(resource,
1573                                               names.close,
1574                                               List.<JCExpression>nil());
1575         return make.Exec(resourceClose);
1576     }
1577 
1578     private JCExpression makeNonNullCheck(JCExpression expression) {
1579         return makeBinary(JCTree.NE, expression, makeNull());
1580     }
1581 
1582     /** Construct a tree that represents the outer instance
1583      *  <C.this>. Never pick the current `this'.
1584      *  @param pos           The source code position to be used for the tree.
1585      *  @param c             The qualifier class.
1586      */
1587     JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {
1588         List<VarSymbol> ots = outerThisStack;
1589         if (ots.isEmpty()) {
1590             log.error(pos, "no.encl.instance.of.type.in.scope", c);
1591             Assert.error();
1592             return makeNull();
1593         }
1594         VarSymbol ot = ots.head;
1595         JCExpression tree = access(make.at(pos).Ident(ot));
1596         TypeSymbol otc = ot.type.tsym;
1597         while (otc != c) {
1598             do {
1599                 ots = ots.tail;
1600                 if (ots.isEmpty()) {
1601                     log.error(pos,


3594             result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
3595     }
3596 
3597     public void visitLetExpr(LetExpr tree) {
3598         tree.defs = translateVarDefs(tree.defs);
3599         tree.expr = translate(tree.expr, tree.type);
3600         result = tree;
3601     }
3602 
3603     // There ought to be nothing to rewrite here;
3604     // we don't generate code.
3605     public void visitAnnotation(JCAnnotation tree) {
3606         result = tree;
3607     }
3608 
3609     @Override
3610     public void visitTry(JCTry tree) {
3611         if (tree.resources.isEmpty()) {
3612             super.visitTry(tree);
3613         } else {
3614             result = makeTwrTry(tree);
3615         }
3616     }
3617 
3618 /**************************************************************************
3619  * main method
3620  *************************************************************************/
3621 
3622     /** Translate a toplevel class and return a list consisting of
3623      *  the translated class and translated versions of all inner classes.
3624      *  @param env   The attribution environment current at the class definition.
3625      *               We need this for resolving some additional symbols.
3626      *  @param cdef  The tree representing the class definition.
3627      */
3628     public List<JCTree> translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) {
3629         ListBuffer<JCTree> translated = null;
3630         try {
3631             attrEnv = env;
3632             this.make = make;
3633             endPositions = env.toplevel.endPositions;
3634             currentClass = null;