< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java

Print this page
rev 51104 : imported patch switch


   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) {


< prev index next >