9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.javac.comp;
27
28 import java.util.*;
29
30 import javax.lang.model.element.ElementKind;
31 import javax.tools.JavaFileObject;
32
33 import com.sun.source.tree.IdentifierTree;
34 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
35 import com.sun.source.tree.MemberSelectTree;
36 import com.sun.source.tree.TreeVisitor;
37 import com.sun.source.util.SimpleTreeVisitor;
38 import com.sun.tools.javac.code.*;
39 import com.sun.tools.javac.code.Lint.LintCategory;
40 import com.sun.tools.javac.code.Scope.WriteableScope;
41 import com.sun.tools.javac.code.Source.Feature;
42 import com.sun.tools.javac.code.Symbol.*;
43 import com.sun.tools.javac.code.Type.*;
44 import com.sun.tools.javac.code.TypeMetadata.Annotations;
45 import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError;
46 import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext;
47 import com.sun.tools.javac.comp.Check.CheckContext;
48 import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
49 import com.sun.tools.javac.jvm.*;
50 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.Diamond;
51 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.DiamondInvalidArg;
52 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.DiamondInvalidArgs;
688 }
689
690 WriteableScope copyScope(WriteableScope sc) {
691 WriteableScope newScope = WriteableScope.create(sc.owner);
692 List<Symbol> elemsList = List.nil();
693 for (Symbol sym : sc.getSymbols()) {
694 elemsList = elemsList.prepend(sym);
695 }
696 for (Symbol s : elemsList) {
697 newScope.enter(s);
698 }
699 return newScope;
700 }
701
702 /** Derived visitor method: attribute an expression tree.
703 */
704 public Type attribExpr(JCTree tree, Env<AttrContext> env, Type pt) {
705 return attribTree(tree, env, new ResultInfo(KindSelector.VAL, !pt.hasTag(ERROR) ? pt : Type.noType));
706 }
707
708 /** Derived visitor method: attribute an expression tree with
709 * no constraints on the computed type.
710 */
711 public Type attribExpr(JCTree tree, Env<AttrContext> env) {
712 return attribTree(tree, env, unknownExprInfo);
713 }
714
715 /** Derived visitor method: attribute a type tree.
716 */
717 public Type attribType(JCTree tree, Env<AttrContext> env) {
718 Type result = attribType(tree, env, Type.noType);
719 return result;
720 }
721
722 /** Derived visitor method: attribute a type tree.
723 */
724 Type attribType(JCTree tree, Env<AttrContext> env, Type pt) {
725 Type result = attribTree(tree, env, new ResultInfo(KindSelector.TYP, pt));
726 return result;
727 }
1378 }
1379
1380 public void visitLabelled(JCLabeledStatement tree) {
1381 // Check that label is not used in an enclosing statement
1382 Env<AttrContext> env1 = env;
1383 while (env1 != null && !env1.tree.hasTag(CLASSDEF)) {
1384 if (env1.tree.hasTag(LABELLED) &&
1385 ((JCLabeledStatement) env1.tree).label == tree.label) {
1386 log.error(tree.pos(),
1387 Errors.LabelAlreadyInUse(tree.label));
1388 break;
1389 }
1390 env1 = env1.next;
1391 }
1392
1393 attribStat(tree.body, env.dup(tree));
1394 result = null;
1395 }
1396
1397 public void visitSwitch(JCSwitch tree) {
1398 Type seltype = attribExpr(tree.selector, env);
1399
1400 Env<AttrContext> switchEnv =
1401 env.dup(tree, env.info.dup(env.info.scope.dup()));
1402
1403 try {
1404
1405 boolean enumSwitch = (seltype.tsym.flags() & Flags.ENUM) != 0;
1406 boolean stringSwitch = types.isSameType(seltype, syms.stringType);
1407 if (!enumSwitch && !stringSwitch)
1408 seltype = chk.checkType(tree.selector.pos(), seltype, syms.intType);
1409
1410 // Attribute all cases and
1411 // check that there are no duplicate case labels or default clauses.
1412 Set<Object> labels = new HashSet<>(); // The set of case labels.
1413 boolean hasDefault = false; // Is there a default label?
1414 for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
1415 JCCase c = l.head;
1416 if (c.pat != null) {
1417 if (enumSwitch) {
1418 Symbol sym = enumConstant(c.pat, seltype);
1419 if (sym == null) {
1420 log.error(c.pat.pos(), Errors.EnumLabelMustBeUnqualifiedEnum);
1421 } else if (!labels.add(sym)) {
1422 log.error(c.pos(), Errors.DuplicateCaseLabel);
1423 }
1424 } else {
1425 Type pattype = attribExpr(c.pat, switchEnv, seltype);
1426 if (!pattype.hasTag(ERROR)) {
1427 if (pattype.constValue() == null) {
1428 log.error(c.pat.pos(),
1429 (stringSwitch ? Errors.StringConstReq : Errors.ConstExprReq));
1430 } else if (!labels.add(pattype.constValue())) {
1431 log.error(c.pos(), Errors.DuplicateCaseLabel);
1432 }
1433 }
1434 }
1435 } else if (hasDefault) {
1436 log.error(c.pos(), Errors.DuplicateDefaultLabel);
1437 } else {
1438 hasDefault = true;
1439 }
1440 Env<AttrContext> caseEnv =
1441 switchEnv.dup(c, env.info.dup(switchEnv.info.scope.dup()));
1442 try {
1443 attribStats(c.stats, caseEnv);
1444 } finally {
1445 caseEnv.info.scope.leave();
1446 addVars(c.stats, switchEnv.info.scope);
1447 }
1448 }
1449
1450 result = null;
1451 }
1452 finally {
1453 switchEnv.info.scope.leave();
1454 }
1455 }
1456 // where
1457 /** Add any variables defined in stats to the switch scope. */
1458 private static void addVars(List<JCStatement> stats, WriteableScope switchScope) {
1459 for (;stats.nonEmpty(); stats = stats.tail) {
1460 JCTree stat = stats.head;
1461 if (stat.hasTag(VARDEF))
1462 switchScope.enter(((JCVariableDecl) stat).sym);
1463 }
1464 }
1465 // where
1466 /** Return the selected enumeration constant symbol, or null. */
1467 private Symbol enumConstant(JCTree tree, Type enumType) {
1468 if (tree.hasTag(IDENT)) {
1469 JCIdent ident = (JCIdent)tree;
1470 Name name = ident.name;
1471 for (Symbol sym : enumType.tsym.members().getSymbolsByName(name)) {
1472 if (sym.kind == VAR) {
1592
1593 tree.polyKind = (!allowPoly ||
1594 pt().hasTag(NONE) && pt() != Type.recoveryType && pt() != Infer.anyPoly ||
1595 isBooleanOrNumeric(env, tree)) ?
1596 PolyKind.STANDALONE : PolyKind.POLY;
1597
1598 if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) {
1599 //this means we are returning a poly conditional from void-compatible lambda expression
1600 resultInfo.checkContext.report(tree, diags.fragment(Fragments.ConditionalTargetCantBeVoid));
1601 result = tree.type = types.createErrorType(resultInfo.pt);
1602 return;
1603 }
1604
1605 ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ?
1606 unknownExprInfo :
1607 resultInfo.dup(conditionalContext(resultInfo.checkContext));
1608
1609 Type truetype = attribTree(tree.truepart, env, condInfo);
1610 Type falsetype = attribTree(tree.falsepart, env, condInfo);
1611
1612 Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(tree, truetype, falsetype) : pt();
1613 if (condtype.constValue() != null &&
1614 truetype.constValue() != null &&
1615 falsetype.constValue() != null &&
1616 !owntype.hasTag(NONE)) {
1617 //constant folding
1618 owntype = cfolder.coerce(condtype.isTrue() ? truetype : falsetype, owntype);
1619 }
1620 result = check(tree, owntype, KindSelector.VAL, resultInfo);
1621 }
1622 //where
1623 private boolean isBooleanOrNumeric(Env<AttrContext> env, JCExpression tree) {
1624 switch (tree.getTag()) {
1625 case LITERAL: return ((JCLiteral)tree).typetag.isSubRangeOf(DOUBLE) ||
1626 ((JCLiteral)tree).typetag == BOOLEAN ||
1627 ((JCLiteral)tree).typetag == BOT;
1628 case LAMBDA: case REFERENCE: return false;
1629 case PARENS: return isBooleanOrNumeric(env, ((JCParens)tree).expr);
1630 case CONDEXPR:
1631 JCConditional condTree = (JCConditional)tree;
1632 return isBooleanOrNumeric(env, condTree.truepart) &&
1674 //subexpression against target type; if we are in a method check context,
1675 //depending on whether boxing is allowed, we could have incompatibilities
1676 @Override
1677 public void report(DiagnosticPosition pos, JCDiagnostic details) {
1678 enclosingContext.report(pos, diags.fragment(Fragments.IncompatibleTypeInConditional(details)));
1679 }
1680 };
1681 }
1682
1683 /** Compute the type of a conditional expression, after
1684 * checking that it exists. See JLS 15.25. Does not take into
1685 * account the special case where condition and both arms
1686 * are constants.
1687 *
1688 * @param pos The source position to be used for error
1689 * diagnostics.
1690 * @param thentype The type of the expression's then-part.
1691 * @param elsetype The type of the expression's else-part.
1692 */
1693 Type condType(DiagnosticPosition pos,
1694 Type thentype, Type elsetype) {
1695 // If same type, that is the result
1696 if (types.isSameType(thentype, elsetype))
1697 return thentype.baseType();
1698
1699 Type thenUnboxed = (thentype.isPrimitive())
1700 ? thentype : types.unboxedType(thentype);
1701 Type elseUnboxed = (elsetype.isPrimitive())
1702 ? elsetype : types.unboxedType(elsetype);
1703
1704 // Otherwise, if both arms can be converted to a numeric
1705 // type, return the least numeric type that fits both arms
1706 // (i.e. return larger of the two, or return int if one
1707 // arm is short, the other is char).
1708 if (thenUnboxed.isPrimitive() && elseUnboxed.isPrimitive()) {
1709 // If one arm has an integer subrange type (i.e., byte,
1710 // short, or char), and the other is an integer constant
1711 // that fits into the subrange, return the subrange type.
1712 if (thenUnboxed.getTag().isStrictSubRangeOf(INT) &&
1713 elseUnboxed.hasTag(INT) &&
1714 types.isAssignable(elseUnboxed, thenUnboxed)) {
1715 return thenUnboxed.baseType();
1716 }
1717 if (elseUnboxed.getTag().isStrictSubRangeOf(INT) &&
1718 thenUnboxed.hasTag(INT) &&
1719 types.isAssignable(thenUnboxed, elseUnboxed)) {
1720 return elseUnboxed.baseType();
1721 }
1722
1723 for (TypeTag tag : primitiveTags) {
1724 Type candidate = syms.typeOfTag[tag.ordinal()];
1725 if (types.isSubtype(thenUnboxed, candidate) &&
1726 types.isSubtype(elseUnboxed, candidate)) {
1727 return candidate;
1728 }
1729 }
1730 }
1731
1732 // Those were all the cases that could result in a primitive
1733 if (thentype.isPrimitive())
1734 thentype = types.boxedClass(thentype).type;
1735 if (elsetype.isPrimitive())
1736 elsetype = types.boxedClass(elsetype).type;
1737
1738 if (types.isSubtype(thentype, elsetype))
1739 return elsetype.baseType();
1740 if (types.isSubtype(elsetype, thentype))
1741 return thentype.baseType();
1742
1743 if (thentype.hasTag(VOID) || elsetype.hasTag(VOID)) {
1744 log.error(pos,
1745 Errors.NeitherConditionalSubtype(thentype,
1746 elsetype));
1747 return thentype.baseType();
1748 }
1749
1750 // both are known to be reference types. The result is
1751 // lub(thentype,elsetype). This cannot fail, as it will
1752 // always be possible to infer "Object" if nothing better.
1753 return types.lub(thentype.baseType(), elsetype.baseType());
1754 }
1755
1756 final static TypeTag[] primitiveTags = new TypeTag[]{
1757 BYTE,
1758 CHAR,
1759 SHORT,
1760 INT,
1761 LONG,
1762 FLOAT,
1763 DOUBLE,
1764 BOOLEAN,
1765 };
1766
1767 public void visitIf(JCIf tree) {
1768 attribExpr(tree.cond, env, syms.booleanType);
1769 attribStat(tree.thenpart, env);
1770 if (tree.elsepart != null)
1771 attribStat(tree.elsepart, env);
1772 chk.checkEmptyIf(tree);
1773 result = null;
1774 }
1775
1776 public void visitExec(JCExpressionStatement tree) {
1777 //a fresh environment is required for 292 inference to work properly ---
1778 //see Infer.instantiatePolymorphicSignatureInstance()
1779 Env<AttrContext> localEnv = env.dup(tree);
1780 attribExpr(tree.expr, localEnv);
1781 result = null;
1782 }
1783
1784 public void visitBreak(JCBreak tree) {
1785 tree.target = findJumpTarget(tree.pos(), tree.getTag(), tree.label, env);
1786 result = null;
1787 }
1788
1789 public void visitContinue(JCContinue tree) {
1790 tree.target = findJumpTarget(tree.pos(), tree.getTag(), tree.label, env);
1791 result = null;
1792 }
1793 //where
1794 /** Return the target of a break or continue statement, if it exists,
1795 * report an error if not.
1796 * Note: The target of a labelled break or continue is the
1797 * (non-labelled) statement tree referred to by the label,
1798 * not the tree representing the labelled statement itself.
1799 *
1800 * @param pos The position to be used for error diagnostics
1801 * @param tag The tag of the jump statement. This is either
1802 * Tree.BREAK or Tree.CONTINUE.
1803 * @param label The label of the jump statement, or null if no
1804 * label is given.
1805 * @param env The environment current at the jump statement.
1806 */
1807 private JCTree findJumpTarget(DiagnosticPosition pos,
1808 JCTree.Tag tag,
1809 Name label,
1810 Env<AttrContext> env) {
1811 // Search environments outwards from the point of jump.
1812 Env<AttrContext> env1 = env;
1813 LOOP:
1814 while (env1 != null) {
1815 switch (env1.tree.getTag()) {
1816 case LABELLED:
1817 JCLabeledStatement labelled = (JCLabeledStatement)env1.tree;
1818 if (label == labelled.label) {
1819 // If jump is a continue, check that target is a loop.
1820 if (tag == CONTINUE) {
1821 if (!labelled.body.hasTag(DOLOOP) &&
1822 !labelled.body.hasTag(WHILELOOP) &&
1823 !labelled.body.hasTag(FORLOOP) &&
1824 !labelled.body.hasTag(FOREACHLOOP))
1825 log.error(pos, Errors.NotLoopLabel(label));
1826 // Found labelled statement target, now go inwards
1827 // to next non-labelled tree.
1828 return TreeInfo.referencedStatement(labelled);
1829 } else {
1830 return labelled;
1831 }
1832 }
1833 break;
1834 case DOLOOP:
1835 case WHILELOOP:
1836 case FORLOOP:
1837 case FOREACHLOOP:
1838 if (label == null) return env1.tree;
1839 break;
1840 case SWITCH:
1841 if (label == null && tag == BREAK) return env1.tree;
1842 break;
1843 case LAMBDA:
1844 case METHODDEF:
1845 case CLASSDEF:
1846 break LOOP;
1847 default:
1848 }
1849 env1 = env1.next;
1850 }
1851 if (label != null)
1852 log.error(pos, Errors.UndefLabel(label));
1853 else if (tag == CONTINUE)
1854 log.error(pos, Errors.ContOutsideLoop);
1855 else
1856 log.error(pos, Errors.BreakOutsideSwitchLoop);
1857 return null;
1858 }
1859
1860 public void visitReturn(JCReturn tree) {
1861 // Check that there is an enclosing method which is
1862 // nested within than the enclosing class.
1863 if (env.info.returnResult == null) {
1864 log.error(tree.pos(), Errors.RetOutsideMeth);
1865 } else {
1866 // Attribute return expression, if it exists, and check that
1867 // it conforms to result type of enclosing method.
1868 if (tree.expr != null) {
1869 if (env.info.returnResult.pt.hasTag(VOID)) {
1870 env.info.returnResult.checkContext.report(tree.expr.pos(),
1871 diags.fragment(Fragments.UnexpectedRetVal));
1872 }
1873 attribTree(tree.expr, env, env.info.returnResult);
1874 } else if (!env.info.returnResult.pt.hasTag(VOID) &&
1875 !env.info.returnResult.pt.hasTag(NONE)) {
1876 env.info.returnResult.checkContext.report(tree.pos(),
1877 diags.fragment(Fragments.MissingRetVal(env.info.returnResult.pt)));
1878 }
1879 }
1880 result = null;
1881 }
1882
1883 public void visitThrow(JCThrow tree) {
1884 Type owntype = attribExpr(tree.expr, env, allowPoly ? Type.noType : syms.throwableType);
2927 }
2928 } else {
2929 /* if the field is static then we need to create a fake clinit
2930 * method, this method can later be reused by LTM.
2931 */
2932 MethodSymbol clinit = clinits.get(enclClass);
2933 if (clinit == null) {
2934 Type clinitType = new MethodType(List.nil(),
2935 syms.voidType, List.nil(), syms.methodClass);
2936 clinit = new MethodSymbol(STATIC | SYNTHETIC | PRIVATE,
2937 names.clinit, clinitType, enclClass);
2938 clinit.params = List.nil();
2939 clinits.put(enclClass, clinit);
2940 }
2941 newScopeOwner = clinit;
2942 }
2943 lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dupUnshared(newScopeOwner)));
2944 } else {
2945 lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dup()));
2946 }
2947 return lambdaEnv;
2948 }
2949
2950 @Override
2951 public void visitReference(final JCMemberReference that) {
2952 if (pt().isErroneous() || (pt().hasTag(NONE) && pt() != Type.recoveryType)) {
2953 if (pt().hasTag(NONE) && (env.info.enclVar == null || !env.info.enclVar.type.isErroneous())) {
2954 //method reference only allowed in assignment or method invocation/cast context
2955 log.error(that.pos(), Errors.UnexpectedMref);
2956 }
2957 result = that.type = types.createErrorType(pt());
2958 return;
2959 }
2960 final Env<AttrContext> localEnv = env.dup(that);
2961 try {
2962 //attribute member reference qualifier - if this is a constructor
2963 //reference, the expected kind must be a type
2964 Type exprType = attribTree(that.expr, env, memberReferenceQualifierResult(that));
2965
2966 if (that.getMode() == JCMemberReference.ReferenceMode.NEW) {
|
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.javac.comp;
27
28 import java.util.*;
29 import java.util.function.BiConsumer;
30
31 import javax.lang.model.element.ElementKind;
32 import javax.tools.JavaFileObject;
33
34 import com.sun.source.tree.CaseTree.CaseKind;
35 import com.sun.source.tree.IdentifierTree;
36 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
37 import com.sun.source.tree.MemberSelectTree;
38 import com.sun.source.tree.TreeVisitor;
39 import com.sun.source.util.SimpleTreeVisitor;
40 import com.sun.tools.javac.code.*;
41 import com.sun.tools.javac.code.Lint.LintCategory;
42 import com.sun.tools.javac.code.Scope.WriteableScope;
43 import com.sun.tools.javac.code.Source.Feature;
44 import com.sun.tools.javac.code.Symbol.*;
45 import com.sun.tools.javac.code.Type.*;
46 import com.sun.tools.javac.code.TypeMetadata.Annotations;
47 import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError;
48 import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext;
49 import com.sun.tools.javac.comp.Check.CheckContext;
50 import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
51 import com.sun.tools.javac.jvm.*;
52 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.Diamond;
53 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.DiamondInvalidArg;
54 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.DiamondInvalidArgs;
690 }
691
692 WriteableScope copyScope(WriteableScope sc) {
693 WriteableScope newScope = WriteableScope.create(sc.owner);
694 List<Symbol> elemsList = List.nil();
695 for (Symbol sym : sc.getSymbols()) {
696 elemsList = elemsList.prepend(sym);
697 }
698 for (Symbol s : elemsList) {
699 newScope.enter(s);
700 }
701 return newScope;
702 }
703
704 /** Derived visitor method: attribute an expression tree.
705 */
706 public Type attribExpr(JCTree tree, Env<AttrContext> env, Type pt) {
707 return attribTree(tree, env, new ResultInfo(KindSelector.VAL, !pt.hasTag(ERROR) ? pt : Type.noType));
708 }
709
710 /** Derived visitor method: attribute an expression tree.
711 */
712 public Type attribExpr(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) {
713 return attribTree(tree, env, resultInfo);
714 }
715
716 /** Derived visitor method: attribute an expression tree with
717 * no constraints on the computed type.
718 */
719 public Type attribExpr(JCTree tree, Env<AttrContext> env) {
720 return attribTree(tree, env, unknownExprInfo);
721 }
722
723 /** Derived visitor method: attribute a type tree.
724 */
725 public Type attribType(JCTree tree, Env<AttrContext> env) {
726 Type result = attribType(tree, env, Type.noType);
727 return result;
728 }
729
730 /** Derived visitor method: attribute a type tree.
731 */
732 Type attribType(JCTree tree, Env<AttrContext> env, Type pt) {
733 Type result = attribTree(tree, env, new ResultInfo(KindSelector.TYP, pt));
734 return result;
735 }
1386 }
1387
1388 public void visitLabelled(JCLabeledStatement tree) {
1389 // Check that label is not used in an enclosing statement
1390 Env<AttrContext> env1 = env;
1391 while (env1 != null && !env1.tree.hasTag(CLASSDEF)) {
1392 if (env1.tree.hasTag(LABELLED) &&
1393 ((JCLabeledStatement) env1.tree).label == tree.label) {
1394 log.error(tree.pos(),
1395 Errors.LabelAlreadyInUse(tree.label));
1396 break;
1397 }
1398 env1 = env1.next;
1399 }
1400
1401 attribStat(tree.body, env.dup(tree));
1402 result = null;
1403 }
1404
1405 public void visitSwitch(JCSwitch tree) {
1406 handleSwitch(tree, tree.selector, tree.cases, (c, caseEnv) -> {
1407 attribStats(c.stats, caseEnv);
1408 });
1409 result = null;
1410 }
1411
1412 public void visitSwitchExpression(JCSwitchExpression tree) {
1413 tree.polyKind = (pt().hasTag(NONE) && pt() != Type.recoveryType && pt() != Infer.anyPoly) ?
1414 PolyKind.STANDALONE : PolyKind.POLY;
1415
1416 if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) {
1417 //this means we are returning a poly conditional from void-compatible lambda expression
1418 resultInfo.checkContext.report(tree, diags.fragment(Fragments.SwitchExpressionTargetCantBeVoid));
1419 result = tree.type = types.createErrorType(resultInfo.pt);
1420 return;
1421 }
1422
1423 ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ?
1424 unknownExprInfo :
1425 resultInfo.dup(switchExpressionContext(resultInfo.checkContext));
1426
1427 ListBuffer<Type> caseTypes = new ListBuffer<>();
1428
1429 handleSwitch(tree, tree.selector, tree.cases, (c, caseEnv) -> {
1430 caseEnv.info.breakResult = condInfo;
1431 attribStats(c.stats, caseEnv);
1432 new TreeScanner() {
1433 @Override
1434 public void visitBreak(JCBreak brk) {
1435 if (brk.target == tree)
1436 caseTypes.append(brk.value != null ? brk.value.type : syms.errType);
1437 super.visitBreak(brk);
1438 }
1439
1440 @Override public void visitClassDef(JCClassDecl tree) {}
1441 @Override public void visitLambda(JCLambda tree) {}
1442 @Override public void visitMethodDef(JCMethodDecl tree) {}
1443 }.scan(c.stats);
1444 });
1445
1446 Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(tree, caseTypes.toList()) : pt();
1447
1448 result = tree.type = check(tree, owntype, KindSelector.VAL, resultInfo);
1449 }
1450 //where:
1451 CheckContext switchExpressionContext(CheckContext checkContext) {
1452 return new Check.NestedCheckContext(checkContext) {
1453 //this will use enclosing check context to check compatibility of
1454 //subexpression against target type; if we are in a method check context,
1455 //depending on whether boxing is allowed, we could have incompatibilities
1456 @Override
1457 public void report(DiagnosticPosition pos, JCDiagnostic details) {
1458 enclosingContext.report(pos, diags.fragment(Fragments.IncompatibleTypeInSwitchExpression(details)));
1459 }
1460 };
1461 }
1462
1463 private void handleSwitch(JCTree switchTree,
1464 JCExpression selector,
1465 List<JCCase> cases,
1466 BiConsumer<JCCase, Env<AttrContext>> attribCase) {
1467 Type seltype = attribExpr(selector, env);
1468
1469 Env<AttrContext> switchEnv =
1470 env.dup(switchTree, env.info.dup(env.info.scope.dup()));
1471
1472 try {
1473 boolean enumSwitch = (seltype.tsym.flags() & Flags.ENUM) != 0;
1474 boolean stringSwitch = types.isSameType(seltype, syms.stringType);
1475 if (!enumSwitch && !stringSwitch)
1476 seltype = chk.checkType(selector.pos(), seltype, syms.intType);
1477
1478 // Attribute all cases and
1479 // check that there are no duplicate case labels or default clauses.
1480 Set<Object> labels = new HashSet<>(); // The set of case labels.
1481 boolean hasDefault = false; // Is there a default label?
1482 @SuppressWarnings("removal")
1483 CaseKind caseKind = null;
1484 boolean wasError = false;
1485 for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
1486 JCCase c = l.head;
1487 if (caseKind == null) {
1488 caseKind = c.caseKind;
1489 } else if (caseKind != c.caseKind && !wasError) {
1490 log.error(c.pos(),
1491 Errors.SwitchMixingCaseTypes);
1492 wasError = true;
1493 }
1494 if (c.getExpressions().nonEmpty()) {
1495 for (JCExpression pat : c.getExpressions()) {
1496 if (TreeInfo.isNull(pat)) {
1497 log.error(pat.pos(),
1498 Errors.SwitchNullNotAllowed);
1499 } else if (enumSwitch) {
1500 Symbol sym = enumConstant(pat, seltype);
1501 if (sym == null) {
1502 log.error(pat.pos(), Errors.EnumLabelMustBeUnqualifiedEnum);
1503 } else if (!labels.add(sym)) {
1504 log.error(c.pos(), Errors.DuplicateCaseLabel);
1505 }
1506 } else {
1507 Type pattype = attribExpr(pat, switchEnv, seltype);
1508 if (!pattype.hasTag(ERROR)) {
1509 if (pattype.constValue() == null) {
1510 log.error(pat.pos(),
1511 (stringSwitch ? Errors.StringConstReq : Errors.ConstExprReq));
1512 } else if (!labels.add(pattype.constValue())) {
1513 log.error(c.pos(), Errors.DuplicateCaseLabel);
1514 }
1515 }
1516 }
1517 }
1518 } else if (hasDefault) {
1519 log.error(c.pos(), Errors.DuplicateDefaultLabel);
1520 } else {
1521 hasDefault = true;
1522 }
1523 Env<AttrContext> caseEnv =
1524 switchEnv.dup(c, env.info.dup(switchEnv.info.scope.dup()));
1525 try {
1526 attribCase.accept(c, caseEnv);
1527 } finally {
1528 caseEnv.info.scope.leave();
1529 addVars(c.stats, switchEnv.info.scope);
1530 }
1531 }
1532 } finally {
1533 switchEnv.info.scope.leave();
1534 }
1535 }
1536 // where
1537 /** Add any variables defined in stats to the switch scope. */
1538 private static void addVars(List<JCStatement> stats, WriteableScope switchScope) {
1539 for (;stats.nonEmpty(); stats = stats.tail) {
1540 JCTree stat = stats.head;
1541 if (stat.hasTag(VARDEF))
1542 switchScope.enter(((JCVariableDecl) stat).sym);
1543 }
1544 }
1545 // where
1546 /** Return the selected enumeration constant symbol, or null. */
1547 private Symbol enumConstant(JCTree tree, Type enumType) {
1548 if (tree.hasTag(IDENT)) {
1549 JCIdent ident = (JCIdent)tree;
1550 Name name = ident.name;
1551 for (Symbol sym : enumType.tsym.members().getSymbolsByName(name)) {
1552 if (sym.kind == VAR) {
1672
1673 tree.polyKind = (!allowPoly ||
1674 pt().hasTag(NONE) && pt() != Type.recoveryType && pt() != Infer.anyPoly ||
1675 isBooleanOrNumeric(env, tree)) ?
1676 PolyKind.STANDALONE : PolyKind.POLY;
1677
1678 if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) {
1679 //this means we are returning a poly conditional from void-compatible lambda expression
1680 resultInfo.checkContext.report(tree, diags.fragment(Fragments.ConditionalTargetCantBeVoid));
1681 result = tree.type = types.createErrorType(resultInfo.pt);
1682 return;
1683 }
1684
1685 ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ?
1686 unknownExprInfo :
1687 resultInfo.dup(conditionalContext(resultInfo.checkContext));
1688
1689 Type truetype = attribTree(tree.truepart, env, condInfo);
1690 Type falsetype = attribTree(tree.falsepart, env, condInfo);
1691
1692 Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(tree, List.of(truetype, falsetype)) : pt();
1693 if (condtype.constValue() != null &&
1694 truetype.constValue() != null &&
1695 falsetype.constValue() != null &&
1696 !owntype.hasTag(NONE)) {
1697 //constant folding
1698 owntype = cfolder.coerce(condtype.isTrue() ? truetype : falsetype, owntype);
1699 }
1700 result = check(tree, owntype, KindSelector.VAL, resultInfo);
1701 }
1702 //where
1703 private boolean isBooleanOrNumeric(Env<AttrContext> env, JCExpression tree) {
1704 switch (tree.getTag()) {
1705 case LITERAL: return ((JCLiteral)tree).typetag.isSubRangeOf(DOUBLE) ||
1706 ((JCLiteral)tree).typetag == BOOLEAN ||
1707 ((JCLiteral)tree).typetag == BOT;
1708 case LAMBDA: case REFERENCE: return false;
1709 case PARENS: return isBooleanOrNumeric(env, ((JCParens)tree).expr);
1710 case CONDEXPR:
1711 JCConditional condTree = (JCConditional)tree;
1712 return isBooleanOrNumeric(env, condTree.truepart) &&
1754 //subexpression against target type; if we are in a method check context,
1755 //depending on whether boxing is allowed, we could have incompatibilities
1756 @Override
1757 public void report(DiagnosticPosition pos, JCDiagnostic details) {
1758 enclosingContext.report(pos, diags.fragment(Fragments.IncompatibleTypeInConditional(details)));
1759 }
1760 };
1761 }
1762
1763 /** Compute the type of a conditional expression, after
1764 * checking that it exists. See JLS 15.25. Does not take into
1765 * account the special case where condition and both arms
1766 * are constants.
1767 *
1768 * @param pos The source position to be used for error
1769 * diagnostics.
1770 * @param thentype The type of the expression's then-part.
1771 * @param elsetype The type of the expression's else-part.
1772 */
1773 Type condType(DiagnosticPosition pos,
1774 List<Type> condTypes) {
1775 if (condTypes.isEmpty()) {
1776 return syms.objectType; //TODO: how to handle?
1777 }
1778 if (condTypes.size() == 1) {
1779 return condTypes.head;
1780 }
1781 Type first = condTypes.head;
1782 // If same type, that is the result
1783 if (condTypes.tail.stream().allMatch(t -> types.isSameType(first, t)))
1784 return first.baseType();
1785
1786 List<Type> unboxedTypes = condTypes.stream()
1787 .map(t -> t.isPrimitive() ? t : types.unboxedType(t))
1788 .collect(List.collector());
1789
1790 // Otherwise, if both arms can be converted to a numeric
1791 // type, return the least numeric type that fits both arms
1792 // (i.e. return larger of the two, or return int if one
1793 // arm is short, the other is char).
1794 if (unboxedTypes.stream().allMatch(t -> t.isPrimitive())) {
1795 // If one arm has an integer subrange type (i.e., byte,
1796 // short, or char), and the other is an integer constant
1797 // that fits into the subrange, return the subrange type.
1798 for (Type type : unboxedTypes) {
1799 if (!type.getTag().isStrictSubRangeOf(INT)) {
1800 continue;
1801 }
1802 if (unboxedTypes.stream().filter(t -> t != type).allMatch(t -> t.hasTag(INT) && types.isAssignable(t, type)))
1803 return type.baseType();
1804 }
1805
1806 for (TypeTag tag : primitiveTags) {
1807 Type candidate = syms.typeOfTag[tag.ordinal()];
1808 if (unboxedTypes.stream().allMatch(t -> types.isSubtype(t, candidate))) {
1809 return candidate;
1810 }
1811 }
1812 }
1813
1814 // Those were all the cases that could result in a primitive
1815 condTypes = condTypes.stream()
1816 .map(t -> t.isPrimitive() ? types.boxedClass(t).type : t)
1817 .collect(List.collector());
1818
1819 for (Type type : condTypes) {
1820 if (condTypes.stream().filter(t -> t != type).allMatch(t -> types.isAssignable(t, type)))
1821 return type.baseType();
1822 }
1823
1824 if (condTypes.stream().anyMatch(t -> t.hasTag(VOID))) {
1825 //XXX:
1826 log.error(pos,
1827 Errors.NeitherConditionalSubtype(condTypes.head,
1828 condTypes.tail.head));
1829 return condTypes.head.baseType();
1830 }
1831
1832 // both are known to be reference types. The result is
1833 // lub(thentype,elsetype). This cannot fail, as it will
1834 // always be possible to infer "Object" if nothing better.
1835 return types.lub(condTypes.stream().map(t -> t.baseType()).collect(List.collector()));
1836 }
1837
1838 final static TypeTag[] primitiveTags = new TypeTag[]{
1839 BYTE,
1840 CHAR,
1841 SHORT,
1842 INT,
1843 LONG,
1844 FLOAT,
1845 DOUBLE,
1846 BOOLEAN,
1847 };
1848
1849 public void visitIf(JCIf tree) {
1850 attribExpr(tree.cond, env, syms.booleanType);
1851 attribStat(tree.thenpart, env);
1852 if (tree.elsepart != null)
1853 attribStat(tree.elsepart, env);
1854 chk.checkEmptyIf(tree);
1855 result = null;
1856 }
1857
1858 public void visitExec(JCExpressionStatement tree) {
1859 //a fresh environment is required for 292 inference to work properly ---
1860 //see Infer.instantiatePolymorphicSignatureInstance()
1861 Env<AttrContext> localEnv = env.dup(tree);
1862 attribExpr(tree.expr, localEnv);
1863 result = null;
1864 }
1865
1866 public void visitBreak(JCBreak tree) {
1867 if (env.info.breakResult != null) {
1868 if (tree.value == null) {
1869 tree.target = findJumpTarget(tree.pos(), tree.getTag(), null, env);
1870 if (tree.target.hasTag(SWITCH_EXPRESSION)) {
1871 log.error(tree.pos(), Errors.BreakMissingValue);
1872 }
1873 } else {
1874 if (env.info.breakResult.pt.hasTag(VOID)) {
1875 //can happen?
1876 env.info.breakResult.checkContext.report(tree.value.pos(),
1877 diags.fragment(Fragments.UnexpectedRetVal));
1878 }
1879 boolean attribute = true;
1880 if (tree.value.hasTag(IDENT)) {
1881 //disambiguate break <LABEL> and break <ident-as-an-expression>:
1882 Name label = ((JCIdent) tree.value).name;
1883 Pair<JCTree, Error> jumpTarget = findJumpTargetNoError(tree.getTag(), label, env);
1884
1885 if (jumpTarget.fst != null) {
1886 JCTree speculative = deferredAttr.attribSpeculative(tree.value, env, unknownExprInfo);
1887 if (!speculative.type.hasTag(ERROR)) {
1888 log.error(tree.pos(), Errors.BreakAmbiguousTarget(label));
1889 if (jumpTarget.snd == null) {
1890 tree.target = jumpTarget.fst;
1891 attribute = false;
1892 } else {
1893 //nothing
1894 }
1895 } else {
1896 if (jumpTarget.snd != null) {
1897 log.error(tree.pos(), jumpTarget.snd);
1898 }
1899 tree.target = jumpTarget.fst;
1900 attribute = false;
1901 }
1902 }
1903 }
1904 if (attribute) {
1905 attribTree(tree.value, env, env.info.breakResult);
1906 JCTree immediateTarget = findJumpTarget(tree.pos(), tree.getTag(), null, env);
1907 if (immediateTarget.getTag() != SWITCH_EXPRESSION) {
1908 log.error(tree.pos(), Errors.BreakExprNotImmediate);
1909 Env<AttrContext> env1 = env;
1910 while (env1 != null && env1.tree.getTag() != SWITCH_EXPRESSION) {
1911 env1 = env1.next;
1912 }
1913 Assert.checkNonNull(env1);
1914 tree.target = env1.tree;
1915 } else {
1916 tree.target = immediateTarget;
1917 }
1918 }
1919 }
1920 } else {
1921 if (tree.value == null || tree.value.hasTag(IDENT)) {
1922 Name label = tree.value != null ? ((JCIdent) tree.value).name : null;
1923 tree.target = findJumpTarget(tree.pos(), tree.getTag(), label, env);
1924 } else {
1925 log.error(tree.pos(), Errors.BreakComplexValueNoSwitchExpression);
1926 attribTree(tree.value, env, unknownExprInfo);
1927 }
1928 }
1929 result = null;
1930 }
1931
1932 public void visitContinue(JCContinue tree) {
1933 tree.target = findJumpTarget(tree.pos(), tree.getTag(), tree.label, env);
1934 result = null;
1935 }
1936 //where
1937 /** Return the target of a break or continue statement, if it exists,
1938 * report an error if not.
1939 * Note: The target of a labelled break or continue is the
1940 * (non-labelled) statement tree referred to by the label,
1941 * not the tree representing the labelled statement itself.
1942 *
1943 * @param pos The position to be used for error diagnostics
1944 * @param tag The tag of the jump statement. This is either
1945 * Tree.BREAK or Tree.CONTINUE.
1946 * @param label The label of the jump statement, or null if no
1947 * label is given.
1948 * @param env The environment current at the jump statement.
1949 */
1950 private JCTree findJumpTarget(DiagnosticPosition pos,
1951 JCTree.Tag tag,
1952 Name label,
1953 Env<AttrContext> env) {
1954 Pair<JCTree, Error> jumpTarget = findJumpTargetNoError(tag, label, env);
1955
1956 if (jumpTarget.snd != null) {
1957 log.error(pos, jumpTarget.snd);
1958 }
1959
1960 return jumpTarget.fst;
1961 }
1962 /** Return the target of a break or continue statement, if it exists,
1963 * report an error if not.
1964 * Note: The target of a labelled break or continue is the
1965 * (non-labelled) statement tree referred to by the label,
1966 * not the tree representing the labelled statement itself.
1967 *
1968 * @param tag The tag of the jump statement. This is either
1969 * Tree.BREAK or Tree.CONTINUE.
1970 * @param label The label of the jump statement, or null if no
1971 * label is given.
1972 * @param env The environment current at the jump statement.
1973 */
1974 private Pair<JCTree, JCDiagnostic.Error> findJumpTargetNoError(JCTree.Tag tag,
1975 Name label,
1976 Env<AttrContext> env) {
1977 // Search environments outwards from the point of jump.
1978 Env<AttrContext> env1 = env;
1979 JCDiagnostic.Error pendingError = null;
1980 LOOP:
1981 while (env1 != null) {
1982 switch (env1.tree.getTag()) {
1983 case LABELLED:
1984 JCLabeledStatement labelled = (JCLabeledStatement)env1.tree;
1985 if (label == labelled.label) {
1986 // If jump is a continue, check that target is a loop.
1987 if (tag == CONTINUE) {
1988 if (!labelled.body.hasTag(DOLOOP) &&
1989 !labelled.body.hasTag(WHILELOOP) &&
1990 !labelled.body.hasTag(FORLOOP) &&
1991 !labelled.body.hasTag(FOREACHLOOP)) {
1992 pendingError = Errors.NotLoopLabel(label);
1993 }
1994 // Found labelled statement target, now go inwards
1995 // to next non-labelled tree.
1996 return Pair.of(TreeInfo.referencedStatement(labelled), pendingError);
1997 } else {
1998 return Pair.of(labelled, pendingError);
1999 }
2000 }
2001 break;
2002 case DOLOOP:
2003 case WHILELOOP:
2004 case FORLOOP:
2005 case FOREACHLOOP:
2006 if (label == null) return Pair.of(env1.tree, pendingError);
2007 break;
2008 case SWITCH:
2009 if (label == null && tag == BREAK) return Pair.of(env1.tree, null);
2010 break;
2011 case SWITCH_EXPRESSION:
2012 if (tag == BREAK) {
2013 if (label == null) {
2014 return Pair.of(env1.tree, null);
2015 } else {
2016 pendingError = Errors.BreakOutsideSwitchExpression;
2017 }
2018 } else {
2019 pendingError = Errors.ContinueOutsideSwitchExpression;
2020 }
2021 break;
2022 case LAMBDA:
2023 case METHODDEF:
2024 case CLASSDEF:
2025 break LOOP;
2026 default:
2027 }
2028 env1 = env1.next;
2029 }
2030 if (label != null)
2031 return Pair.of(null, Errors.UndefLabel(label));
2032 else if (tag == CONTINUE)
2033 return Pair.of(null, Errors.ContOutsideLoop);
2034 else
2035 return Pair.of(null, Errors.BreakOutsideSwitchLoop);
2036 }
2037
2038 public void visitReturn(JCReturn tree) {
2039 // Check that there is an enclosing method which is
2040 // nested within than the enclosing class.
2041 if (env.info.returnResult == null) {
2042 log.error(tree.pos(), Errors.RetOutsideMeth);
2043 } else if (env.info.breakResult != null) {
2044 log.error(tree.pos(), Errors.ReturnOutsideSwitchExpression);
2045 } else {
2046 // Attribute return expression, if it exists, and check that
2047 // it conforms to result type of enclosing method.
2048 if (tree.expr != null) {
2049 if (env.info.returnResult.pt.hasTag(VOID)) {
2050 env.info.returnResult.checkContext.report(tree.expr.pos(),
2051 diags.fragment(Fragments.UnexpectedRetVal));
2052 }
2053 attribTree(tree.expr, env, env.info.returnResult);
2054 } else if (!env.info.returnResult.pt.hasTag(VOID) &&
2055 !env.info.returnResult.pt.hasTag(NONE)) {
2056 env.info.returnResult.checkContext.report(tree.pos(),
2057 diags.fragment(Fragments.MissingRetVal(env.info.returnResult.pt)));
2058 }
2059 }
2060 result = null;
2061 }
2062
2063 public void visitThrow(JCThrow tree) {
2064 Type owntype = attribExpr(tree.expr, env, allowPoly ? Type.noType : syms.throwableType);
3107 }
3108 } else {
3109 /* if the field is static then we need to create a fake clinit
3110 * method, this method can later be reused by LTM.
3111 */
3112 MethodSymbol clinit = clinits.get(enclClass);
3113 if (clinit == null) {
3114 Type clinitType = new MethodType(List.nil(),
3115 syms.voidType, List.nil(), syms.methodClass);
3116 clinit = new MethodSymbol(STATIC | SYNTHETIC | PRIVATE,
3117 names.clinit, clinitType, enclClass);
3118 clinit.params = List.nil();
3119 clinits.put(enclClass, clinit);
3120 }
3121 newScopeOwner = clinit;
3122 }
3123 lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dupUnshared(newScopeOwner)));
3124 } else {
3125 lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dup()));
3126 }
3127 lambdaEnv.info.breakResult = null;
3128 return lambdaEnv;
3129 }
3130
3131 @Override
3132 public void visitReference(final JCMemberReference that) {
3133 if (pt().isErroneous() || (pt().hasTag(NONE) && pt() != Type.recoveryType)) {
3134 if (pt().hasTag(NONE) && (env.info.enclVar == null || !env.info.enclVar.type.isErroneous())) {
3135 //method reference only allowed in assignment or method invocation/cast context
3136 log.error(that.pos(), Errors.UnexpectedMref);
3137 }
3138 result = that.type = types.createErrorType(pt());
3139 return;
3140 }
3141 final Env<AttrContext> localEnv = env.dup(that);
3142 try {
3143 //attribute member reference qualifier - if this is a constructor
3144 //reference, the expected kind must be a type
3145 Type exprType = attribTree(that.expr, env, memberReferenceQualifierResult(that));
3146
3147 if (that.getMode() == JCMemberReference.ReferenceMode.NEW) {
|