langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java
changeset 8434 afb406fc66fe
parent 8242 3873b4aaf4a8
child 8622 4f032629a0fd
equal deleted inserted replaced
8433:2f2222b89463 8434:afb406fc66fe
  1423             // need to go via this$n
  1423             // need to go via this$n
  1424             return makeOuterThis(pos, c);
  1424             return makeOuterThis(pos, c);
  1425         }
  1425         }
  1426     }
  1426     }
  1427 
  1427 
  1428     /** Optionally replace a try statement with an automatic resource
  1428     /**
  1429      *  management (ARM) block.
  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      *
  1430      * @param tree  The try statement to inspect.
  1460      * @param tree  The try statement to inspect.
  1431      * @return      An ARM block, or the original try block if there are no
  1461      * @return A a desugared try-with-resources tree, or the original
  1432      *              resources to manage.
  1462      * try block if there are no resources to manage.
  1433      */
  1463      */
  1434     JCTree makeArmTry(JCTry tree) {
  1464     JCTree makeTwrTry(JCTry tree) {
  1435         make_at(tree.pos());
  1465         make_at(tree.pos());
  1436         twrVars = twrVars.dup();
  1466         twrVars = twrVars.dup();
  1437         JCBlock armBlock = makeArmBlock(tree.resources, tree.body, 0);
  1467         JCBlock twrBlock = makeTwrBlock(tree.resources, tree.body, 0);
  1438         if (tree.catchers.isEmpty() && tree.finalizer == null)
  1468         if (tree.catchers.isEmpty() && tree.finalizer == null)
  1439             result = translate(armBlock);
  1469             result = translate(twrBlock);
  1440         else
  1470         else
  1441             result = translate(make.Try(armBlock, tree.catchers, tree.finalizer));
  1471             result = translate(make.Try(twrBlock, tree.catchers, tree.finalizer));
  1442         twrVars = twrVars.leave();
  1472         twrVars = twrVars.leave();
  1443         return result;
  1473         return result;
  1444     }
  1474     }
  1445 
  1475 
  1446     private JCBlock makeArmBlock(List<JCTree> resources, JCBlock block, int depth) {
  1476     private JCBlock makeTwrBlock(List<JCTree> resources, JCBlock block, int depth) {
  1447         if (resources.isEmpty())
  1477         if (resources.isEmpty())
  1448             return block;
  1478             return block;
  1449 
  1479 
  1450         // Add resource declaration or expression to block statements
  1480         // Add resource declaration or expression to block statements
  1451         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
  1481         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
  1495         JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(assign, rethrowStat));
  1525         JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(assign, rethrowStat));
  1496         JCCatch catchClause = make.Catch(paramTree, catchBlock);
  1526         JCCatch catchClause = make.Catch(paramTree, catchBlock);
  1497 
  1527 
  1498         int oldPos = make.pos;
  1528         int oldPos = make.pos;
  1499         make.at(TreeInfo.endPos(block));
  1529         make.at(TreeInfo.endPos(block));
  1500         JCBlock finallyClause = makeArmFinallyClause(primaryException, expr);
  1530         JCBlock finallyClause = makeTwrFinallyClause(primaryException, expr);
  1501         make.at(oldPos);
  1531         make.at(oldPos);
  1502         JCTry outerTry = make.Try(makeArmBlock(resources.tail, block, depth + 1),
  1532         JCTry outerTry = make.Try(makeTwrBlock(resources.tail, block, depth + 1),
  1503                                   List.<JCCatch>of(catchClause),
  1533                                   List.<JCCatch>of(catchClause),
  1504                                   finallyClause);
  1534                                   finallyClause);
  1505         stats.add(outerTry);
  1535         stats.add(outerTry);
  1506         return make.Block(0L, stats.toList());
  1536         return make.Block(0L, stats.toList());
  1507     }
  1537     }
  1508 
  1538 
  1509     private JCBlock makeArmFinallyClause(Symbol primaryException, JCExpression resource) {
  1539     private JCBlock makeTwrFinallyClause(Symbol primaryException, JCExpression resource) {
  1510         // primaryException.addSuppressed(catchException);
  1540         // primaryException.addSuppressed(catchException);
  1511         VarSymbol catchException =
  1541         VarSymbol catchException =
  1512             new VarSymbol(0, make.paramName(2),
  1542             new VarSymbol(0, make.paramName(2),
  1513                           syms.throwableType,
  1543                           syms.throwableType,
  1514                           currentMethodSym);
  1544                           currentMethodSym);
  1523         JCVariableDecl catchExceptionDecl = make.VarDef(catchException, null);
  1553         JCVariableDecl catchExceptionDecl = make.VarDef(catchException, null);
  1524         JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(addSuppressionStatement));
  1554         JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(addSuppressionStatement));
  1525         List<JCCatch> catchClauses = List.<JCCatch>of(make.Catch(catchExceptionDecl, catchBlock));
  1555         List<JCCatch> catchClauses = List.<JCCatch>of(make.Catch(catchExceptionDecl, catchBlock));
  1526         JCTry tryTree = make.Try(tryBlock, catchClauses, null);
  1556         JCTry tryTree = make.Try(tryBlock, catchClauses, null);
  1527 
  1557 
  1528         // if (resource != null) resourceClose;
  1558         // if (primaryException != null) {try...} else resourceClose;
  1529         JCExpression nullCheck = makeBinary(JCTree.NE,
  1559         JCIf closeIfStatement = make.If(makeNonNullCheck(make.Ident(primaryException)),
  1530                                             make.Ident(primaryException),
       
  1531                                             makeNull());
       
  1532         JCIf closeIfStatement = make.If(nullCheck,
       
  1533                                         tryTree,
  1560                                         tryTree,
  1534                                         makeResourceCloseInvocation(resource));
  1561                                         makeResourceCloseInvocation(resource));
  1535         return make.Block(0L, List.<JCStatement>of(closeIfStatement));
  1562 
       
  1563         // if (#resource != null) { if (primaryException ...  }
       
  1564         return make.Block(0L,
       
  1565                           List.<JCStatement>of(make.If(makeNonNullCheck(resource),
       
  1566                                                        closeIfStatement,
       
  1567                                                        null)));
  1536     }
  1568     }
  1537 
  1569 
  1538     private JCStatement makeResourceCloseInvocation(JCExpression resource) {
  1570     private JCStatement makeResourceCloseInvocation(JCExpression resource) {
  1539         // create resource.close() method invocation
  1571         // create resource.close() method invocation
  1540         JCExpression resourceClose = makeCall(resource, names.close, List.<JCExpression>nil());
  1572         JCExpression resourceClose = makeCall(resource,
       
  1573                                               names.close,
       
  1574                                               List.<JCExpression>nil());
  1541         return make.Exec(resourceClose);
  1575         return make.Exec(resourceClose);
       
  1576     }
       
  1577 
       
  1578     private JCExpression makeNonNullCheck(JCExpression expression) {
       
  1579         return makeBinary(JCTree.NE, expression, makeNull());
  1542     }
  1580     }
  1543 
  1581 
  1544     /** Construct a tree that represents the outer instance
  1582     /** Construct a tree that represents the outer instance
  1545      *  <C.this>. Never pick the current `this'.
  1583      *  <C.this>. Never pick the current `this'.
  1546      *  @param pos           The source code position to be used for the tree.
  1584      *  @param pos           The source code position to be used for the tree.
  3571     @Override
  3609     @Override
  3572     public void visitTry(JCTry tree) {
  3610     public void visitTry(JCTry tree) {
  3573         if (tree.resources.isEmpty()) {
  3611         if (tree.resources.isEmpty()) {
  3574             super.visitTry(tree);
  3612             super.visitTry(tree);
  3575         } else {
  3613         } else {
  3576             result = makeArmTry(tree);
  3614             result = makeTwrTry(tree);
  3577         }
  3615         }
  3578     }
  3616     }
  3579 
  3617 
  3580 /**************************************************************************
  3618 /**************************************************************************
  3581  * main method
  3619  * main method