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;
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) &&
1673 //this will use enclosing check context to check compatibility of
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 import java.util.stream.Collectors;
31
32 import javax.lang.model.element.ElementKind;
33 import javax.tools.JavaFileObject;
34
35 import com.sun.source.tree.CaseTree.CaseKind;
36 import com.sun.source.tree.IdentifierTree;
37 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
38 import com.sun.source.tree.MemberSelectTree;
39 import com.sun.source.tree.TreeVisitor;
40 import com.sun.source.util.SimpleTreeVisitor;
41 import com.sun.tools.javac.code.*;
42 import com.sun.tools.javac.code.Lint.LintCategory;
43 import com.sun.tools.javac.code.Scope.WriteableScope;
44 import com.sun.tools.javac.code.Source.Feature;
45 import com.sun.tools.javac.code.Symbol.*;
46 import com.sun.tools.javac.code.Type.*;
47 import com.sun.tools.javac.code.TypeMetadata.Annotations;
48 import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError;
49 import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext;
50 import com.sun.tools.javac.comp.Check.CheckContext;
51 import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
52 import com.sun.tools.javac.jvm.*;
53 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.Diamond;
54 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.DiamondInvalidArg;
55 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.DiamondInvalidArgs;
1381 }
1382
1383 public void visitLabelled(JCLabeledStatement tree) {
1384 // Check that label is not used in an enclosing statement
1385 Env<AttrContext> env1 = env;
1386 while (env1 != null && !env1.tree.hasTag(CLASSDEF)) {
1387 if (env1.tree.hasTag(LABELLED) &&
1388 ((JCLabeledStatement) env1.tree).label == tree.label) {
1389 log.error(tree.pos(),
1390 Errors.LabelAlreadyInUse(tree.label));
1391 break;
1392 }
1393 env1 = env1.next;
1394 }
1395
1396 attribStat(tree.body, env.dup(tree));
1397 result = null;
1398 }
1399
1400 public void visitSwitch(JCSwitch tree) {
1401 handleSwitch(tree, tree.selector, tree.cases, (c, caseEnv) -> {
1402 attribStats(c.stats, caseEnv);
1403 });
1404 result = null;
1405 }
1406
1407 public void visitSwitchExpression(JCSwitchExpression tree) {
1408 tree.polyKind = (pt().hasTag(NONE) && pt() != Type.recoveryType && pt() != Infer.anyPoly) ?
1409 PolyKind.STANDALONE : PolyKind.POLY;
1410
1411 if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) {
1412 //this means we are returning a poly conditional from void-compatible lambda expression
1413 resultInfo.checkContext.report(tree, diags.fragment(Fragments.SwitchExpressionTargetCantBeVoid));
1414 result = tree.type = types.createErrorType(resultInfo.pt);
1415 return;
1416 }
1417
1418 ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ?
1419 unknownExprInfo :
1420 resultInfo.dup(switchExpressionContext(resultInfo.checkContext));
1421
1422 ListBuffer<DiagnosticPosition> caseTypePositions = new ListBuffer<>();
1423 ListBuffer<Type> caseTypes = new ListBuffer<>();
1424
1425 handleSwitch(tree, tree.selector, tree.cases, (c, caseEnv) -> {
1426 caseEnv.info.breakResult = condInfo;
1427 attribStats(c.stats, caseEnv);
1428 new TreeScanner() {
1429 @Override
1430 public void visitBreak(JCBreak brk) {
1431 if (brk.target == tree) {
1432 caseTypePositions.append(brk.value != null ? brk.value.pos() : brk.pos());
1433 caseTypes.append(brk.value != null ? brk.value.type : syms.errType);
1434 }
1435 super.visitBreak(brk);
1436 }
1437
1438 @Override public void visitClassDef(JCClassDecl tree) {}
1439 @Override public void visitLambda(JCLambda tree) {}
1440 }.scan(c.stats);
1441 });
1442
1443 if (tree.cases.isEmpty()) {
1444 log.error(tree.pos(),
1445 Errors.SwitchExpressionEmpty);
1446 }
1447
1448 Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(caseTypePositions.toList(), caseTypes.toList()) : pt();
1449
1450 result = tree.type = check(tree, owntype, KindSelector.VAL, resultInfo);
1451 }
1452 //where:
1453 CheckContext switchExpressionContext(CheckContext checkContext) {
1454 return new Check.NestedCheckContext(checkContext) {
1455 //this will use enclosing check context to check compatibility of
1456 //subexpression against target type; if we are in a method check context,
1457 //depending on whether boxing is allowed, we could have incompatibilities
1458 @Override
1459 public void report(DiagnosticPosition pos, JCDiagnostic details) {
1460 enclosingContext.report(pos, diags.fragment(Fragments.IncompatibleTypeInSwitchExpression(details)));
1461 }
1462 };
1463 }
1464
1465 private void handleSwitch(JCTree switchTree,
1466 JCExpression selector,
1467 List<JCCase> cases,
1468 BiConsumer<JCCase, Env<AttrContext>> attribCase) {
1469 Type seltype = attribExpr(selector, env);
1470
1471 Env<AttrContext> switchEnv =
1472 env.dup(switchTree, env.info.dup(env.info.scope.dup()));
1473
1474 try {
1475 boolean enumSwitch = (seltype.tsym.flags() & Flags.ENUM) != 0;
1476 boolean stringSwitch = types.isSameType(seltype, syms.stringType);
1477 if (!enumSwitch && !stringSwitch)
1478 seltype = chk.checkType(selector.pos(), seltype, syms.intType);
1479
1480 // Attribute all cases and
1481 // check that there are no duplicate case labels or default clauses.
1482 Set<Object> labels = new HashSet<>(); // The set of case labels.
1483 boolean hasDefault = false; // Is there a default label?
1484 @SuppressWarnings("removal")
1485 CaseKind caseKind = null;
1486 boolean wasError = false;
1487 for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
1488 JCCase c = l.head;
1489 if (caseKind == null) {
1490 caseKind = c.caseKind;
1491 } else if (caseKind != c.caseKind && !wasError) {
1492 log.error(c.pos(),
1493 Errors.SwitchMixingCaseTypes);
1494 wasError = true;
1495 }
1496 if (c.getExpressions().nonEmpty()) {
1497 for (JCExpression pat : c.getExpressions()) {
1498 if (TreeInfo.isNull(pat)) {
1499 log.error(pat.pos(),
1500 Errors.SwitchNullNotAllowed);
1501 } else if (enumSwitch) {
1502 Symbol sym = enumConstant(pat, seltype);
1503 if (sym == null) {
1504 log.error(pat.pos(), Errors.EnumLabelMustBeUnqualifiedEnum);
1505 } else if (!labels.add(sym)) {
1506 log.error(c.pos(), Errors.DuplicateCaseLabel);
1507 }
1508 } else {
1509 Type pattype = attribExpr(pat, switchEnv, seltype);
1510 if (!pattype.hasTag(ERROR)) {
1511 if (pattype.constValue() == null) {
1512 log.error(pat.pos(),
1513 (stringSwitch ? Errors.StringConstReq : Errors.ConstExprReq));
1514 } else if (!labels.add(pattype.constValue())) {
1515 log.error(c.pos(), Errors.DuplicateCaseLabel);
1516 }
1517 }
1518 }
1519 }
1520 } else if (hasDefault) {
1521 log.error(c.pos(), Errors.DuplicateDefaultLabel);
1522 } else {
1523 hasDefault = true;
1524 }
1525 Env<AttrContext> caseEnv =
1526 switchEnv.dup(c, env.info.dup(switchEnv.info.scope.dup()));
1527 try {
1528 attribCase.accept(c, caseEnv);
1529 } finally {
1530 caseEnv.info.scope.leave();
1531 addVars(c.stats, switchEnv.info.scope);
1532 }
1533 }
1534 } finally {
1535 switchEnv.info.scope.leave();
1536 }
1537 }
1538 // where
1539 /** Add any variables defined in stats to the switch scope. */
1540 private static void addVars(List<JCStatement> stats, WriteableScope switchScope) {
1541 for (;stats.nonEmpty(); stats = stats.tail) {
1542 JCTree stat = stats.head;
1543 if (stat.hasTag(VARDEF))
1544 switchScope.enter(((JCVariableDecl) stat).sym);
1545 }
1546 }
1547 // where
1548 /** Return the selected enumeration constant symbol, or null. */
1549 private Symbol enumConstant(JCTree tree, Type enumType) {
1550 if (tree.hasTag(IDENT)) {
1551 JCIdent ident = (JCIdent)tree;
1552 Name name = ident.name;
1553 for (Symbol sym : enumType.tsym.members().getSymbolsByName(name)) {
1554 if (sym.kind == VAR) {
1674
1675 tree.polyKind = (!allowPoly ||
1676 pt().hasTag(NONE) && pt() != Type.recoveryType && pt() != Infer.anyPoly ||
1677 isBooleanOrNumeric(env, tree)) ?
1678 PolyKind.STANDALONE : PolyKind.POLY;
1679
1680 if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) {
1681 //this means we are returning a poly conditional from void-compatible lambda expression
1682 resultInfo.checkContext.report(tree, diags.fragment(Fragments.ConditionalTargetCantBeVoid));
1683 result = tree.type = types.createErrorType(resultInfo.pt);
1684 return;
1685 }
1686
1687 ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ?
1688 unknownExprInfo :
1689 resultInfo.dup(conditionalContext(resultInfo.checkContext));
1690
1691 Type truetype = attribTree(tree.truepart, env, condInfo);
1692 Type falsetype = attribTree(tree.falsepart, env, condInfo);
1693
1694 Type owntype = (tree.polyKind == PolyKind.STANDALONE) ?
1695 condType(List.of(tree.truepart.pos(), tree.falsepart.pos()),
1696 List.of(truetype, falsetype)) : pt();
1697 if (condtype.constValue() != null &&
1698 truetype.constValue() != null &&
1699 falsetype.constValue() != null &&
1700 !owntype.hasTag(NONE)) {
1701 //constant folding
1702 owntype = cfolder.coerce(condtype.isTrue() ? truetype : falsetype, owntype);
1703 }
1704 result = check(tree, owntype, KindSelector.VAL, resultInfo);
1705 }
1706 //where
1707 private boolean isBooleanOrNumeric(Env<AttrContext> env, JCExpression tree) {
1708 switch (tree.getTag()) {
1709 case LITERAL: return ((JCLiteral)tree).typetag.isSubRangeOf(DOUBLE) ||
1710 ((JCLiteral)tree).typetag == BOOLEAN ||
1711 ((JCLiteral)tree).typetag == BOT;
1712 case LAMBDA: case REFERENCE: return false;
1713 case PARENS: return isBooleanOrNumeric(env, ((JCParens)tree).expr);
1714 case CONDEXPR:
1715 JCConditional condTree = (JCConditional)tree;
1716 return isBooleanOrNumeric(env, condTree.truepart) &&
1757 //this will use enclosing check context to check compatibility of
1758 //subexpression against target type; if we are in a method check context,
1759 //depending on whether boxing is allowed, we could have incompatibilities
1760 @Override
1761 public void report(DiagnosticPosition pos, JCDiagnostic details) {
1762 enclosingContext.report(pos, diags.fragment(Fragments.IncompatibleTypeInConditional(details)));
1763 }
1764 };
1765 }
1766
1767 /** Compute the type of a conditional expression, after
1768 * checking that it exists. See JLS 15.25. Does not take into
1769 * account the special case where condition and both arms
1770 * are constants.
1771 *
1772 * @param pos The source position to be used for error
1773 * diagnostics.
1774 * @param thentype The type of the expression's then-part.
1775 * @param elsetype The type of the expression's else-part.
1776 */
1777 Type condType(List<DiagnosticPosition> positions, List<Type> condTypes) {
1778 if (condTypes.isEmpty()) {
1779 return syms.objectType; //TODO: how to handle?
1780 }
1781 if (condTypes.size() == 1) {
1782 return condTypes.head;
1783 }
1784 Type first = condTypes.head;
1785 // If same type, that is the result
1786 if (condTypes.tail.stream().allMatch(t -> types.isSameType(first, t)))
1787 return first.baseType();
1788
1789 List<Type> unboxedTypes = condTypes.stream()
1790 .map(t -> t.isPrimitive() ? t : types.unboxedType(t))
1791 .collect(List.collector());
1792
1793 // Otherwise, if both arms can be converted to a numeric
1794 // type, return the least numeric type that fits both arms
1795 // (i.e. return larger of the two, or return int if one
1796 // arm is short, the other is char).
1797 if (unboxedTypes.stream().allMatch(t -> t.isPrimitive())) {
1798 // If one arm has an integer subrange type (i.e., byte,
1799 // short, or char), and the other is an integer constant
1800 // that fits into the subrange, return the subrange type.
1801 for (Type type : unboxedTypes) {
1802 if (!type.getTag().isStrictSubRangeOf(INT)) {
1803 continue;
1804 }
1805 if (unboxedTypes.stream().filter(t -> t != type).allMatch(t -> t.hasTag(INT) && types.isAssignable(t, type)))
1806 return type.baseType();
1807 }
1808
1809 for (TypeTag tag : primitiveTags) {
1810 Type candidate = syms.typeOfTag[tag.ordinal()];
1811 if (unboxedTypes.stream().allMatch(t -> types.isSubtype(t, candidate))) {
1812 return candidate;
1813 }
1814 }
1815 }
1816
1817 // Those were all the cases that could result in a primitive
1818 condTypes = condTypes.stream()
1819 .map(t -> t.isPrimitive() ? types.boxedClass(t).type : t)
1820 .collect(List.collector());
1821
1822 for (Type type : condTypes) {
1823 if (condTypes.stream().filter(t -> t != type).allMatch(t -> types.isAssignable(t, type)))
1824 return type.baseType();
1825 }
1826
1827 Iterator<DiagnosticPosition> posIt = positions.iterator();
1828
1829 condTypes = condTypes.stream()
1830 .map(t -> chk.checkNonVoid(posIt.next(), t))
1831 .collect(List.collector());
1832
1833 // both are known to be reference types. The result is
1834 // lub(thentype,elsetype). This cannot fail, as it will
1835 // always be possible to infer "Object" if nothing better.
1836 return types.lub(condTypes.stream().map(t -> t.baseType()).collect(List.collector()));
1837 }
1838
1839 final static TypeTag[] primitiveTags = new TypeTag[]{
1840 BYTE,
1841 CHAR,
1842 SHORT,
1843 INT,
1844 LONG,
1845 FLOAT,
1846 DOUBLE,
1847 BOOLEAN,
1848 };
1849
1850 public void visitIf(JCIf tree) {
1851 attribExpr(tree.cond, env, syms.booleanType);
1852 attribStat(tree.thenpart, env);
1853 if (tree.elsepart != null)
1854 attribStat(tree.elsepart, env);
1855 chk.checkEmptyIf(tree);
1856 result = null;
1857 }
1858
1859 public void visitExec(JCExpressionStatement tree) {
1860 //a fresh environment is required for 292 inference to work properly ---
1861 //see Infer.instantiatePolymorphicSignatureInstance()
1862 Env<AttrContext> localEnv = env.dup(tree);
1863 attribExpr(tree.expr, localEnv);
1864 result = null;
1865 }
1866
1867 public void visitBreak(JCBreak tree) {
1868 if (env.info.breakResult != null) {
1869 if (tree.value == null) {
1870 tree.target = findJumpTarget(tree.pos(), tree.getTag(), null, env);
1871 if (tree.target.hasTag(SWITCH_EXPRESSION)) {
1872 log.error(tree.pos(), Errors.BreakMissingValue);
1873 }
1874 } else {
1875 if (env.info.breakResult.pt.hasTag(VOID)) {
1876 //can happen?
1877 env.info.breakResult.checkContext.report(tree.value.pos(),
1878 diags.fragment(Fragments.UnexpectedRetVal));
1879 }
1880 boolean attribute = true;
1881 if (tree.value.hasTag(IDENT)) {
1882 //disambiguate break <LABEL> and break <ident-as-an-expression>:
1883 Name label = ((JCIdent) tree.value).name;
1884 Pair<JCTree, Error> jumpTarget = findJumpTargetNoError(tree.getTag(), label, env);
1885
1886 if (jumpTarget.fst != null) {
1887 JCTree speculative = deferredAttr.attribSpeculative(tree.value, env, unknownExprInfo);
1888 if (!speculative.type.hasTag(ERROR)) {
1889 log.error(tree.pos(), Errors.BreakAmbiguousTarget(label));
1890 if (jumpTarget.snd == null) {
1891 tree.target = jumpTarget.fst;
1892 attribute = false;
1893 } else {
1894 //nothing
1895 }
1896 } else {
1897 if (jumpTarget.snd != null) {
1898 log.error(tree.pos(), jumpTarget.snd);
1899 }
1900 tree.target = jumpTarget.fst;
1901 attribute = false;
1902 }
1903 }
1904 }
1905 if (attribute) {
1906 attribTree(tree.value, env, env.info.breakResult);
1907 JCTree immediateTarget = findJumpTarget(tree.pos(), tree.getTag(), null, env);
1908 if (immediateTarget.getTag() != SWITCH_EXPRESSION) {
1909 log.error(tree.pos(), Errors.BreakExprNotImmediate);
1910 Env<AttrContext> env1 = env;
1911 while (env1 != null && env1.tree.getTag() != SWITCH_EXPRESSION) {
1912 env1 = env1.next;
1913 }
1914 Assert.checkNonNull(env1);
1915 tree.target = env1.tree;
1916 } else {
1917 tree.target = immediateTarget;
1918 }
1919 }
1920 }
1921 } else {
1922 if (tree.value == null || tree.value.hasTag(IDENT)) {
1923 Name label = tree.value != null ? ((JCIdent) tree.value).name : null;
1924 tree.target = findJumpTarget(tree.pos(), tree.getTag(), label, env);
1925 } else {
1926 log.error(tree.pos(), Errors.BreakComplexValueNoSwitchExpression);
1927 attribTree(tree.value, env, unknownExprInfo);
1928 }
1929 }
1930 result = null;
1931 }
1932
1933 public void visitContinue(JCContinue tree) {
1934 tree.target = findJumpTarget(tree.pos(), tree.getTag(), tree.label, env);
1935 result = null;
1936 }
1937 //where
1938 /** Return the target of a break or continue statement, if it exists,
1939 * report an error if not.
1940 * Note: The target of a labelled break or continue is the
1941 * (non-labelled) statement tree referred to by the label,
1942 * not the tree representing the labelled statement itself.
1943 *
1944 * @param pos The position to be used for error diagnostics
1945 * @param tag The tag of the jump statement. This is either
1946 * Tree.BREAK or Tree.CONTINUE.
1947 * @param label The label of the jump statement, or null if no
1948 * label is given.
1949 * @param env The environment current at the jump statement.
1950 */
1951 private JCTree findJumpTarget(DiagnosticPosition pos,
1952 JCTree.Tag tag,
1953 Name label,
1954 Env<AttrContext> env) {
1955 Pair<JCTree, Error> jumpTarget = findJumpTargetNoError(tag, label, env);
1956
1957 if (jumpTarget.snd != null) {
1958 log.error(pos, jumpTarget.snd);
1959 }
1960
1961 return jumpTarget.fst;
1962 }
1963 /** Return the target of a break or continue statement, if it exists,
1964 * report an error if not.
1965 * Note: The target of a labelled break or continue is the
1966 * (non-labelled) statement tree referred to by the label,
1967 * not the tree representing the labelled statement itself.
1968 *
1969 * @param tag The tag of the jump statement. This is either
1970 * Tree.BREAK or Tree.CONTINUE.
1971 * @param label The label of the jump statement, or null if no
1972 * label is given.
1973 * @param env The environment current at the jump statement.
1974 */
1975 private Pair<JCTree, JCDiagnostic.Error> findJumpTargetNoError(JCTree.Tag tag,
1976 Name label,
1977 Env<AttrContext> env) {
1978 // Search environments outwards from the point of jump.
1979 Env<AttrContext> env1 = env;
1980 JCDiagnostic.Error pendingError = null;
1981 LOOP:
1982 while (env1 != null) {
1983 switch (env1.tree.getTag()) {
1984 case LABELLED:
1985 JCLabeledStatement labelled = (JCLabeledStatement)env1.tree;
1986 if (label == labelled.label) {
1987 // If jump is a continue, check that target is a loop.
1988 if (tag == CONTINUE) {
1989 if (!labelled.body.hasTag(DOLOOP) &&
1990 !labelled.body.hasTag(WHILELOOP) &&
1991 !labelled.body.hasTag(FORLOOP) &&
1992 !labelled.body.hasTag(FOREACHLOOP)) {
1993 pendingError = Errors.NotLoopLabel(label);
1994 }
1995 // Found labelled statement target, now go inwards
1996 // to next non-labelled tree.
1997 return Pair.of(TreeInfo.referencedStatement(labelled), pendingError);
1998 } else {
1999 return Pair.of(labelled, pendingError);
2000 }
2001 }
2002 break;
2003 case DOLOOP:
2004 case WHILELOOP:
2005 case FORLOOP:
2006 case FOREACHLOOP:
2007 if (label == null) return Pair.of(env1.tree, pendingError);
2008 break;
2009 case SWITCH:
2010 if (label == null && tag == BREAK) return Pair.of(env1.tree, null);
2011 break;
2012 case SWITCH_EXPRESSION:
2013 if (tag == BREAK) {
2014 if (label == null) {
2015 return Pair.of(env1.tree, null);
2016 } else {
2017 pendingError = Errors.BreakOutsideSwitchExpression;
2018 }
2019 } else {
2020 pendingError = Errors.ContinueOutsideSwitchExpression;
2021 }
2022 break;
2023 case LAMBDA:
2024 case METHODDEF:
2025 case CLASSDEF:
2026 break LOOP;
2027 default:
2028 }
2029 env1 = env1.next;
2030 }
2031 if (label != null)
2032 return Pair.of(null, Errors.UndefLabel(label));
2033 else if (tag == CONTINUE)
2034 return Pair.of(null, Errors.ContOutsideLoop);
2035 else
2036 return Pair.of(null, Errors.BreakOutsideSwitchLoop);
2037 }
2038
2039 public void visitReturn(JCReturn tree) {
2040 // Check that there is an enclosing method which is
2041 // nested within than the enclosing class.
2042 if (env.info.returnResult == null) {
2043 log.error(tree.pos(), Errors.RetOutsideMeth);
2044 } else if (env.info.breakResult != null) {
2045 log.error(tree.pos(), Errors.ReturnOutsideSwitchExpression);
2046 } else {
2047 // Attribute return expression, if it exists, and check that
2048 // it conforms to result type of enclosing method.
2049 if (tree.expr != null) {
2050 if (env.info.returnResult.pt.hasTag(VOID)) {
2051 env.info.returnResult.checkContext.report(tree.expr.pos(),
2052 diags.fragment(Fragments.UnexpectedRetVal));
2053 }
2054 attribTree(tree.expr, env, env.info.returnResult);
2055 } else if (!env.info.returnResult.pt.hasTag(VOID) &&
2056 !env.info.returnResult.pt.hasTag(NONE)) {
2057 env.info.returnResult.checkContext.report(tree.pos(),
2058 diags.fragment(Fragments.MissingRetVal(env.info.returnResult.pt)));
2059 }
2060 }
2061 result = null;
2062 }
2063
2064 public void visitThrow(JCThrow tree) {
2065 Type owntype = attribExpr(tree.expr, env, allowPoly ? Type.noType : syms.throwableType);
3108 }
3109 } else {
3110 /* if the field is static then we need to create a fake clinit
3111 * method, this method can later be reused by LTM.
3112 */
3113 MethodSymbol clinit = clinits.get(enclClass);
3114 if (clinit == null) {
3115 Type clinitType = new MethodType(List.nil(),
3116 syms.voidType, List.nil(), syms.methodClass);
3117 clinit = new MethodSymbol(STATIC | SYNTHETIC | PRIVATE,
3118 names.clinit, clinitType, enclClass);
3119 clinit.params = List.nil();
3120 clinits.put(enclClass, clinit);
3121 }
3122 newScopeOwner = clinit;
3123 }
3124 lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dupUnshared(newScopeOwner)));
3125 } else {
3126 lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dup()));
3127 }
3128 lambdaEnv.info.breakResult = null;
3129 return lambdaEnv;
3130 }
3131
3132 @Override
3133 public void visitReference(final JCMemberReference that) {
3134 if (pt().isErroneous() || (pt().hasTag(NONE) && pt() != Type.recoveryType)) {
3135 if (pt().hasTag(NONE) && (env.info.enclVar == null || !env.info.enclVar.type.isErroneous())) {
3136 //method reference only allowed in assignment or method invocation/cast context
3137 log.error(that.pos(), Errors.UnexpectedMref);
3138 }
3139 result = that.type = types.createErrorType(pt());
3140 return;
3141 }
3142 final Env<AttrContext> localEnv = env.dup(that);
3143 try {
3144 //attribute member reference qualifier - if this is a constructor
3145 //reference, the expected kind must be a type
3146 Type exprType = attribTree(that.expr, env, memberReferenceQualifierResult(that));
3147
3148 if (that.getMode() == JCMemberReference.ReferenceMode.NEW) {
|