8223305: Compiler support for Switch Expressions

Reviewed-by: mcimadamore, vromero
This commit is contained in:
Jan Lahoda 2019-06-10 05:09:52 +02:00
parent c569ad302a
commit b34b2d993c
88 changed files with 2033 additions and 829 deletions

View file

@ -257,8 +257,8 @@ public enum SourceVersion {
* followed only by characters for which {@link * followed only by characters for which {@link
* Character#isJavaIdentifierPart(int)} returns {@code true}. * Character#isJavaIdentifierPart(int)} returns {@code true}.
* This pattern matches regular identifiers, keywords, restricted * This pattern matches regular identifiers, keywords, restricted
* keywords, and the literals {@code "true"}, {@code "false"}, * keywords, restricted identifiers and the literals {@code "true"},
* {@code "null"}, and {@code "var"}. * {@code "false"}, {@code "null"}.
* *
* The method returns {@code false} for all other strings. * The method returns {@code false} for all other strings.
* *
@ -295,7 +295,7 @@ public enum SourceVersion {
* for keywords, boolean literals, and the null literal. * for keywords, boolean literals, and the null literal.
* *
* This method returns {@code true} for <i>restricted * This method returns {@code true} for <i>restricted
* keywords</i> and {@code "var"}. * keywords</i> and <i>restricted identifiers</i>
* *
* @param name the string to check * @param name the string to check
* @return {@code true} if this string is a * @return {@code true} if this string is a
@ -314,7 +314,7 @@ public enum SourceVersion {
* for keywords, boolean literals, and the null literal. * for keywords, boolean literals, and the null literal.
* *
* This method returns {@code true} for <i>restricted * This method returns {@code true} for <i>restricted
* keywords</i> and {@code "var"}. * keywords</i> and <i>restricted identifiers</i>
* *
* @param name the string to check * @param name the string to check
* @param version the version to use * @param version the version to use
@ -338,7 +338,7 @@ public enum SourceVersion {
* Returns whether or not {@code s} is a keyword, boolean literal, * Returns whether or not {@code s} is a keyword, boolean literal,
* or null literal in the latest source version. * or null literal in the latest source version.
* This method returns {@code false} for <i>restricted * This method returns {@code false} for <i>restricted
* keywords</i> and {@code "var"}. * keywords</i> and <i>restricted identifiers</i>.
* *
* @param s the string to check * @param s the string to check
* @return {@code true} if {@code s} is a keyword, or boolean * @return {@code true} if {@code s} is a keyword, or boolean
@ -355,7 +355,7 @@ public enum SourceVersion {
* Returns whether or not {@code s} is a keyword, boolean literal, * Returns whether or not {@code s} is a keyword, boolean literal,
* or null literal in the given source version. * or null literal in the given source version.
* This method returns {@code false} for <i>restricted * This method returns {@code false} for <i>restricted
* keywords</i> and {@code "var"}. * keywords</i> and <i>restricted identifiers</i>.
* *
* @param s the string to check * @param s the string to check
* @param version the version to use * @param version the version to use

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -35,8 +35,6 @@ import javax.lang.model.element.Name;
* break; * break;
* *
* break <em>label</em> ; * break <em>label</em> ;
*
* break <em>expression</em> ;
* </pre> * </pre>
* *
* @jls 14.15 The break Statement * @jls 14.15 The break Statement
@ -52,17 +50,4 @@ public interface BreakTree extends StatementTree {
*/ */
Name getLabel(); Name getLabel();
/**
* Returns the expression for this {@code break} statement.
*
* @return the expression
* @since 12
*
* @deprecated This method is modeling value breaks, which are part of
* a preview feature and may be removed if the preview feature
* is removed.
*
*/
@Deprecated(forRemoval=true, since="12")
ExpressionTree getValue();
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -656,7 +656,21 @@ public interface Tree {
* An implementation-reserved node. This is the not the node * An implementation-reserved node. This is the not the node
* you are looking for. * you are looking for.
*/ */
OTHER(null); OTHER(null),
/**
* Used for instances of {@link YieldTree}.
*
* @since 13
*
* @deprecated
* This enum constant is modeling yield statement,
* which are part of a preview feature and may be removed
* if the preview feature is removed.
*/
@Deprecated(forRemoval=true, since="13")
@SuppressWarnings("removal")
YIELD(YieldTree.class);
Kind(Class<? extends Tree> intf) { Kind(Class<? extends Tree> intf) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -555,4 +555,20 @@ public interface TreeVisitor<R,P> {
* @return a result value * @return a result value
*/ */
R visitOther(Tree node, P p); R visitOther(Tree node, P p);
/**
* Visits a YieldTree node.
* @param node the node being visited
* @param p a parameter value
* @return a result value
* @since 13
*
* @deprecated
* This method is modeling yield statement,
* which are part of a preview feature and may be removed
* if the preview feature is removed.
*/
@Deprecated(forRemoval=true, since="13")
@SuppressWarnings("removal")
R visitYield(YieldTree node, P p);
} }

View file

@ -0,0 +1,53 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.source.tree;
/**
* A tree node for a {@code yield} statement.
*
* For example:
* <pre>
* yield <em>expression</em> ;
* </pre>
*
* @jls section TODO
*
* @since 13
*
* @deprecated This class is modeling yield from switch expressions,
* which are part of a preview feature and may be removed if
* the preview feature is removed.
*/
@Deprecated(forRemoval=true, since="13")
public interface YieldTree extends StatementTree {
/**
* Returns the expression for this {@code yield} statement.
*
* @return the expression
*/
ExpressionTree getValue();
}

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -782,4 +782,18 @@ public class SimpleTreeVisitor <R,P> implements TreeVisitor<R,P> {
public R visitOther(Tree node, P p) { public R visitOther(Tree node, P p) {
return defaultAction(node, p); return defaultAction(node, p);
} }
/**
* {@inheritDoc} This implementation calls {@code defaultAction}.
*
* @param node {@inheritDoc}
* @param p {@inheritDoc}
* @return the result of {@code defaultAction}
*/
@Override
@Deprecated(forRemoval=true, since="13")
@SuppressWarnings("removal")
public R visitYield(YieldTree node, P p) {
return defaultAction(node, p);
}
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -467,9 +467,8 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
* @return the result of scanning * @return the result of scanning
*/ */
@Override @Override
@SuppressWarnings("removal")
public R visitBreak(BreakTree node, P p) { public R visitBreak(BreakTree node, P p) {
return scan(node.getValue(), p); return null;
} }
/** /**
@ -935,4 +934,23 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
public R visitErroneous(ErroneousTree node, P p) { public R visitErroneous(ErroneousTree node, P p) {
return null; return null;
} }
/**
* {@inheritDoc} This implementation returns {@code null}.
*
* @param node {@inheritDoc}
* @param p {@inheritDoc}
* @return the result of scanning
*
* @deprecated
* This method is modeling switch expressions,
* which are part of a preview feature and may be removed
* if the preview feature is removed.
*/
@Override
@Deprecated(forRemoval=true, since="13")
@SuppressWarnings("removal")
public R visitYield(YieldTree node, P p) {
return scan(node.getValue(), p);
}
} }

View file

@ -71,7 +71,7 @@ public class Kinds {
HIDDEN(Category.RESOLUTION_TARGET), // not overloaded non-target HIDDEN(Category.RESOLUTION_TARGET), // not overloaded non-target
STATICERR(Category.RESOLUTION_TARGET), // overloaded? target STATICERR(Category.RESOLUTION_TARGET), // overloaded? target
MISSING_ENCL(Category.RESOLUTION), // not overloaded non-target MISSING_ENCL(Category.RESOLUTION), // not overloaded non-target
BAD_VAR(Category.RESOLUTION), // not overloaded non-target BAD_RESTRICTED_TYPE(Category.RESOLUTION), // not overloaded non-target
ABSENT_VAR(Category.RESOLUTION_TARGET, KindName.VAR), // not overloaded non-target ABSENT_VAR(Category.RESOLUTION_TARGET, KindName.VAR), // not overloaded non-target
WRONG_MTHS(Category.RESOLUTION_TARGET, KindName.METHOD), // overloaded target WRONG_MTHS(Category.RESOLUTION_TARGET, KindName.METHOD), // overloaded target
WRONG_MTH(Category.RESOLUTION_TARGET, KindName.METHOD), // not overloaded target WRONG_MTH(Category.RESOLUTION_TARGET, KindName.METHOD), // not overloaded target

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -43,7 +43,6 @@ import com.sun.tools.javac.comp.Infer.PartiallyInferredMethodType;
import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase; import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase;
import com.sun.tools.javac.resources.CompilerProperties.Fragments; import com.sun.tools.javac.resources.CompilerProperties.Fragments;
import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCBreak;
import com.sun.tools.javac.tree.JCTree.JCConditional; import com.sun.tools.javac.tree.JCTree.JCConditional;
import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCLambda; import com.sun.tools.javac.tree.JCTree.JCLambda;
@ -77,6 +76,7 @@ import static com.sun.tools.javac.code.TypeTag.DEFERRED;
import static com.sun.tools.javac.code.TypeTag.FORALL; import static com.sun.tools.javac.code.TypeTag.FORALL;
import static com.sun.tools.javac.code.TypeTag.METHOD; import static com.sun.tools.javac.code.TypeTag.METHOD;
import static com.sun.tools.javac.code.TypeTag.VOID; import static com.sun.tools.javac.code.TypeTag.VOID;
import com.sun.tools.javac.tree.JCTree.JCYield;
/** /**
* This class performs attribution of method/constructor arguments when target-typing is enabled * This class performs attribution of method/constructor arguments when target-typing is enabled
@ -468,7 +468,7 @@ public class ArgumentAttr extends JCTree.Visitor {
*/ */
class SwitchExpressionType extends ArgumentType<JCSwitchExpression> { class SwitchExpressionType extends ArgumentType<JCSwitchExpression> {
/** List of break expressions (lazily populated). */ /** List of break expressions (lazily populated). */
Optional<List<JCBreak>> breakExpressions = Optional.empty(); Optional<List<JCYield>> yieldExpressions = Optional.empty();
SwitchExpressionType(JCExpression tree, Env<AttrContext> env, JCSwitchExpression speculativeCond) { SwitchExpressionType(JCExpression tree, Env<AttrContext> env, JCSwitchExpression speculativeCond) {
this(tree, env, speculativeCond, new HashMap<>()); this(tree, env, speculativeCond, new HashMap<>());
@ -487,7 +487,7 @@ public class ArgumentAttr extends JCTree.Visitor {
return attr.types.createErrorType(resultInfo.pt); return attr.types.createErrorType(resultInfo.pt);
} else { } else {
//poly //poly
for (JCBreak brk : breakExpressions()) { for (JCYield brk : yieldExpressions()) {
checkSpeculative(brk.value, brk.value.type, resultInfo); checkSpeculative(brk.value, brk.value.type, resultInfo);
} }
return localInfo.pt; return localInfo.pt;
@ -495,19 +495,20 @@ public class ArgumentAttr extends JCTree.Visitor {
} }
/** Compute return expressions (if needed). */ /** Compute return expressions (if needed). */
List<JCBreak> breakExpressions() { List<JCYield> yieldExpressions() {
return breakExpressions.orElseGet(() -> { return yieldExpressions.orElseGet(() -> {
final List<JCBreak> res; final List<JCYield> res;
ListBuffer<JCBreak> buf = new ListBuffer<>(); ListBuffer<JCYield> buf = new ListBuffer<>();
new SwitchExpressionScanner() { new SwitchExpressionScanner() {
@Override @Override
public void visitBreak(JCBreak tree) { public void visitYield(JCYield tree) {
if (tree.target == speculativeTree) if (tree.target == speculativeTree)
buf.add(tree); buf.add(tree);
super.visitYield(tree);
} }
}.scan(speculativeTree.cases); }.scan(speculativeTree.cases);
res = buf.toList(); res = buf.toList();
breakExpressions = Optional.of(res); yieldExpressions = Optional.of(res);
return res; return res;
}); });
} }

View file

@ -77,6 +77,8 @@ import static com.sun.tools.javac.code.TypeTag.WILDCARD;
import com.sun.tools.javac.comp.Analyzer.AnalyzerMode; import com.sun.tools.javac.comp.Analyzer.AnalyzerMode;
import static com.sun.tools.javac.tree.JCTree.Tag.*; import static com.sun.tools.javac.tree.JCTree.Tag.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
import com.sun.tools.javac.util.Log.DeferredDiagnosticHandler;
import com.sun.tools.javac.util.Log.DiscardDiagnosticHandler;
/** This is the main context-dependent analysis phase in GJC. It /** This is the main context-dependent analysis phase in GJC. It
* encompasses name resolution, type checking and constant folding as * encompasses name resolution, type checking and constant folding as
@ -358,7 +360,7 @@ public class Attr extends JCTree.Visitor {
Name name = (Name)node.getIdentifier(); Name name = (Name)node.getIdentifier();
if (site.kind == PCK) { if (site.kind == PCK) {
env.toplevel.packge = (PackageSymbol)site; env.toplevel.packge = (PackageSymbol)site;
return rs.findIdentInPackage(env, (TypeSymbol)site, name, return rs.findIdentInPackage(null, env, (TypeSymbol)site, name,
KindSelector.TYP_PCK); KindSelector.TYP_PCK);
} else { } else {
env.enclClass.sym = (ClassSymbol)site; env.enclClass.sym = (ClassSymbol)site;
@ -368,7 +370,7 @@ public class Attr extends JCTree.Visitor {
@Override @DefinedBy(Api.COMPILER_TREE) @Override @DefinedBy(Api.COMPILER_TREE)
public Symbol visitIdentifier(IdentifierTree node, Env<AttrContext> env) { public Symbol visitIdentifier(IdentifierTree node, Env<AttrContext> env) {
return rs.findIdent(env, (Name)node.getName(), KindSelector.TYP_PCK); return rs.findIdent(null, env, (Name)node.getName(), KindSelector.TYP_PCK);
} }
} }
@ -1425,16 +1427,16 @@ public class Attr extends JCTree.Visitor {
ListBuffer<Type> caseTypes = new ListBuffer<>(); ListBuffer<Type> caseTypes = new ListBuffer<>();
handleSwitch(tree, tree.selector, tree.cases, (c, caseEnv) -> { handleSwitch(tree, tree.selector, tree.cases, (c, caseEnv) -> {
caseEnv.info.breakResult = condInfo; caseEnv.info.yieldResult = condInfo;
attribStats(c.stats, caseEnv); attribStats(c.stats, caseEnv);
new TreeScanner() { new TreeScanner() {
@Override @Override
public void visitBreak(JCBreak brk) { public void visitYield(JCYield brk) {
if (brk.target == tree) { if (brk.target == tree) {
caseTypePositions.append(brk.value != null ? brk.value.pos() : brk.pos()); caseTypePositions.append(brk.value != null ? brk.value.pos() : brk.pos());
caseTypes.append(brk.value != null ? brk.value.type : syms.errType); caseTypes.append(brk.value != null ? brk.value.type : syms.errType);
} }
super.visitBreak(brk); super.visitYield(brk);
} }
@Override public void visitClassDef(JCClassDecl tree) {} @Override public void visitClassDef(JCClassDecl tree) {}
@ -1864,67 +1866,19 @@ public class Attr extends JCTree.Visitor {
} }
public void visitBreak(JCBreak tree) { public void visitBreak(JCBreak tree) {
if (env.info.breakResult != null) { tree.target = findJumpTarget(tree.pos(), tree.getTag(), tree.label, env);
if (tree.value == null) { result = null;
tree.target = findJumpTarget(tree.pos(), tree.getTag(), null, env); }
if (tree.target.hasTag(SWITCH_EXPRESSION)) {
log.error(tree.pos(), Errors.BreakMissingValue);
}
} else {
if (env.info.breakResult.pt.hasTag(VOID)) {
//can happen?
env.info.breakResult.checkContext.report(tree.value.pos(),
diags.fragment(Fragments.UnexpectedRetVal));
}
boolean attribute = true;
if (tree.value.hasTag(IDENT)) {
//disambiguate break <LABEL> and break <ident-as-an-expression>:
Name label = ((JCIdent) tree.value).name;
Pair<JCTree, Error> jumpTarget = findJumpTargetNoError(tree.getTag(), label, env);
if (jumpTarget.fst != null) { public void visitYield(JCYield tree) {
JCTree speculative = deferredAttr.attribSpeculative(tree.value, env, unknownExprInfo); if (env.info.yieldResult != null) {
if (!speculative.type.hasTag(ERROR)) { attribTree(tree.value, env, env.info.yieldResult);
log.error(tree.pos(), Errors.BreakAmbiguousTarget(label)); tree.target = findJumpTarget(tree.pos(), tree.getTag(), names.empty, env);
if (jumpTarget.snd == null) {
tree.target = jumpTarget.fst;
attribute = false;
} else {
//nothing
}
} else {
if (jumpTarget.snd != null) {
log.error(tree.pos(), jumpTarget.snd);
}
tree.target = jumpTarget.fst;
attribute = false;
}
}
}
if (attribute) {
attribTree(tree.value, env, env.info.breakResult);
JCTree immediateTarget = findJumpTarget(tree.pos(), tree.getTag(), null, env);
if (immediateTarget.getTag() != SWITCH_EXPRESSION) {
log.error(tree.pos(), Errors.BreakExprNotImmediate(immediateTarget.getTag()));
Env<AttrContext> env1 = env;
while (env1 != null && env1.tree.getTag() != SWITCH_EXPRESSION) {
env1 = env1.next;
}
Assert.checkNonNull(env1);
tree.target = env1.tree;
} else {
tree.target = immediateTarget;
}
}
}
} else { } else {
if (tree.value == null || tree.value.hasTag(IDENT)) { log.error(tree.pos(), tree.value.hasTag(PARENS)
Name label = tree.value != null ? ((JCIdent) tree.value).name : null; ? Errors.NoSwitchExpressionQualify
tree.target = findJumpTarget(tree.pos(), tree.getTag(), label, env); : Errors.NoSwitchExpression);
} else { attribTree(tree.value, env, unknownExprInfo);
log.error(tree.pos(), Errors.BreakComplexValueNoSwitchExpression);
attribTree(tree.value, env, unknownExprInfo);
}
} }
result = null; result = null;
} }
@ -1934,8 +1888,8 @@ public class Attr extends JCTree.Visitor {
result = null; result = null;
} }
//where //where
/** Return the target of a break or continue statement, if it exists, /** Return the target of a break, continue or yield statement,
* report an error if not. * if it exists, report an error if not.
* Note: The target of a labelled break or continue is the * Note: The target of a labelled break or continue is the
* (non-labelled) statement tree referred to by the label, * (non-labelled) statement tree referred to by the label,
* not the tree representing the labelled statement itself. * not the tree representing the labelled statement itself.
@ -2009,12 +1963,10 @@ public class Attr extends JCTree.Visitor {
if (label == null && tag == BREAK) return Pair.of(env1.tree, null); if (label == null && tag == BREAK) return Pair.of(env1.tree, null);
break; break;
case SWITCH_EXPRESSION: case SWITCH_EXPRESSION:
if (tag == BREAK) { if (tag == YIELD) {
if (label == null) { return Pair.of(env1.tree, null);
return Pair.of(env1.tree, null); } else if (tag == BREAK) {
} else { pendingError = Errors.BreakOutsideSwitchExpression;
pendingError = Errors.BreakOutsideSwitchExpression;
}
} else { } else {
pendingError = Errors.ContinueOutsideSwitchExpression; pendingError = Errors.ContinueOutsideSwitchExpression;
} }
@ -2029,6 +1981,8 @@ public class Attr extends JCTree.Visitor {
} }
if (label != null) if (label != null)
return Pair.of(null, Errors.UndefLabel(label)); return Pair.of(null, Errors.UndefLabel(label));
else if (pendingError != null)
return Pair.of(null, pendingError);
else if (tag == CONTINUE) else if (tag == CONTINUE)
return Pair.of(null, Errors.ContOutsideLoop); return Pair.of(null, Errors.ContOutsideLoop);
else else
@ -2040,7 +1994,7 @@ public class Attr extends JCTree.Visitor {
// nested within than the enclosing class. // nested within than the enclosing class.
if (env.info.returnResult == null) { if (env.info.returnResult == null) {
log.error(tree.pos(), Errors.RetOutsideMeth); log.error(tree.pos(), Errors.RetOutsideMeth);
} else if (env.info.breakResult != null) { } else if (env.info.yieldResult != null) {
log.error(tree.pos(), Errors.ReturnOutsideSwitchExpression); log.error(tree.pos(), Errors.ReturnOutsideSwitchExpression);
} else { } else {
// Attribute return expression, if it exists, and check that // Attribute return expression, if it exists, and check that
@ -3136,7 +3090,7 @@ public class Attr extends JCTree.Visitor {
} else { } else {
lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dup())); lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dup()));
} }
lambdaEnv.info.breakResult = null; lambdaEnv.info.yieldResult = null;
return lambdaEnv; return lambdaEnv;
} }
@ -3916,7 +3870,7 @@ public class Attr extends JCTree.Visitor {
switch (site.getTag()) { switch (site.getTag()) {
case PACKAGE: case PACKAGE:
return rs.accessBase( return rs.accessBase(
rs.findIdentInPackage(env, site.tsym, name, resultInfo.pkind), rs.findIdentInPackage(pos, env, site.tsym, name, resultInfo.pkind),
pos, location, site, name, true); pos, location, site, name, true);
case ARRAY: case ARRAY:
case CLASS: case CLASS:
@ -3931,7 +3885,7 @@ public class Attr extends JCTree.Visitor {
return syms.getClassField(site, types); return syms.getClassField(site, types);
} else { } else {
// We are seeing a plain identifier as selector. // We are seeing a plain identifier as selector.
Symbol sym = rs.findIdentInType(env, site, name, resultInfo.pkind); Symbol sym = rs.findIdentInType(pos, env, site, name, resultInfo.pkind);
sym = rs.accessBase(sym, pos, location, site, name, true); sym = rs.accessBase(sym, pos, location, site, name, true);
return sym; return sym;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -101,10 +101,10 @@ public class AttrContext {
*/ */
Attr.ResultInfo returnResult = null; Attr.ResultInfo returnResult = null;
/** ResultInfo to be used for attributing 'break' statement expressions /** ResultInfo to be used for attributing 'yield' statement expressions
* (set by Attr.visitSwitchExpression) * (set by Attr.visitSwitchExpression)
*/ */
Attr.ResultInfo breakResult = null; Attr.ResultInfo yieldResult = null;
/** Symbol corresponding to the site of a qualified default super call /** Symbol corresponding to the site of a qualified default super call
*/ */
@ -129,7 +129,7 @@ public class AttrContext {
info.lint = lint; info.lint = lint;
info.enclVar = enclVar; info.enclVar = enclVar;
info.returnResult = returnResult; info.returnResult = returnResult;
info.breakResult = breakResult; info.yieldResult = yieldResult;
info.defaultSuperCallSite = defaultSuperCallSite; info.defaultSuperCallSite = defaultSuperCallSite;
info.isSerializable = isSerializable; info.isSerializable = isSerializable;
info.isLambda = isLambda; info.isLambda = isLambda;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -1161,7 +1161,7 @@ public class DeferredAttr extends JCTree.Visitor {
SwitchExpressionScanner() { SwitchExpressionScanner() {
super(EnumSet.of(BLOCK, CASE, CATCH, DOLOOP, FOREACHLOOP, super(EnumSet.of(BLOCK, CASE, CATCH, DOLOOP, FOREACHLOOP,
FORLOOP, IF, BREAK, SYNCHRONIZED, SWITCH, TRY, WHILELOOP)); FORLOOP, IF, SYNCHRONIZED, SWITCH, TRY, WHILELOOP, YIELD));
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -314,6 +314,12 @@ public class Flow {
JCTree getTarget(JCTree tree) { JCTree getTarget(JCTree tree) {
return ((JCContinue)tree).target; return ((JCContinue)tree).target;
} }
},
YIELD(JCTree.Tag.YIELD) {
@Override
JCTree getTarget(JCTree tree) {
return ((JCYield)tree).target;
}
}; };
final JCTree.Tag treeTag; final JCTree.Tag treeTag;
@ -386,6 +392,11 @@ public class Flow {
return resolveJump(tree, oldPendingExits, JumpKind.BREAK); return resolveJump(tree, oldPendingExits, JumpKind.BREAK);
} }
/** Resolve all yields of this statement. */
Liveness resolveYields(JCTree tree, ListBuffer<PendingExit> oldPendingExits) {
return resolveJump(tree, oldPendingExits, JumpKind.YIELD);
}
@Override @Override
public void scan(JCTree tree) { public void scan(JCTree tree) {
if (tree != null && ( if (tree != null && (
@ -400,9 +411,15 @@ public class Flow {
} }
protected void scanSyntheticBreak(TreeMaker make, JCTree swtch) { protected void scanSyntheticBreak(TreeMaker make, JCTree swtch) {
JCBreak brk = make.at(Position.NOPOS).Break(null); if (swtch.hasTag(SWITCH_EXPRESSION)) {
brk.target = swtch; JCYield brk = make.at(Position.NOPOS).Yield(null);
scan(brk); brk.target = swtch;
scan(brk);
} else {
JCBreak brk = make.at(Position.NOPOS).Break(null);
brk.target = swtch;
scan(brk);
}
} }
} }
@ -517,7 +534,8 @@ public class Flow {
while (exits.nonEmpty()) { while (exits.nonEmpty()) {
PendingExit exit = exits.head; PendingExit exit = exits.head;
exits = exits.tail; exits = exits.tail;
Assert.check(exit.tree.hasTag(RETURN)); Assert.check(exit.tree.hasTag(RETURN) ||
log.hasErrorOn(exit.tree.pos()));
} }
} finally { } finally {
lint = lintPrev; lint = lintPrev;
@ -677,7 +695,7 @@ public class Flow {
log.error(tree, Errors.NotExhaustive); log.error(tree, Errors.NotExhaustive);
} }
alive = prevAlive; alive = prevAlive;
alive = alive.or(resolveBreaks(tree, prevPendingExits)); alive = alive.or(resolveYields(tree, prevPendingExits));
} }
public void visitTry(JCTry tree) { public void visitTry(JCTry tree) {
@ -745,8 +763,12 @@ public class Flow {
} }
public void visitBreak(JCBreak tree) { public void visitBreak(JCBreak tree) {
if (tree.isValueBreak()) recordExit(new PendingExit(tree));
scan(tree.value); }
@Override
public void visitYield(JCYield tree) {
scan(tree.value);
recordExit(new PendingExit(tree)); recordExit(new PendingExit(tree));
} }
@ -1032,7 +1054,8 @@ public class Flow {
PendingExit exit = exits.head; PendingExit exit = exits.head;
exits = exits.tail; exits = exits.tail;
if (!(exit instanceof ThrownPendingExit)) { if (!(exit instanceof ThrownPendingExit)) {
Assert.check(exit.tree.hasTag(RETURN)); Assert.check(exit.tree.hasTag(RETURN) ||
log.hasErrorOn(exit.tree.pos()));
} else { } else {
// uncaught throws will be reported later // uncaught throws will be reported later
pendingExits.append(exit); pendingExits.append(exit);
@ -1126,7 +1149,11 @@ public class Flow {
scan(c.pats); scan(c.pats);
scan(c.stats); scan(c.stats);
} }
resolveBreaks(tree, prevPendingExits); if (tree.hasTag(SWITCH_EXPRESSION)) {
resolveYields(tree, prevPendingExits);
} else {
resolveBreaks(tree, prevPendingExits);
}
} }
public void visitTry(JCTry tree) { public void visitTry(JCTry tree) {
@ -1267,8 +1294,11 @@ public class Flow {
} }
public void visitBreak(JCBreak tree) { public void visitBreak(JCBreak tree) {
if (tree.isValueBreak()) recordExit(new PendingExit(tree));
scan(tree.value); }
public void visitYield(JCYield tree) {
scan(tree.value);
recordExit(new PendingExit(tree)); recordExit(new PendingExit(tree));
} }
@ -1357,7 +1387,8 @@ public class Flow {
PendingExit exit = exits.head; PendingExit exit = exits.head;
exits = exits.tail; exits = exits.tail;
if (!(exit instanceof ThrownPendingExit)) { if (!(exit instanceof ThrownPendingExit)) {
Assert.check(exit.tree.hasTag(RETURN)); Assert.check(exit.tree.hasTag(RETURN) ||
log.hasErrorOn(exit.tree.pos()));
} else { } else {
// uncaught throws will be reported later // uncaught throws will be reported later
pendingExits.append(exit); pendingExits.append(exit);
@ -1977,7 +2008,9 @@ public class Flow {
while (exits.nonEmpty()) { while (exits.nonEmpty()) {
PendingExit exit = exits.head; PendingExit exit = exits.head;
exits = exits.tail; exits = exits.tail;
Assert.check(exit.tree.hasTag(RETURN), exit.tree); Assert.check(exit.tree.hasTag(RETURN) ||
log.hasErrorOn(exit.tree.pos()),
exit.tree);
if (isInitialConstructor) { if (isInitialConstructor) {
Assert.check(exit instanceof AssignPendingExit); Assert.check(exit instanceof AssignPendingExit);
inits.assign(((AssignPendingExit) exit).exit_inits); inits.assign(((AssignPendingExit) exit).exit_inits);
@ -2232,7 +2265,11 @@ public class Flow {
inits.andSet(initsSwitch); inits.andSet(initsSwitch);
} }
} }
resolveBreaks(tree, prevPendingExits); if (tree.hasTag(SWITCH_EXPRESSION)) {
resolveYields(tree, prevPendingExits);
} else {
resolveBreaks(tree, prevPendingExits);
}
nextadr = nextadrPrev; nextadr = nextadrPrev;
} }
// where // where
@ -2397,37 +2434,39 @@ public class Flow {
@Override @Override
public void visitBreak(JCBreak tree) { public void visitBreak(JCBreak tree) {
if (tree.isValueBreak()) {
if (tree.target.hasTag(SWITCH_EXPRESSION)) {
JCSwitchExpression expr = (JCSwitchExpression) tree.target;
if (expr.type.hasTag(BOOLEAN)) {
scanCond(tree.value);
Bits initsAfterBreakWhenTrue = new Bits(initsWhenTrue);
Bits initsAfterBreakWhenFalse = new Bits(initsWhenFalse);
Bits uninitsAfterBreakWhenTrue = new Bits(uninitsWhenTrue);
Bits uninitsAfterBreakWhenFalse = new Bits(uninitsWhenFalse);
PendingExit exit = new PendingExit(tree) {
@Override
void resolveJump() {
if (!inits.isReset()) {
split(true);
}
initsWhenTrue.andSet(initsAfterBreakWhenTrue);
initsWhenFalse.andSet(initsAfterBreakWhenFalse);
uninitsWhenTrue.andSet(uninitsAfterBreakWhenTrue);
uninitsWhenFalse.andSet(uninitsAfterBreakWhenFalse);
}
};
merge();
recordExit(exit);
return ;
}
}
scan(tree.value);
}
recordExit(new AssignPendingExit(tree, inits, uninits)); recordExit(new AssignPendingExit(tree, inits, uninits));
} }
@Override
public void visitYield(JCYield tree) {
JCSwitchExpression expr = (JCSwitchExpression) tree.target;
if (expr != null && expr.type.hasTag(BOOLEAN)) {
scanCond(tree.value);
Bits initsAfterBreakWhenTrue = new Bits(initsWhenTrue);
Bits initsAfterBreakWhenFalse = new Bits(initsWhenFalse);
Bits uninitsAfterBreakWhenTrue = new Bits(uninitsWhenTrue);
Bits uninitsAfterBreakWhenFalse = new Bits(uninitsWhenFalse);
PendingExit exit = new PendingExit(tree) {
@Override
void resolveJump() {
if (!inits.isReset()) {
split(true);
}
initsWhenTrue.andSet(initsAfterBreakWhenTrue);
initsWhenFalse.andSet(initsAfterBreakWhenFalse);
uninitsWhenTrue.andSet(uninitsAfterBreakWhenTrue);
uninitsWhenFalse.andSet(uninitsAfterBreakWhenFalse);
}
};
merge();
recordExit(exit);
return ;
} else {
scan(tree.value);
recordExit(new AssignPendingExit(tree, inits, uninits));
}
}
@Override @Override
public void visitContinue(JCContinue tree) { public void visitContinue(JCContinue tree) {
recordExit(new AssignPendingExit(tree, inits, uninits)); recordExit(new AssignPendingExit(tree, inits, uninits));
@ -2788,9 +2827,8 @@ public class Flow {
} }
@Override @Override
public void visitBreak(JCBreak tree) { public void visitYield(JCYield tree) {
if (tree.isValueBreak()) scan(tree.value);
scan(tree.value);
} }
public void visitModuleDef(JCModuleDecl tree) { public void visitModuleDef(JCModuleDecl tree) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -272,9 +272,8 @@ public class Lower extends TreeTranslator {
} }
@Override @Override
public void visitBreak(JCBreak tree) { public void visitYield(JCYield tree) {
if (tree.isValueBreak()) scan(tree.value);
scan(tree.value);
} }
} }
@ -1887,7 +1886,7 @@ public class Lower extends TreeTranslator {
ClassSymbol c = types.boxedClass(type); ClassSymbol c = types.boxedClass(type);
Symbol typeSym = Symbol typeSym =
rs.accessBase( rs.accessBase(
rs.findIdentInType(attrEnv, c.type, names.TYPE, KindSelector.VAR), rs.findIdentInType(pos, attrEnv, c.type, names.TYPE, KindSelector.VAR),
pos, c.type, names.TYPE, true); pos, c.type, names.TYPE, true);
if (typeSym.kind == VAR) if (typeSym.kind == VAR)
((VarSymbol)typeSym).getConstValue(); // ensure initializer is evaluated ((VarSymbol)typeSym).getConstValue(); // ensure initializer is evaluated
@ -3224,6 +3223,11 @@ public class Lower extends TreeTranslator {
if (tree.target == src) if (tree.target == src)
tree.target = dest; tree.target = dest;
} }
public void visitYield(JCYield tree) {
if (tree.target == src)
tree.target = dest;
scan(tree.value);
}
public void visitContinue(JCContinue tree) { public void visitContinue(JCContinue tree) {
if (tree.target == src) if (tree.target == src)
tree.target = dest; tree.target = dest;
@ -3676,9 +3680,12 @@ public class Lower extends TreeTranslator {
@Override @Override
public void visitBreak(JCBreak tree) { public void visitBreak(JCBreak tree) {
if (tree.isValueBreak()) { result = tree;
tree.value = translate(tree.value, tree.target.type); }
}
@Override
public void visitYield(JCYield tree) {
tree.value = translate(tree.value, tree.target.type);
result = tree; result = tree;
} }

View file

@ -245,7 +245,7 @@ public class MemberEnter extends JCTree.Visitor {
tree.sym.type.getReturnType()); tree.sym.type.getReturnType());
} }
if ((tree.mods.flags & STATIC) != 0) localEnv.info.staticLevel++; if ((tree.mods.flags & STATIC) != 0) localEnv.info.staticLevel++;
localEnv.info.breakResult = null; localEnv.info.yieldResult = null;
return localEnv; return localEnv;
} }

View file

@ -43,6 +43,7 @@ import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.main.Option; import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.resources.CompilerProperties.Errors; import com.sun.tools.javac.resources.CompilerProperties.Errors;
import com.sun.tools.javac.resources.CompilerProperties.Fragments; import com.sun.tools.javac.resources.CompilerProperties.Fragments;
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
import com.sun.tools.javac.tree.*; import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind; import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
@ -52,6 +53,7 @@ import com.sun.tools.javac.util.DefinedBy.Api;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
import com.sun.tools.javac.util.JCDiagnostic.Warning;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -63,6 +65,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -105,6 +108,7 @@ public class Resolve {
public final boolean checkVarargsAccessAfterResolution; public final boolean checkVarargsAccessAfterResolution;
private final boolean compactMethodDiags; private final boolean compactMethodDiags;
private final boolean allowLocalVariableTypeInference; private final boolean allowLocalVariableTypeInference;
private final boolean allowYieldStatement;
final EnumSet<VerboseResolutionMode> verboseResolutionMode; final EnumSet<VerboseResolutionMode> verboseResolutionMode;
WriteableScope polymorphicSignatureScope; WriteableScope polymorphicSignatureScope;
@ -128,6 +132,7 @@ public class Resolve {
moduleFinder = ModuleFinder.instance(context); moduleFinder = ModuleFinder.instance(context);
types = Types.instance(context); types = Types.instance(context);
diags = JCDiagnostic.Factory.instance(context); diags = JCDiagnostic.Factory.instance(context);
Preview preview = Preview.instance(context);
Source source = Source.instance(context); Source source = Source.instance(context);
Options options = Options.instance(context); Options options = Options.instance(context);
compactMethodDiags = options.isSet(Option.XDIAGS, "compact") || compactMethodDiags = options.isSet(Option.XDIAGS, "compact") ||
@ -136,6 +141,8 @@ public class Resolve {
Target target = Target.instance(context); Target target = Target.instance(context);
allowFunctionalInterfaceMostSpecific = Feature.FUNCTIONAL_INTERFACE_MOST_SPECIFIC.allowedInSource(source); allowFunctionalInterfaceMostSpecific = Feature.FUNCTIONAL_INTERFACE_MOST_SPECIFIC.allowedInSource(source);
allowLocalVariableTypeInference = Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source); allowLocalVariableTypeInference = Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source);
allowYieldStatement = (!preview.isPreview(Feature.SWITCH_EXPRESSION) || preview.isEnabled()) &&
Feature.SWITCH_EXPRESSION.allowedInSource(source);
checkVarargsAccessAfterResolution = checkVarargsAccessAfterResolution =
Feature.POST_APPLICABILITY_VARARGS_ACCESS_CHECK.allowedInSource(source); Feature.POST_APPLICABILITY_VARARGS_ACCESS_CHECK.allowedInSource(source);
polymorphicSignatureScope = WriteableScope.create(syms.noSymbol); polymorphicSignatureScope = WriteableScope.create(syms.noSymbol);
@ -2330,13 +2337,15 @@ public class Resolve {
} }
/** Find an unqualified identifier which matches a specified kind set. /** Find an unqualified identifier which matches a specified kind set.
* @param pos position on which report warnings, if any;
* null warnings should not be reported
* @param env The current environment. * @param env The current environment.
* @param name The identifier's name. * @param name The identifier's name.
* @param kind Indicates the possible symbol kinds * @param kind Indicates the possible symbol kinds
* (a subset of VAL, TYP, PCK). * (a subset of VAL, TYP, PCK).
*/ */
Symbol findIdent(Env<AttrContext> env, Name name, KindSelector kind) { Symbol findIdent(DiagnosticPosition pos, Env<AttrContext> env, Name name, KindSelector kind) {
return checkVarType(findIdentInternal(env, name, kind), name); return checkRestrictedType(pos, findIdentInternal(env, name, kind), name);
} }
Symbol findIdentInternal(Env<AttrContext> env, Name name, KindSelector kind) { Symbol findIdentInternal(Env<AttrContext> env, Name name, KindSelector kind) {
@ -2362,14 +2371,17 @@ public class Resolve {
} }
/** Find an identifier in a package which matches a specified kind set. /** Find an identifier in a package which matches a specified kind set.
* @param pos position on which report warnings, if any;
* null warnings should not be reported
* @param env The current environment. * @param env The current environment.
* @param name The identifier's name. * @param name The identifier's name.
* @param kind Indicates the possible symbol kinds * @param kind Indicates the possible symbol kinds
* (a nonempty subset of TYP, PCK). * (a nonempty subset of TYP, PCK).
*/ */
Symbol findIdentInPackage(Env<AttrContext> env, TypeSymbol pck, Symbol findIdentInPackage(DiagnosticPosition pos,
Env<AttrContext> env, TypeSymbol pck,
Name name, KindSelector kind) { Name name, KindSelector kind) {
return checkVarType(findIdentInPackageInternal(env, pck, name, kind), name); return checkRestrictedType(pos, findIdentInPackageInternal(env, pck, name, kind), name);
} }
Symbol findIdentInPackageInternal(Env<AttrContext> env, TypeSymbol pck, Symbol findIdentInPackageInternal(Env<AttrContext> env, TypeSymbol pck,
@ -2395,15 +2407,18 @@ public class Resolve {
} }
/** Find an identifier among the members of a given type `site'. /** Find an identifier among the members of a given type `site'.
* @param pos position on which report warnings, if any;
* null warnings should not be reported
* @param env The current environment. * @param env The current environment.
* @param site The type containing the symbol to be found. * @param site The type containing the symbol to be found.
* @param name The identifier's name. * @param name The identifier's name.
* @param kind Indicates the possible symbol kinds * @param kind Indicates the possible symbol kinds
* (a subset of VAL, TYP). * (a subset of VAL, TYP).
*/ */
Symbol findIdentInType(Env<AttrContext> env, Type site, Symbol findIdentInType(DiagnosticPosition pos,
Env<AttrContext> env, Type site,
Name name, KindSelector kind) { Name name, KindSelector kind) {
return checkVarType(findIdentInTypeInternal(env, site, name, kind), name); return checkRestrictedType(pos, findIdentInTypeInternal(env, site, name, kind), name);
} }
Symbol findIdentInTypeInternal(Env<AttrContext> env, Type site, Symbol findIdentInTypeInternal(Env<AttrContext> env, Type site,
@ -2424,10 +2439,17 @@ public class Resolve {
return bestSoFar; return bestSoFar;
} }
private Symbol checkVarType(Symbol bestSoFar, Name name) { private Symbol checkRestrictedType(DiagnosticPosition pos, Symbol bestSoFar, Name name) {
if (allowLocalVariableTypeInference && name.equals(names.var) && if (bestSoFar.kind == TYP || bestSoFar.kind == ABSENT_TYP) {
(bestSoFar.kind == TYP || bestSoFar.kind == ABSENT_TYP)) { if (allowLocalVariableTypeInference && name.equals(names.var)) {
bestSoFar = new BadVarTypeError(); bestSoFar = new BadRestrictedTypeError(names.var);
} else if (name.equals(names.yield)) {
if (allowYieldStatement) {
bestSoFar = new BadRestrictedTypeError(names.yield);
} else if (pos != null) {
log.warning(pos, Warnings.IllegalRefToRestrictedType(names.yield));
}
}
} }
return bestSoFar; return bestSoFar;
} }
@ -2597,7 +2619,7 @@ public class Resolve {
Symbol resolveIdent(DiagnosticPosition pos, Env<AttrContext> env, Symbol resolveIdent(DiagnosticPosition pos, Env<AttrContext> env,
Name name, KindSelector kind) { Name name, KindSelector kind) {
return accessBase( return accessBase(
findIdent(env, name, kind), findIdent(pos, env, name, kind),
pos, env.enclClass.sym.type, name, false); pos, env.enclClass.sym.type, name, false);
} }
@ -3833,14 +3855,16 @@ public class Resolve {
} }
} }
class BadVarTypeError extends ResolveError { class BadRestrictedTypeError extends ResolveError {
BadVarTypeError() { private final Name typeName;
super(Kind.BAD_VAR, "bad var use"); BadRestrictedTypeError(Name typeName) {
super(Kind.BAD_RESTRICTED_TYPE, "bad var use");
this.typeName = typeName;
} }
@Override @Override
JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
return diags.create(dkind, log.currentSource(), pos, "illegal.ref.to.var.type"); return diags.create(dkind, log.currentSource(), pos, "illegal.ref.to.restricted.type", typeName);
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -620,11 +620,14 @@ public class TransTypes extends TreeTranslator {
@Override @Override
public void visitBreak(JCBreak tree) { public void visitBreak(JCBreak tree) {
if (tree.isValueBreak()) { result = tree;
tree.value = translate(tree.value, erasure(tree.value.type)); }
tree.value.type = erasure(tree.value.type);
tree.value = retype(tree.value, tree.value.type, pt); @Override
} public void visitYield(JCYield tree) {
tree.value = translate(tree.value, erasure(tree.value.type));
tree.value.type = erasure(tree.value.type);
tree.value = retype(tree.value, tree.value.type, pt);
result = tree; result = tree;
} }

View file

@ -71,6 +71,7 @@ import com.sun.tools.javac.tree.JCTree.JCProvides;
import com.sun.tools.javac.tree.JCTree.JCRequires; import com.sun.tools.javac.tree.JCTree.JCRequires;
import com.sun.tools.javac.tree.JCTree.JCReturn; import com.sun.tools.javac.tree.JCTree.JCReturn;
import com.sun.tools.javac.tree.JCTree.JCSwitch; import com.sun.tools.javac.tree.JCTree.JCSwitch;
import com.sun.tools.javac.tree.JCTree.JCSwitchExpression;
import com.sun.tools.javac.tree.JCTree.JCSynchronized; import com.sun.tools.javac.tree.JCTree.JCSynchronized;
import com.sun.tools.javac.tree.JCTree.JCThrow; import com.sun.tools.javac.tree.JCTree.JCThrow;
import com.sun.tools.javac.tree.JCTree.JCTry; import com.sun.tools.javac.tree.JCTree.JCTry;
@ -84,6 +85,7 @@ import com.sun.tools.javac.tree.JCTree.JCUses;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.JCTree.JCWhileLoop; import com.sun.tools.javac.tree.JCTree.JCWhileLoop;
import com.sun.tools.javac.tree.JCTree.JCWildcard; import com.sun.tools.javac.tree.JCTree.JCWildcard;
import com.sun.tools.javac.tree.JCTree.JCYield;
import com.sun.tools.javac.tree.JCTree.LetExpr; import com.sun.tools.javac.tree.JCTree.LetExpr;
import com.sun.tools.javac.tree.JCTree.TypeBoundKind; import com.sun.tools.javac.tree.JCTree.TypeBoundKind;
import com.sun.tools.javac.tree.TreeInfo; import com.sun.tools.javac.tree.TreeInfo;
@ -259,6 +261,12 @@ public class TreeDiffer extends TreeScanner {
@Override @Override
public void visitBreak(JCBreak tree) { public void visitBreak(JCBreak tree) {
JCBreak that = (JCBreak) parameter; JCBreak that = (JCBreak) parameter;
result = tree.label == that.label;
}
@Override
public void visitYield(JCYield tree) {
JCYield that = (JCYield) parameter;
result = scan(tree.value, that.value); result = scan(tree.value, that.value);
} }
@ -498,6 +506,12 @@ public class TreeDiffer extends TreeScanner {
result = scan(tree.selector, that.selector) && scan(tree.cases, that.cases); result = scan(tree.selector, that.selector) && scan(tree.cases, that.cases);
} }
@Override
public void visitSwitchExpression(JCSwitchExpression tree) {
JCSwitchExpression that = (JCSwitchExpression) parameter;
result = scan(tree.selector, that.selector) && scan(tree.cases, that.cases);
}
@Override @Override
public void visitSynchronized(JCSynchronized tree) { public void visitSynchronized(JCSynchronized tree) {
JCSynchronized that = (JCSynchronized) parameter; JCSynchronized that = (JCSynchronized) parameter;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -377,6 +377,11 @@ implements CRTFlags {
result = sr; result = sr;
} }
public void visitYield(JCYield tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
result = sr;
}
public void visitContinue(JCContinue tree) { public void visitContinue(JCContinue tree) {
SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
result = sr; result = sr;

View file

@ -1716,47 +1716,49 @@ public class Gen extends JCTree.Visitor {
} }
public void visitBreak(JCBreak tree) { public void visitBreak(JCBreak tree) {
Assert.check(code.isStatementStart());
final Env<GenContext> targetEnv = unwindBreak(tree.target);
targetEnv.info.addExit(code.branch(goto_));
endFinalizerGaps(env, targetEnv);
}
public void visitYield(JCYield tree) {
Assert.check(code.isStatementStart()); Assert.check(code.isStatementStart());
final Env<GenContext> targetEnv; final Env<GenContext> targetEnv;
if (tree.isValueBreak()) { //restore stack as it was before the switch expression:
//restore stack as it was before the switch expression: for (LocalItem li : stackBeforeSwitchExpression) {
for (LocalItem li : stackBeforeSwitchExpression) { li.load();
li.load(); }
} if (inCondSwitchExpression) {
if (inCondSwitchExpression) { CondItem value = genCond(tree.value, CRT_FLOW_TARGET);
CondItem value = genCond(tree.value, CRT_FLOW_TARGET); Chain falseJumps = value.jumpFalse();
Chain falseJumps = value.jumpFalse(); targetEnv = unwindBreak(tree.target);
targetEnv = unwindBreak(tree); code.resolve(value.trueJumps);
code.resolve(value.trueJumps); Chain trueJumps = code.branch(goto_);
Chain trueJumps = code.branch(goto_); if (switchExpressionTrueChain == null) {
if (switchExpressionTrueChain == null) { switchExpressionTrueChain = trueJumps;
switchExpressionTrueChain = trueJumps;
} else {
switchExpressionTrueChain =
Code.mergeChains(switchExpressionTrueChain, trueJumps);
}
if (switchExpressionFalseChain == null) {
switchExpressionFalseChain = falseJumps;
} else {
switchExpressionFalseChain =
Code.mergeChains(switchExpressionFalseChain, falseJumps);
}
} else { } else {
genExpr(tree.value, pt).load(); switchExpressionTrueChain =
code.state.forceStackTop(tree.target.type); Code.mergeChains(switchExpressionTrueChain, trueJumps);
targetEnv = unwindBreak(tree); }
targetEnv.info.addExit(code.branch(goto_)); if (switchExpressionFalseChain == null) {
switchExpressionFalseChain = falseJumps;
} else {
switchExpressionFalseChain =
Code.mergeChains(switchExpressionFalseChain, falseJumps);
} }
} else { } else {
targetEnv = unwindBreak(tree); genExpr(tree.value, pt).load();
code.state.forceStackTop(tree.target.type);
targetEnv = unwindBreak(tree.target);
targetEnv.info.addExit(code.branch(goto_)); targetEnv.info.addExit(code.branch(goto_));
} }
endFinalizerGaps(env, targetEnv); endFinalizerGaps(env, targetEnv);
} }
//where: //where:
private Env<GenContext> unwindBreak(JCBreak tree) { private Env<GenContext> unwindBreak(JCTree target) {
int tmpPos = code.pendingStatPos; int tmpPos = code.pendingStatPos;
Env<GenContext> targetEnv = unwind(tree.target, env); Env<GenContext> targetEnv = unwind(target, env);
code.pendingStatPos = tmpPos; code.pendingStatPos = tmpPos;
return targetEnv; return targetEnv;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -182,6 +182,8 @@ public class JavacParser implements Parser {
this.keepLineMap = keepLineMap; this.keepLineMap = keepLineMap;
this.errorTree = F.Erroneous(); this.errorTree = F.Erroneous();
endPosTable = newEndPosTable(keepEndPositions); endPosTable = newEndPosTable(keepEndPositions);
this.allowYieldStatement = (!preview.isPreview(Feature.SWITCH_EXPRESSION) || preview.isEnabled()) &&
Feature.SWITCH_EXPRESSION.allowedInSource(source);
} }
protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) { protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
@ -211,6 +213,10 @@ public class JavacParser implements Parser {
*/ */
boolean allowThisIdent; boolean allowThisIdent;
/** Switch: is yield statement allowed in this source level?
*/
boolean allowYieldStatement;
/** The type of the method receiver, as specified by a first "this" parameter. /** The type of the method receiver, as specified by a first "this" parameter.
*/ */
JCVariableDecl receiverParam; JCVariableDecl receiverParam;
@ -769,9 +775,10 @@ public class JavacParser implements Parser {
public JCExpression unannotatedType(boolean allowVar) { public JCExpression unannotatedType(boolean allowVar) {
JCExpression result = term(TYPE); JCExpression result = term(TYPE);
Name restrictedTypeName;
if (!allowVar && isRestrictedLocalVarTypeName(result, true)) { if (!allowVar && (restrictedTypeName = restrictedTypeName(result, true)) != null) {
syntaxError(result.pos, Errors.VarNotAllowedHere); syntaxError(result.pos, Errors.RestrictedTypeNotAllowedHere(restrictedTypeName));
} }
return result; return result;
@ -1377,6 +1384,7 @@ public class JavacParser implements Parser {
break; break;
case SWITCH: case SWITCH:
checkSourceLevel(Feature.SWITCH_EXPRESSION); checkSourceLevel(Feature.SWITCH_EXPRESSION);
allowYieldStatement = true;
int switchPos = token.pos; int switchPos = token.pos;
nextToken(); nextToken();
JCExpression selector = parExpression(); JCExpression selector = parExpression();
@ -1436,7 +1444,7 @@ public class JavacParser implements Parser {
kind = JCCase.RULE; kind = JCCase.RULE;
} else { } else {
JCExpression value = parseExpression(); JCExpression value = parseExpression();
stats = List.of(to(F.at(value).Break(value))); stats = List.of(to(F.at(value).Yield(value)));
body = value; body = value;
kind = JCCase.RULE; kind = JCCase.RULE;
accept(SEMI); accept(SEMI);
@ -1607,7 +1615,7 @@ public class JavacParser implements Parser {
int depth = 0; int depth = 0;
boolean type = false; boolean type = false;
ParensResult defaultResult = ParensResult.PARENS; ParensResult defaultResult = ParensResult.PARENS;
outer: for (int lookahead = 0 ; ; lookahead++) { outer: for (int lookahead = 0; ; lookahead++) {
TokenKind tk = S.token(lookahead).kind; TokenKind tk = S.token(lookahead).kind;
switch (tk) { switch (tk) {
case COMMA: case COMMA:
@ -1782,12 +1790,13 @@ public class JavacParser implements Parser {
if (explicitParams) { if (explicitParams) {
LambdaClassifier lambdaClassifier = new LambdaClassifier(); LambdaClassifier lambdaClassifier = new LambdaClassifier();
for (JCVariableDecl param: params) { for (JCVariableDecl param: params) {
Name restrictedTypeName;
if (param.vartype != null && if (param.vartype != null &&
isRestrictedLocalVarTypeName(param.vartype, false) && (restrictedTypeName = restrictedTypeName(param.vartype, false)) != null &&
param.vartype.hasTag(TYPEARRAY)) { param.vartype.hasTag(TYPEARRAY)) {
log.error(DiagnosticFlag.SYNTAX, param.pos, log.error(DiagnosticFlag.SYNTAX, param.pos,
Feature.VAR_SYNTAX_IMPLICIT_LAMBDAS.allowedInSource(source) Feature.VAR_SYNTAX_IMPLICIT_LAMBDAS.allowedInSource(source)
? Errors.VarNotAllowedArray : Errors.VarNotAllowedHere); ? Errors.RestrictedTypeNotAllowedArray(restrictedTypeName) : Errors.RestrictedTypeNotAllowedHere(restrictedTypeName));
} }
lambdaClassifier.addParameter(param); lambdaClassifier.addParameter(param);
if (lambdaClassifier.result() == LambdaParameterKind.ERROR) { if (lambdaClassifier.result() == LambdaParameterKind.ERROR) {
@ -1799,7 +1808,7 @@ public class JavacParser implements Parser {
} }
for (JCVariableDecl param: params) { for (JCVariableDecl param: params) {
if (param.vartype != null if (param.vartype != null
&& isRestrictedLocalVarTypeName(param.vartype, true)) { && restrictedTypeName(param.vartype, true) != null) {
checkSourceLevel(param.pos, Feature.VAR_SYNTAX_IMPLICIT_LAMBDAS); checkSourceLevel(param.pos, Feature.VAR_SYNTAX_IMPLICIT_LAMBDAS);
param.startPos = TreeInfo.getStartPos(param.vartype); param.startPos = TreeInfo.getStartPos(param.vartype);
param.vartype = null; param.vartype = null;
@ -1837,7 +1846,7 @@ public class JavacParser implements Parser {
void addParameter(JCVariableDecl param) { void addParameter(JCVariableDecl param) {
if (param.vartype != null && param.name != names.empty) { if (param.vartype != null && param.name != names.empty) {
if (isRestrictedLocalVarTypeName(param.vartype, false)) { if (restrictedTypeName(param.vartype, false) != null) {
reduce(LambdaParameterKind.VAR); reduce(LambdaParameterKind.VAR);
} else { } else {
reduce(LambdaParameterKind.EXPLICIT); reduce(LambdaParameterKind.EXPLICIT);
@ -1944,10 +1953,27 @@ public class JavacParser implements Parser {
return args.toList(); return args.toList();
} }
JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) { JCExpression arguments(List<JCExpression> typeArgs, JCExpression t) {
int pos = token.pos; int pos = token.pos;
List<JCExpression> args = arguments(); List<JCExpression> args = arguments();
return toP(F.at(pos).Apply(typeArgs, t, args)); JCExpression mi = F.at(pos).Apply(typeArgs, t, args);
if (t.hasTag(IDENT) && isInvalidUnqualifiedMethodIdentifier(((JCIdent) t).pos,
((JCIdent) t).name)) {
log.error(DiagnosticFlag.SYNTAX, t, Errors.InvalidYield);
mi = F.Erroneous(List.of(mi));
}
return toP(mi);
}
boolean isInvalidUnqualifiedMethodIdentifier(int pos, Name name) {
if (name == names.yield) {
if (allowYieldStatement) {
return true;
} else {
log.warning(pos, Warnings.InvalidYield);
}
}
return false;
} }
/** TypeArgumentsOpt = [ TypeArguments ] /** TypeArgumentsOpt = [ TypeArguments ]
@ -2506,6 +2532,7 @@ public class JavacParser implements Parser {
/**This method parses a statement appearing inside a block. /**This method parses a statement appearing inside a block.
*/ */
@SuppressWarnings("fallthrough")
List<JCStatement> blockStatement() { List<JCStatement> blockStatement() {
//todo: skip to anchor on error(?) //todo: skip to anchor on error(?)
int pos = token.pos; int pos = token.pos;
@ -2543,6 +2570,52 @@ public class JavacParser implements Parser {
log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.LocalEnum); log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.LocalEnum);
dc = token.comment(CommentStyle.JAVADOC); dc = token.comment(CommentStyle.JAVADOC);
return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc)); return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
case IDENTIFIER:
if (token.name() == names.yield && allowYieldStatement) {
Token next = S.token(1);
boolean isYieldStatement;
switch (next.kind) {
case PLUS: case SUB: case STRINGLITERAL: case CHARLITERAL:
case INTLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
case NULL: case IDENTIFIER: case TRUE: case FALSE:
case NEW: case SWITCH: case THIS: case SUPER:
isYieldStatement = true;
break;
case PLUSPLUS: case SUBSUB:
isYieldStatement = S.token(2).kind != SEMI;
break;
case LPAREN:
int lookahead = 2;
int balance = 1;
boolean hasComma = false;
Token l;
while ((l = S.token(lookahead)).kind != EOF && balance != 0) {
switch (l.kind) {
case LPAREN: balance++; break;
case RPAREN: balance--; break;
case COMMA: if (balance == 1) hasComma = true; break;
}
lookahead++;
}
isYieldStatement = (!hasComma && lookahead != 3) || l.kind == ARROW;
break;
case SEMI: //error recovery - this is not a valid statement:
isYieldStatement = true;
break;
default:
isYieldStatement = false;
break;
}
if (isYieldStatement) {
nextToken();
JCExpression t = term(EXPR);
accept(SEMI);
return List.of(toP(F.at(pos).Yield(t)));
}
//else intentional fall-through
}
default: default:
Token prevToken = token; Token prevToken = token;
JCExpression t = term(EXPR | TYPE); JCExpression t = term(EXPR | TYPE);
@ -2702,9 +2775,9 @@ public class JavacParser implements Parser {
} }
case BREAK: { case BREAK: {
nextToken(); nextToken();
JCExpression value = token.kind == SEMI ? null : parseExpression(); Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
accept(SEMI); accept(SEMI);
JCBreak t = toP(F.at(pos).Break(value)); JCBreak t = toP(F.at(pos).Break(label));
return t; return t;
} }
case CONTINUE: { case CONTINUE: {
@ -3181,14 +3254,14 @@ public class JavacParser implements Parser {
int startPos = Position.NOPOS; int startPos = Position.NOPOS;
if (elemType.hasTag(IDENT)) { if (elemType.hasTag(IDENT)) {
Name typeName = ((JCIdent)elemType).name; Name typeName = ((JCIdent)elemType).name;
if (isRestrictedLocalVarTypeName(typeName, pos, !compound && localDecl)) { if (isRestrictedTypeName(typeName, pos, !compound && localDecl)) {
if (type.hasTag(TYPEARRAY) && !compound) { if (type.hasTag(TYPEARRAY) && !compound) {
//error - 'var' and arrays //error - 'var' and arrays
reportSyntaxError(pos, Errors.VarNotAllowedArray); reportSyntaxError(pos, Errors.RestrictedTypeNotAllowedArray(typeName));
} else { } else {
if(compound) if(compound)
//error - 'var' in compound local var decl //error - 'var' in compound local var decl
reportSyntaxError(pos, Errors.VarNotAllowedCompound); reportSyntaxError(pos, Errors.RestrictedTypeNotAllowedCompound(typeName));
startPos = TreeInfo.getStartPos(mods); startPos = TreeInfo.getStartPos(mods);
if (startPos == Position.NOPOS) if (startPos == Position.NOPOS)
startPos = TreeInfo.getStartPos(type); startPos = TreeInfo.getStartPos(type);
@ -3204,23 +3277,30 @@ public class JavacParser implements Parser {
return result; return result;
} }
boolean isRestrictedLocalVarTypeName(JCExpression e, boolean shouldWarn) { Name restrictedTypeName(JCExpression e, boolean shouldWarn) {
switch (e.getTag()) { switch (e.getTag()) {
case IDENT: case IDENT:
return isRestrictedLocalVarTypeName(((JCIdent)e).name, e.pos, shouldWarn); return isRestrictedTypeName(((JCIdent)e).name, e.pos, shouldWarn) ? ((JCIdent)e).name : null;
case TYPEARRAY: case TYPEARRAY:
return isRestrictedLocalVarTypeName(((JCArrayTypeTree)e).elemtype, shouldWarn); return restrictedTypeName(((JCArrayTypeTree)e).elemtype, shouldWarn);
default: default:
return false; return null;
} }
} }
boolean isRestrictedLocalVarTypeName(Name name, int pos, boolean shouldWarn) { boolean isRestrictedTypeName(Name name, int pos, boolean shouldWarn) {
if (name == names.var) { if (name == names.var) {
if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) { if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
return true; return true;
} else if (shouldWarn) { } else if (shouldWarn) {
log.warning(pos, Warnings.VarNotAllowed); log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
}
}
if (name == names.yield) {
if (allowYieldStatement) {
return true;
} else if (shouldWarn) {
log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK13));
} }
} }
return false; return false;
@ -3614,8 +3694,8 @@ public class JavacParser implements Parser {
Name typeName() { Name typeName() {
int pos = token.pos; int pos = token.pos;
Name name = ident(); Name name = ident();
if (isRestrictedLocalVarTypeName(name, pos, true)) { if (isRestrictedTypeName(name, pos, true)) {
reportSyntaxError(pos, Errors.VarNotAllowed); reportSyntaxError(pos, Errors.RestrictedTypeNotAllowed(name, name == names.var ? Source.JDK10 : Source.JDK13));
} }
return name; return name;
} }

View file

@ -188,17 +188,14 @@ compiler.err.bad.initializer=\
compiler.err.break.outside.switch.loop=\ compiler.err.break.outside.switch.loop=\
break outside switch or loop break outside switch or loop
compiler.err.break.missing.value=\
missing break value
compiler.err.break.outside.switch.expression=\ compiler.err.break.outside.switch.expression=\
break outside of enclosing switch expression attempt to break out of a switch expression
compiler.err.continue.outside.switch.expression=\ compiler.err.continue.outside.switch.expression=\
continue outside of enclosing switch expression attempt to continue out of a switch expression
compiler.err.return.outside.switch.expression=\ compiler.err.return.outside.switch.expression=\
return outside of enclosing switch expression attempt to return out of a switch expression
compiler.err.rule.completes.normally=\ compiler.err.rule.completes.normally=\
switch rule completes without providing a value\n\ switch rule completes without providing a value\n\
@ -208,17 +205,20 @@ compiler.err.switch.expression.completes.normally=\
switch expression completes without providing a value\n\ switch expression completes without providing a value\n\
(switch expressions must either provide a value or throw for all possible input values) (switch expressions must either provide a value or throw for all possible input values)
# 0: name compiler.err.no.switch.expression =\
compiler.err.break.ambiguous.target=\ yield outside of switch expression
ambiguous reference to ''{0}''\n\
(''{0}'' is both a label and an expression)
# 0: tree tag compiler.err.no.switch.expression.qualify=\
compiler.err.break.expr.not.immediate=\ yield outside of switch expression\n\
value break not supported in ''{0}'' (to invoke a method called yield, qualify the yield with a receiver or type name)
compiler.err.break.complex.value.no.switch.expression=\ compiler.err.invalid.yield=\
unexpected value break invalid use of a restricted identifier ''yield''\n\
(to invoke a method called yield, qualify the yield with a receiver or type name)
compiler.warn.invalid.yield=\
''yield'' may become a restricted identifier in a future release\n\
(to invoke a method called yield, qualify the yield with a receiver or type name)
compiler.err.switch.expression.empty=\ compiler.err.switch.expression.empty=\
switch expression does not have any case clauses switch expression does not have any case clauses
@ -1267,29 +1267,43 @@ compiler.err.io.exception=\
compiler.err.undef.label=\ compiler.err.undef.label=\
undefined label: {0} undefined label: {0}
compiler.err.illegal.ref.to.var.type=\ # 0: name
illegal reference to restricted type ''var'' compiler.err.illegal.ref.to.restricted.type=\
illegal reference to restricted type ''{0}''
compiler.err.var.not.allowed=\ # 0: name
''var'' not allowed here\n\ compiler.warn.illegal.ref.to.restricted.type=\
as of release 10, ''var'' is a restricted local variable type and cannot be used for type declarations illegal reference to restricted type ''{0}''
compiler.warn.var.not.allowed=\ # 0: name, 1: source
as of release 10, ''var'' is a restricted local variable type and cannot be used for type declarations or as the element type of an array compiler.err.restricted.type.not.allowed=\
''{0}'' not allowed here\n\
as of release {1}, ''{0}'' is a restricted type name and cannot be used for type declarations
# 0: name, 1: source
compiler.warn.restricted.type.not.allowed=\
as of release {1}, ''{0}'' is a restricted type name and cannot be used for type declarations or as the element type of an array
# 0: name, 1: source
compiler.warn.restricted.type.not.allowed.preview=\
''{0}'' may become a restricted type name in a future release and may be unusable for type declarations or as the element type of an array
# 0: name (variable), 1: message segment # 0: name (variable), 1: message segment
compiler.err.cant.infer.local.var.type=\ compiler.err.cant.infer.local.var.type=\
cannot infer type for local variable {0}\n\ cannot infer type for local variable {0}\n\
({1}) ({1})
compiler.err.var.not.allowed.here=\ # 0: name
''var'' is not allowed here compiler.err.restricted.type.not.allowed.here=\
''{0}'' is not allowed here
compiler.err.var.not.allowed.array=\ # 0: name
''var'' is not allowed as an element type of an array compiler.err.restricted.type.not.allowed.array=\
''{0}'' is not allowed as an element type of an array
compiler.err.var.not.allowed.compound=\ # 0: name
''var'' is not allowed in a compound declaration compiler.err.restricted.type.not.allowed.compound=\
''{0}'' is not allowed in a compound declaration
# 0: fragment # 0: fragment
compiler.err.invalid.lambda.parameter.declaration=\ compiler.err.invalid.lambda.parameter.declaration=\
@ -2666,22 +2680,6 @@ compiler.misc.kindname.static.init=\
compiler.misc.kindname.instance.init=\ compiler.misc.kindname.instance.init=\
instance initializer instance initializer
# the following are names of tree kinds:
compiler.misc.tree.tag.forloop=\
for
compiler.misc.tree.tag.foreachloop=\
for
compiler.misc.tree.tag.whileloop=\
while
compiler.misc.tree.tag.doloop=\
do
compiler.misc.tree.tag.switch=\
switch
##### #####
compiler.misc.no.args=\ compiler.misc.no.args=\

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -187,6 +187,10 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
*/ */
BREAK, BREAK,
/** Yield statements, of type Yield.
*/
YIELD,
/** Continue statements, of type Continue. /** Continue statements, of type Continue.
*/ */
CONTINUE, CONTINUE,
@ -1551,10 +1555,10 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
* A break from a loop or switch. * A break from a loop or switch.
*/ */
public static class JCBreak extends JCStatement implements BreakTree { public static class JCBreak extends JCStatement implements BreakTree {
public JCExpression value; public Name label;
public JCTree target; public JCTree target;
protected JCBreak(JCExpression value, JCTree target) { protected JCBreak(Name label, JCTree target) {
this.value = value; this.label = label;
this.target = target; this.target = target;
} }
@Override @Override
@ -1567,11 +1571,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public Kind getKind() { return Kind.BREAK; } public Kind getKind() { return Kind.BREAK; }
@DefinedBy(Api.COMPILER_TREE) @DefinedBy(Api.COMPILER_TREE)
public Name getLabel() { public Name getLabel() {
return value != null && value.getKind() == Kind.IDENTIFIER ? ((JCIdent) value).getName() : null; return label;
} }
@DefinedBy(Api.COMPILER_TREE)
@SuppressWarnings("removal")
public JCExpression getValue() { return value; }
@Override @DefinedBy(Api.COMPILER_TREE) @Override @DefinedBy(Api.COMPILER_TREE)
public <R,D> R accept(TreeVisitor<R,D> v, D d) { public <R,D> R accept(TreeVisitor<R,D> v, D d) {
return v.visitBreak(this, d); return v.visitBreak(this, d);
@ -1582,6 +1583,33 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
} }
} }
/**
* A break-with from a switch expression.
*/
@SuppressWarnings("removal")
public static class JCYield extends JCStatement implements YieldTree {
public JCExpression value;
public JCTree target;
protected JCYield(JCExpression value, JCTree target) {
this.value = value;
this.target = target;
}
@Override
public void accept(Visitor v) { v.visitYield(this); }
@DefinedBy(Api.COMPILER_TREE)
public Kind getKind() { return Kind.YIELD; }
@DefinedBy(Api.COMPILER_TREE)
public JCExpression getValue() { return value; }
@Override @DefinedBy(Api.COMPILER_TREE)
public <R,D> R accept(TreeVisitor<R,D> v, D d) {
return v.visitYield(this, d);
}
@Override
public Tag getTag() {
return YIELD;
}
}
/** /**
* A continue of a loop. * A continue of a loop.
*/ */
@ -3091,7 +3119,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
JCExpression elsepart); JCExpression elsepart);
JCIf If(JCExpression cond, JCStatement thenpart, JCStatement elsepart); JCIf If(JCExpression cond, JCStatement thenpart, JCStatement elsepart);
JCExpressionStatement Exec(JCExpression expr); JCExpressionStatement Exec(JCExpression expr);
JCBreak Break(JCExpression value); JCBreak Break(Name label);
JCYield Yield(JCExpression value);
JCContinue Continue(Name label); JCContinue Continue(Name label);
JCReturn Return(JCExpression expr); JCReturn Return(JCExpression expr);
JCThrow Throw(JCExpression expr); JCThrow Throw(JCExpression expr);
@ -3162,6 +3191,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public void visitIf(JCIf that) { visitTree(that); } public void visitIf(JCIf that) { visitTree(that); }
public void visitExec(JCExpressionStatement that) { visitTree(that); } public void visitExec(JCExpressionStatement that) { visitTree(that); }
public void visitBreak(JCBreak that) { visitTree(that); } public void visitBreak(JCBreak that) { visitTree(that); }
public void visitYield(JCYield that) { visitTree(that); }
public void visitContinue(JCContinue that) { visitTree(that); } public void visitContinue(JCContinue that) { visitTree(that); }
public void visitReturn(JCReturn that) { visitTree(that); } public void visitReturn(JCReturn that) { visitTree(that); }
public void visitThrow(JCThrow that) { visitTree(that); } public void visitThrow(JCThrow that) { visitTree(that); }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -982,7 +982,18 @@ public class Pretty extends JCTree.Visitor {
public void visitBreak(JCBreak tree) { public void visitBreak(JCBreak tree) {
try { try {
print("break"); print("break");
if (tree.value != null) print(" " + tree.value); if (tree.label != null) print(" " + tree.label);
print(";");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitYield(JCYield tree) {
try {
print("yield");
print(" ");
printExpr(tree.value);
print(";"); print(";");
} catch (IOException e) { } catch (IOException e) {
throw new UncheckedIOException(e); throw new UncheckedIOException(e);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -140,8 +140,15 @@ public class TreeCopier<P> implements TreeVisitor<JCTree,P> {
@DefinedBy(Api.COMPILER_TREE) @DefinedBy(Api.COMPILER_TREE)
public JCTree visitBreak(BreakTree node, P p) { public JCTree visitBreak(BreakTree node, P p) {
JCBreak t = (JCBreak) node; JCBreak t = (JCBreak) node;
return M.at(t.pos).Break(t.label);
}
@DefinedBy(Api.COMPILER_TREE)
@SuppressWarnings("removal")
public JCTree visitYield(YieldTree node, P p) {
JCYield t = (JCYield) node;
JCExpression value = copy(t.value, p); JCExpression value = copy(t.value, p);
return M.at(t.pos).Break(value); return M.at(t.pos).Yield(value);
} }
@DefinedBy(Api.COMPILER_TREE) @DefinedBy(Api.COMPILER_TREE)

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -333,12 +333,18 @@ public class TreeMaker implements JCTree.Factory {
return tree; return tree;
} }
public JCBreak Break(JCExpression label) { public JCBreak Break(Name label) {
JCBreak tree = new JCBreak(label, null); JCBreak tree = new JCBreak(label, null);
tree.pos = pos; tree.pos = pos;
return tree; return tree;
} }
public JCYield Yield(JCExpression value) {
JCYield tree = new JCYield(value, null);
tree.pos = pos;
return tree;
}
public JCContinue Continue(Name label) { public JCContinue Continue(Name label) {
JCContinue tree = new JCContinue(label, null); JCContinue tree = new JCContinue(label, null);
tree.pos = pos; tree.pos = pos;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -219,6 +219,9 @@ public class TreeScanner extends Visitor {
} }
public void visitBreak(JCBreak tree) { public void visitBreak(JCBreak tree) {
}
public void visitYield(JCYield tree) {
scan(tree.value); scan(tree.value);
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -258,8 +258,11 @@ public class TreeTranslator extends JCTree.Visitor {
} }
public void visitBreak(JCBreak tree) { public void visitBreak(JCBreak tree) {
if (tree.isValueBreak()) result = tree;
tree.value = translate(tree.value); }
public void visitYield(JCYield tree) {
tree.value = translate(tree.value);
result = tree; result = tree;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -554,6 +554,13 @@ public class Log extends AbstractLog {
} }
} }
/**Is an error reported at the given pos (inside the current source)?*/
public boolean hasErrorOn(DiagnosticPosition pos) {
JavaFileObject file = source != null ? source.fileObject : null;
return file != null && recorded.contains(new Pair<>(file, pos.getPreferredPosition()));
}
/** Prompt user after an error. /** Prompt user after an error.
*/ */
public void prompt() { public void prompt() {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -70,6 +70,7 @@ public class Names {
public final Name uses; public final Name uses;
public final Name open; public final Name open;
public final Name with; public final Name with;
public final Name yield;
// field and method names // field and method names
public final Name _name; public final Name _name;
@ -219,6 +220,7 @@ public class Names {
uses = fromString("uses"); uses = fromString("uses");
open = fromString("open"); open = fromString("open");
with = fromString("with"); with = fromString("with");
yield = fromString("yield");
// field and method names // field and method names
_name = fromString("name"); _name = fromString("name");

View file

@ -21,7 +21,7 @@
* questions. * questions.
*/ */
// key: compiler.err.var.not.allowed.array // key: compiler.err.restricted.type.not.allowed.array
import java.util.function.*; import java.util.function.*;

View file

@ -1,65 +0,0 @@
/*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// key: compiler.err.break.expr.not.immediate
// key: compiler.misc.tree.tag.doloop
// key: compiler.misc.tree.tag.foreachloop
// key: compiler.misc.tree.tag.forloop
// key: compiler.misc.tree.tag.switch
// key: compiler.misc.tree.tag.whileloop
// key: compiler.note.note
// key: compiler.err.error
// key: compiler.misc.count.error.plural
// key: compiler.note.preview.filename
// key: compiler.note.preview.recompile
// key: compiler.note.note
// options: --enable-preview -source ${jdk.version}
// run: backdoor
class BreakExprNotImmediate {
int t(int i) {
return switch (i) {
case 0:
for (; ;) {
break 1 + 1;
}
case 1:
for (String s : new String[0]) {
break 1 + 1;
}
case 2:
while (true) {
break 1 + 1;
}
case 3:
do {
break 1 + 1;
} while (true);
case 4:
switch (i) {
default: break 1 + 1;
}
break 0;
};
}
}

View file

@ -21,7 +21,7 @@
* questions. * questions.
*/ */
// key: compiler.warn.var.not.allowed // key: compiler.warn.restricted.type.not.allowed
// options: --release 9 // options: --release 9
class var { } class var { }

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// key: compiler.warn.illegal.ref.to.restricted.type
// key: compiler.warn.restricted.type.not.allowed.preview
class IllegalRefToVarType {
yield list() { return null; }
public class yield {}
}

View file

@ -21,7 +21,7 @@
* questions. * questions.
*/ */
// key: compiler.err.illegal.ref.to.var.type // key: compiler.err.illegal.ref.to.restricted.type
import java.util.List; import java.util.List;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -21,16 +21,14 @@
* questions. * questions.
*/ */
// key: compiler.err.break.ambiguous.target // key: compiler.err.invalid.yield
// key: compiler.note.preview.filename // options: --enable-preview --source 13
// key: compiler.note.preview.recompile
// options: --enable-preview -source ${jdk.version}
class BreakAmbiguousTarget { class BreakComplexValueNoSwitchExpressions {
void m(int i, int j) { void t() {
j: print(switch (i) { while (true) {
default: break j; yield(1, 2);
}); }
} }
void print(int i) { } private void yield(int i, int j) {}
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -21,12 +21,14 @@
* questions. * questions.
*/ */
// key: compiler.err.break.complex.value.no.switch.expression // key: compiler.warn.invalid.yield
// options: --source 13
class BreakComplexValueNoSwitchExpressions { class BreakComplexValueNoSwitchExpressions {
void t() { void t() {
while (true) { while (true) {
break 1 + 1; yield(1, 2);
} }
} }
private void yield(int i, int j) {}
} }

View file

@ -21,15 +21,13 @@
* questions. * questions.
*/ */
// key: compiler.err.break.missing.value // key: compiler.err.no.switch.expression
// key: compiler.note.preview.filename // options: --enable-preview --source 13
// key: compiler.note.preview.recompile
// options: --enable-preview -source ${jdk.version}
class BreakMissingValue { class BreakComplexValueNoSwitchExpressions {
int t(int i) { void t() {
return switch (i) { while (true) {
default: break; yield 1 + 1;
}; }
} }
} }

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// key: compiler.err.no.switch.expression.qualify
// options: --enable-preview --source 13
class BreakComplexValueNoSwitchExpressions {
void t() {
while (true) {
yield(1 + 1);
}
}
private void yield(int i) {}
}

View file

@ -0,0 +1,26 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// key: compiler.warn.restricted.type.not.allowed.preview
class yield { }

View file

@ -28,7 +28,7 @@
class SwitchExpressions { class SwitchExpressions {
int m(int i) { int m(int i) {
return switch (i) { return switch (i) {
default: break -1; default: yield -1;
}; };
} }
} }

View file

@ -21,6 +21,6 @@
* questions. * questions.
*/ */
// key: compiler.err.var.not.allowed // key: compiler.err.restricted.type.not.allowed
class var { } class var { }

View file

@ -21,7 +21,7 @@
* questions. * questions.
*/ */
// key: compiler.err.var.not.allowed.array // key: compiler.err.restricted.type.not.allowed.array
class VarNotAllowedArray { class VarNotAllowedArray {
void test(String[] s) { void test(String[] s) {

View file

@ -21,7 +21,7 @@
* questions. * questions.
*/ */
// key: compiler.err.var.not.allowed.compound // key: compiler.err.restricted.type.not.allowed.compound
class VarNotAllowedCompound { class VarNotAllowedCompound {
void test() { void test() {

View file

@ -21,7 +21,7 @@
* questions. * questions.
*/ */
// key: compiler.err.var.not.allowed.here // key: compiler.err.restricted.type.not.allowed.here
class VarNotAllowedField { class VarNotAllowedField {
var s = ""; var s = "";

View file

@ -48,11 +48,12 @@ public class ExpSwitchNestingTest extends JavacTemplateTestBase {
private static final String INT_ESWITCH_DEFAULT = "int res = switch (x) { default -> { # } };"; private static final String INT_ESWITCH_DEFAULT = "int res = switch (x) { default -> { # } };";
private static final String IF = "if (cond) { # } else throw new RuntimeException();"; private static final String IF = "if (cond) { # } else throw new RuntimeException();";
private static final String BLOCK = "{ # }"; private static final String BLOCK = "{ # }";
private static final String BREAK_Z = "break 0;"; private static final String YIELD_Z = "yield 0;";
private static final String BREAK_S = "break \"hello world\";"; private static final String YIELD_S = "yield \"hello world\";";
private static final String BREAK_INT_FN = "break () -> 0 ;"; private static final String YIELD_INT_FN = "yield () -> 0 ;";
private static final String BREAK_N = "break;"; private static final String BREAK_N = "break;";
private static final String BREAK_L = "break label;"; private static final String BREAK_L = "break label;";
private static final String YIELD_L = "yield label;";
private static final String RETURN_Z = "return 0;"; private static final String RETURN_Z = "return 0;";
private static final String RETURN_N = "return;"; private static final String RETURN_N = "return;";
private static final String RETURN_S = "return \"Hello\";"; private static final String RETURN_S = "return \"Hello\";";
@ -136,11 +137,11 @@ public class ExpSwitchNestingTest extends JavacTemplateTestBase {
assertOK(RUNNABLE, NOTHING); assertOK(RUNNABLE, NOTHING);
assertOK(INT_FN, RETURN_Z); assertOK(INT_FN, RETURN_Z);
assertFail("compiler.err.break.outside.switch.loop", RUNNABLE, BREAK_N); assertFail("compiler.err.break.outside.switch.loop", RUNNABLE, BREAK_N);
assertFail("compiler.err.break.complex.value.no.switch.expression", RUNNABLE, BREAK_Z); assertFail("compiler.err.no.switch.expression", RUNNABLE, YIELD_Z);
assertFail("compiler.err.break.complex.value.no.switch.expression", RUNNABLE, BREAK_S); assertFail("compiler.err.no.switch.expression", RUNNABLE, YIELD_S);
assertFail("compiler.err.break.outside.switch.loop", INT_FN, BREAK_N); assertFail("compiler.err.break.outside.switch.loop", INT_FN, BREAK_N);
assertFail("compiler.err.break.complex.value.no.switch.expression", INT_FN, BREAK_Z); assertFail("compiler.err.no.switch.expression", INT_FN, YIELD_Z);
assertFail("compiler.err.break.complex.value.no.switch.expression", INT_FN, BREAK_S); assertFail("compiler.err.no.switch.expression", INT_FN, YIELD_S);
assertFail("compiler.err.cont.outside.loop", RUNNABLE, CONTINUE_N); assertFail("compiler.err.cont.outside.loop", RUNNABLE, CONTINUE_N);
assertFail("compiler.err.undef.label", RUNNABLE, BREAK_L); assertFail("compiler.err.undef.label", RUNNABLE, BREAK_L);
assertFail("compiler.err.undef.label", RUNNABLE, CONTINUE_L); assertFail("compiler.err.undef.label", RUNNABLE, CONTINUE_L);
@ -155,92 +156,94 @@ public class ExpSwitchNestingTest extends JavacTemplateTestBase {
public void testEswitch() { public void testEswitch() {
//Int-valued switch expressions //Int-valued switch expressions
assertOK(ESWITCH_Z, BREAK_Z); assertOK(ESWITCH_Z, YIELD_Z);
assertOK(LABEL, BLOCK, ESWITCH_Z, BREAK_Z); assertOK(LABEL, BLOCK, ESWITCH_Z, YIELD_Z);
assertFail("compiler.err.break.missing.value", ESWITCH_Z, BREAK_N); assertFail("compiler.err.break.outside.switch.expression", ESWITCH_Z, BREAK_N);
assertFail("compiler.err.prob.found.req", ESWITCH_Z, BREAK_S); assertFail("compiler.err.prob.found.req", ESWITCH_Z, YIELD_S);
assertFail("compiler.err.cant.resolve.location", ESWITCH_Z, BREAK_L); assertFail("compiler.err.undef.label", ESWITCH_Z, BREAK_L);
assertFail("compiler.err.break.outside.switch.expression", LABEL, BLOCK, ESWITCH_Z, BREAK_L); assertFail("compiler.err.break.outside.switch.expression", LABEL, BLOCK, ESWITCH_Z, BREAK_L);
assertFail("compiler.err.undef.label", ESWITCH_Z, CONTINUE_L); assertFail("compiler.err.undef.label", ESWITCH_Z, CONTINUE_L);
assertFail("compiler.err.cont.outside.loop", ESWITCH_Z, CONTINUE_N); assertFail("compiler.err.continue.outside.switch.expression", ESWITCH_Z, CONTINUE_N);
assertFail("compiler.err.return.outside.switch.expression", ESWITCH_Z, RETURN_N); assertFail("compiler.err.return.outside.switch.expression", ESWITCH_Z, RETURN_N);
assertFail("compiler.err.return.outside.switch.expression", ESWITCH_Z, RETURN_Z); assertFail("compiler.err.return.outside.switch.expression", ESWITCH_Z, RETURN_Z);
assertOK(INT_ESWITCH_DEFAULT, BREAK_Z); assertOK(INT_ESWITCH_DEFAULT, YIELD_Z);
assertFail("compiler.err.break.missing.value", INT_ESWITCH_DEFAULT, BREAK_N); assertFail("compiler.err.break.outside.switch.expression", INT_ESWITCH_DEFAULT, BREAK_N);
assertFail("compiler.err.prob.found.req", INT_ESWITCH_DEFAULT, BREAK_S); assertFail("compiler.err.prob.found.req", INT_ESWITCH_DEFAULT, YIELD_S);
assertFail("compiler.err.cant.resolve.location", INT_ESWITCH_DEFAULT, BREAK_L); assertFail("compiler.err.undef.label", INT_ESWITCH_DEFAULT, BREAK_L);
// String-valued switch expressions // String-valued switch expressions
assertOK(ESWITCH_S, BREAK_S); assertOK(ESWITCH_S, YIELD_S);
assertOK(LABEL, BLOCK, ESWITCH_S, BREAK_S); assertOK(LABEL, BLOCK, ESWITCH_S, YIELD_S);
assertFail("compiler.err.break.missing.value", ESWITCH_S, BREAK_N); assertFail("compiler.err.break.outside.switch.expression", ESWITCH_S, BREAK_N);
assertFail("compiler.err.prob.found.req", ESWITCH_S, BREAK_Z); assertFail("compiler.err.prob.found.req", ESWITCH_S, YIELD_Z);
assertFail("compiler.err.cant.resolve.location", ESWITCH_S, BREAK_L); assertFail("compiler.err.undef.label", ESWITCH_S, BREAK_L);
assertFail("compiler.err.break.outside.switch.expression", LABEL, BLOCK, ESWITCH_S, BREAK_L); assertFail("compiler.err.break.outside.switch.expression", LABEL, BLOCK, ESWITCH_S, BREAK_L);
assertFail("compiler.err.undef.label", ESWITCH_S, CONTINUE_L); assertFail("compiler.err.undef.label", ESWITCH_S, CONTINUE_L);
assertFail("compiler.err.cont.outside.loop", ESWITCH_S, CONTINUE_N); assertFail("compiler.err.continue.outside.switch.expression", ESWITCH_S, CONTINUE_N);
assertFail("compiler.err.return.outside.switch.expression", ESWITCH_S, RETURN_N); assertFail("compiler.err.return.outside.switch.expression", ESWITCH_S, RETURN_N);
assertFail("compiler.err.return.outside.switch.expression", ESWITCH_S, RETURN_S); assertFail("compiler.err.return.outside.switch.expression", ESWITCH_S, RETURN_S);
// Function-valued switch expression // Function-valued switch expression
assertOK(INT_FN_ESWITCH, BREAK_INT_FN); assertOK(INT_FN_ESWITCH, YIELD_INT_FN);
assertFail("compiler.err.break.missing.value", INT_FN_ESWITCH, BREAK_N); assertFail("compiler.err.break.outside.switch.expression", INT_FN_ESWITCH, BREAK_N);
assertFail("compiler.err.prob.found.req", INT_FN_ESWITCH, BREAK_Z); assertFail("compiler.err.prob.found.req", INT_FN_ESWITCH, YIELD_Z);
assertFail("compiler.err.prob.found.req", INT_FN_ESWITCH, BREAK_S); assertFail("compiler.err.prob.found.req", INT_FN_ESWITCH, YIELD_S);
assertFail("compiler.err.cant.resolve.location", INT_FN_ESWITCH, BREAK_L); assertFail("compiler.err.undef.label", INT_FN_ESWITCH, BREAK_L);
assertFail("compiler.err.break.outside.switch.expression", LABEL, BLOCK, INT_FN_ESWITCH, BREAK_L); assertFail("compiler.err.break.outside.switch.expression", LABEL, BLOCK, INT_FN_ESWITCH, BREAK_L);
assertFail("compiler.err.undef.label", INT_FN_ESWITCH, CONTINUE_L); assertFail("compiler.err.undef.label", INT_FN_ESWITCH, CONTINUE_L);
assertFail("compiler.err.cont.outside.loop", INT_FN_ESWITCH, CONTINUE_N); assertFail("compiler.err.continue.outside.switch.expression", INT_FN_ESWITCH, CONTINUE_N);
assertFail("compiler.err.return.outside.switch.expression", INT_FN_ESWITCH, RETURN_N); assertFail("compiler.err.return.outside.switch.expression", INT_FN_ESWITCH, RETURN_N);
assertFail("compiler.err.return.outside.switch.expression", INT_FN_ESWITCH, RETURN_S); assertFail("compiler.err.return.outside.switch.expression", INT_FN_ESWITCH, RETURN_S);
} }
public void testNestedInExpSwitch() { public void testNestedInExpSwitch() {
assertOK(ESWITCH_Z, IF, BREAK_Z); assertOK(ESWITCH_Z, IF, YIELD_Z);
assertOK(ESWITCH_Z, BLOCK, BREAK_Z); assertOK(ESWITCH_Z, BLOCK, YIELD_Z);
// //
assertOK(ESWITCH_Z, IF, IF, BREAK_Z); assertOK(ESWITCH_Z, IF, IF, YIELD_Z);
assertOK(ESWITCH_Z, IF, BLOCK, BREAK_Z); assertOK(ESWITCH_Z, IF, BLOCK, YIELD_Z);
assertOK(ESWITCH_Z, BLOCK, IF, BREAK_Z); assertOK(ESWITCH_Z, BLOCK, IF, YIELD_Z);
assertOK(ESWITCH_Z, BLOCK, BLOCK, BREAK_Z); assertOK(ESWITCH_Z, BLOCK, BLOCK, YIELD_Z);
// //
assertOK(ESWITCH_Z, IF, IF, IF, BREAK_Z); assertOK(ESWITCH_Z, IF, IF, IF, YIELD_Z);
assertOK(ESWITCH_Z, IF, IF, BLOCK, BREAK_Z); assertOK(ESWITCH_Z, IF, IF, BLOCK, YIELD_Z);
assertOK(ESWITCH_Z, IF, BLOCK, IF, BREAK_Z); assertOK(ESWITCH_Z, IF, BLOCK, IF, YIELD_Z);
assertOK(ESWITCH_Z, IF, BLOCK, BLOCK, BREAK_Z); assertOK(ESWITCH_Z, IF, BLOCK, BLOCK, YIELD_Z);
assertOK(ESWITCH_Z, BLOCK, IF, IF, BREAK_Z); assertOK(ESWITCH_Z, BLOCK, IF, IF, YIELD_Z);
assertOK(ESWITCH_Z, BLOCK, IF, BLOCK, BREAK_Z); assertOK(ESWITCH_Z, BLOCK, IF, BLOCK, YIELD_Z);
assertOK(ESWITCH_Z, BLOCK, BLOCK, IF, BREAK_Z); assertOK(ESWITCH_Z, BLOCK, BLOCK, IF, YIELD_Z);
assertOK(ESWITCH_Z, BLOCK, BLOCK, BLOCK, BREAK_Z); assertOK(ESWITCH_Z, BLOCK, BLOCK, BLOCK, YIELD_Z);
// //
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, SSWITCH, BREAK_Z); assertOK(ESWITCH_Z, YIELD_Z, SSWITCH, YIELD_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, FOR, BREAK_Z); assertOK(ESWITCH_Z, YIELD_Z, FOR, YIELD_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, WHILE, BREAK_Z); assertOK(ESWITCH_Z, YIELD_Z, WHILE, YIELD_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, DO, BREAK_Z); assertOK(ESWITCH_Z, YIELD_Z, DO, YIELD_Z);
assertFail("compiler.err.break.complex.value.no.switch.expression", ESWITCH_Z, INT_FN, BREAK_Z); assertFail("compiler.err.no.switch.expression", ESWITCH_Z, INT_FN, YIELD_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, SSWITCH, IF, BREAK_Z); assertOK(ESWITCH_Z, YIELD_Z, SSWITCH, IF, YIELD_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, FOR, IF, BREAK_Z); assertOK(ESWITCH_Z, YIELD_Z, FOR, IF, YIELD_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, WHILE, IF, BREAK_Z); assertOK(ESWITCH_Z, YIELD_Z, WHILE, IF, YIELD_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, DO, IF, BREAK_Z); assertOK(ESWITCH_Z, YIELD_Z, DO, IF, YIELD_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, BLOCK, SSWITCH, IF, BREAK_Z); assertOK(ESWITCH_Z, YIELD_Z, BLOCK, SSWITCH, IF, YIELD_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, BLOCK, FOR, IF, BREAK_Z); assertOK(ESWITCH_Z, YIELD_Z, BLOCK, FOR, IF, YIELD_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, BLOCK, WHILE, IF, BREAK_Z); assertOK(ESWITCH_Z, YIELD_Z, BLOCK, WHILE, IF, YIELD_Z);
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, BLOCK, DO, IF, BREAK_Z); assertOK(ESWITCH_Z, YIELD_Z, BLOCK, DO, IF, YIELD_Z);
} }
public void testBreakExpressionLabelDisambiguation() { public void testBreakExpressionLabelDisambiguation() {
assertOK(DEF_LABEL_VAR, ESWITCH_Z, BREAK_L); assertOK(DEF_LABEL_VAR, ESWITCH_Z, YIELD_L);
assertFail("compiler.err.break.ambiguous.target", LABEL, FOR, BLOCK, DEF_LABEL_VAR, ESWITCH_Z, BREAK_L); assertFail("compiler.err.undef.label", DEF_LABEL_VAR, ESWITCH_Z, BREAK_L);
assertFail("compiler.err.break.ambiguous.target", DEF_LABEL_VAR, ESWITCH_Z, LABEL, FOR, BREAK_L); //label break assertFail("compiler.err.break.outside.switch.expression", LABEL, FOR, BLOCK, DEF_LABEL_VAR, ESWITCH_Z, BREAK_L);
assertFail("compiler.err.break.ambiguous.target", DEF_LABEL_VAR, LABEL, BLOCK, ESWITCH_Z, BREAK_L); //expression break assertOK(DEF_LABEL_VAR, ESWITCH_Z, YIELD_Z, LABEL, FOR, BREAK_L); //label break
assertFail("compiler.err.break.outside.switch.expression", DEF_LABEL_VAR, LABEL, BLOCK, ESWITCH_Z, BREAK_L);
assertOK(DEF_LABEL_VAR, LABEL, BLOCK, ESWITCH_Z, YIELD_L); //expression break
// //
} }
public void testFunReturningSwitchExp() { public void testFunReturningSwitchExp() {
assertOK(INT_FN_ESWITCH, BREAK_INT_FN); assertOK(INT_FN_ESWITCH, YIELD_INT_FN);
} }
public void testContinueLoops() { public void testContinueLoops() {

View file

@ -160,6 +160,9 @@ public class Deduplication {
group((Consumer<Integer>) x -> Deduplication.this.f()); group((Consumer<Integer>) x -> Deduplication.this.f());
} }
} }
group((Function<Integer, Integer>) x -> switch (x) { default: yield x; },
(Function<Integer, Integer>) x -> switch (x) { default: yield x; });
} }
void f() {} void f() {}

View file

@ -84,6 +84,7 @@ public class DeduplicationTest {
Listener diagnosticListener = new Listener(); Listener diagnosticListener = new Listener();
Path testSrc = Paths.get(System.getProperty("test.src")); Path testSrc = Paths.get(System.getProperty("test.src"));
Path file = testSrc.resolve("Deduplication.java"); Path file = testSrc.resolve("Deduplication.java");
String sourceVersion = Integer.toString(Runtime.version().feature());
JavacTask task = JavacTask task =
javacTool.getTask( javacTool.getTask(
null, null,
@ -93,7 +94,8 @@ public class DeduplicationTest {
"-d", "-d",
".", ".",
"-XDdebug.dumpLambdaToMethodDeduplication", "-XDdebug.dumpLambdaToMethodDeduplication",
"-XDdebug.dumpLambdaToMethodStats"), "-XDdebug.dumpLambdaToMethodStats",
"--enable-preview", "-source", sourceVersion),
null, null,
fileManager.getJavaFileObjects(file)); fileManager.getJavaFileObjects(file));
Map<JCLambda, JCLambda> dedupedLambdas = new LinkedHashMap<>(); Map<JCLambda, JCLambda> dedupedLambdas = new LinkedHashMap<>();
@ -192,6 +194,9 @@ public class DeduplicationTest {
(JCLambda) d.getDiagnosticPosition().getTree(), (JCLambda) d.getDiagnosticPosition().getTree(),
(MethodSymbol) d.getArgs()[0]); (MethodSymbol) d.getArgs()[0]);
break; break;
case "compiler.note.preview.filename":
case "compiler.note.preview.recompile":
break; //ignore
default: default:
unexpected.add(diagnostic); unexpected.add(diagnostic);
} }

View file

@ -782,6 +782,11 @@ public class DPrinter {
@Override @Override
public void visitBreak(JCBreak tree) { public void visitBreak(JCBreak tree) {
printName("label", tree.label);
}
@Override
public void visitYield(JCYield tree) {
printTree("value", tree.value); printTree("value", tree.value);
} }

View file

@ -1,24 +1,24 @@
ParserTest.java:14:18: compiler.err.var.not.allowed ParserTest.java:14:18: compiler.err.restricted.type.not.allowed: var, 10
ParserTest.java:16:22: compiler.err.var.not.allowed ParserTest.java:16:22: compiler.err.restricted.type.not.allowed: var, 10
ParserTest.java:20:19: compiler.err.var.not.allowed ParserTest.java:20:19: compiler.err.restricted.type.not.allowed: var, 10
ParserTest.java:24:14: compiler.err.var.not.allowed ParserTest.java:24:14: compiler.err.restricted.type.not.allowed: var, 10
ParserTest.java:28:20: compiler.err.var.not.allowed ParserTest.java:28:20: compiler.err.restricted.type.not.allowed: var, 10
ParserTest.java:36:27: compiler.err.var.not.allowed ParserTest.java:36:27: compiler.err.restricted.type.not.allowed: var, 10
ParserTest.java:38:5: compiler.err.var.not.allowed.here ParserTest.java:38:5: compiler.err.restricted.type.not.allowed.here: var
ParserTest.java:41:15: compiler.err.var.not.allowed.array ParserTest.java:41:15: compiler.err.restricted.type.not.allowed.array: var
ParserTest.java:42:13: compiler.err.var.not.allowed.array ParserTest.java:42:13: compiler.err.restricted.type.not.allowed.array: var
ParserTest.java:43:17: compiler.err.var.not.allowed.array ParserTest.java:43:17: compiler.err.restricted.type.not.allowed.array: var
ParserTest.java:44:13: compiler.err.var.not.allowed.array ParserTest.java:44:13: compiler.err.restricted.type.not.allowed.array: var
ParserTest.java:45:15: compiler.err.var.not.allowed.array ParserTest.java:45:15: compiler.err.restricted.type.not.allowed.array: var
ParserTest.java:46:13: compiler.err.var.not.allowed.array ParserTest.java:46:13: compiler.err.restricted.type.not.allowed.array: var
ParserTest.java:49:24: compiler.err.var.not.allowed.compound ParserTest.java:49:24: compiler.err.restricted.type.not.allowed.compound: var
ParserTest.java:54:5: compiler.err.var.not.allowed.here ParserTest.java:54:5: compiler.err.restricted.type.not.allowed.here: var
ParserTest.java:58:16: compiler.err.var.not.allowed.here ParserTest.java:58:16: compiler.err.restricted.type.not.allowed.here: var
ParserTest.java:59:14: compiler.err.var.not.allowed.here ParserTest.java:59:14: compiler.err.restricted.type.not.allowed.here: var
ParserTest.java:60:24: compiler.err.var.not.allowed.here ParserTest.java:60:24: compiler.err.restricted.type.not.allowed.here: var
ParserTest.java:61:22: compiler.err.var.not.allowed.here ParserTest.java:61:22: compiler.err.restricted.type.not.allowed.here: var
ParserTest.java:63:22: compiler.err.var.not.allowed.here ParserTest.java:63:22: compiler.err.restricted.type.not.allowed.here: var
ParserTest.java:64:18: compiler.err.var.not.allowed.here ParserTest.java:64:18: compiler.err.restricted.type.not.allowed.here: var
ParserTest.java:68:35: compiler.err.var.not.allowed.here ParserTest.java:68:35: compiler.err.restricted.type.not.allowed.here: var
ParserTest.java:69:22: compiler.err.var.not.allowed.here ParserTest.java:69:22: compiler.err.restricted.type.not.allowed.here: var
23 errors 23 errors

View file

@ -1,31 +1,31 @@
ParserTest.java:14:18: compiler.warn.var.not.allowed ParserTest.java:14:18: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:16:22: compiler.warn.var.not.allowed ParserTest.java:16:22: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:20:19: compiler.warn.var.not.allowed ParserTest.java:20:19: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:24:14: compiler.warn.var.not.allowed ParserTest.java:24:14: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:28:20: compiler.warn.var.not.allowed ParserTest.java:28:20: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:36:27: compiler.warn.var.not.allowed ParserTest.java:36:27: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:38:5: compiler.warn.var.not.allowed ParserTest.java:38:5: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:41:15: compiler.warn.var.not.allowed ParserTest.java:41:15: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:42:13: compiler.warn.var.not.allowed ParserTest.java:42:13: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:43:17: compiler.warn.var.not.allowed ParserTest.java:43:17: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:44:13: compiler.warn.var.not.allowed ParserTest.java:44:13: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:45:15: compiler.warn.var.not.allowed ParserTest.java:45:15: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:46:13: compiler.warn.var.not.allowed ParserTest.java:46:13: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:47:23: compiler.warn.var.not.allowed ParserTest.java:47:23: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:48:13: compiler.warn.var.not.allowed ParserTest.java:48:13: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:49:13: compiler.warn.var.not.allowed ParserTest.java:49:13: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:50:23: compiler.warn.var.not.allowed ParserTest.java:50:23: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:51:23: compiler.warn.var.not.allowed ParserTest.java:51:23: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:54:5: compiler.warn.var.not.allowed ParserTest.java:54:5: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:58:16: compiler.warn.var.not.allowed ParserTest.java:58:16: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:59:14: compiler.warn.var.not.allowed ParserTest.java:59:14: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:60:24: compiler.warn.var.not.allowed ParserTest.java:60:24: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:61:22: compiler.warn.var.not.allowed ParserTest.java:61:22: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:63:22: compiler.warn.var.not.allowed ParserTest.java:63:22: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:63:40: compiler.warn.var.not.allowed ParserTest.java:63:40: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:64:18: compiler.warn.var.not.allowed ParserTest.java:64:18: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:68:35: compiler.warn.var.not.allowed ParserTest.java:68:35: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:69:22: compiler.warn.var.not.allowed ParserTest.java:69:22: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:73:24: compiler.warn.var.not.allowed ParserTest.java:73:24: compiler.warn.restricted.type.not.allowed: var, 10
ParserTest.java:74:18: compiler.warn.var.not.allowed ParserTest.java:74:18: compiler.warn.restricted.type.not.allowed: var, 10
30 warnings 30 warnings

View file

@ -1,3 +1,3 @@
BadTypeReference.java:14:9: compiler.err.illegal.ref.to.var.type BadTypeReference.java:14:9: compiler.err.illegal.ref.to.restricted.type: var
BadTypeReference.java:15:21: compiler.err.illegal.ref.to.var.type BadTypeReference.java:15:21: compiler.err.illegal.ref.to.restricted.type: var
2 errors 2 errors

View file

@ -1083,12 +1083,12 @@ public class JavacParserTest extends TestCase {
" }" + " }" +
" int j = switch (i) {" + " int j = switch (i) {" +
" case 0 -> i + 1;" + " case 0 -> i + 1;" +
" case 1 -> { break i + 1; }" + " case 1 -> { yield i + 1; }" +
" default -> throw new RuntimeException();" + " default -> throw new RuntimeException();" +
" };" + " };" +
" int k = switch (i) {" + " int k = switch (i) {" +
" case 0: break i + 1;" + " case 0: yield i + 1;" +
" case 1: { break i + 1; }" + " case 1: { yield i + 1; }" +
" default: throw new RuntimeException();" + " default: throw new RuntimeException();" +
" };" + " };" +
" }" + " }" +
@ -1120,7 +1120,7 @@ public class JavacParserTest extends TestCase {
List<String> expectedSpans = List.of( List<String> expectedSpans = List.of(
"i++;", "{ i++; }", "throw new RuntimeException();", "if (true) ;", "i++;", "i++;", "{ i++; }", "throw new RuntimeException();", "if (true) ;", "i++;",
"<null>", "<null>", "<null>", "<null>", "<null>", "<null>", "<null>", "<null>", "<null>", "<null>",
"i + 1"/*TODO semicolon?*/, "{ break i + 1; }", "throw new RuntimeException();", "i + 1"/*TODO semicolon?*/, "{ yield i + 1; }", "throw new RuntimeException();",
"<null>", "<null>", "<null>"); "<null>", "<null>", "<null>");
assertEquals("the error spans are not correct; actual:" + spans, expectedSpans, spans); assertEquals("the error spans are not correct; actual:" + spans, expectedSpans, spans);
String toString = normalize(cut.toString()); String toString = normalize(cut.toString());
@ -1162,19 +1162,19 @@ public class JavacParserTest extends TestCase {
" \n" + " \n" +
" }\n" + " }\n" +
" int j = switch (i) {\n" + " int j = switch (i) {\n" +
" case 0 -> break i + 1;\n" + " case 0 -> yield i + 1;\n" +
" case 1 -> {\n" + " case 1 -> {\n" +
" break i + 1;\n" + " yield i + 1;\n" +
" }\n" + " }\n" +
" default -> throw new RuntimeException();\n" + " default -> throw new RuntimeException();\n" +
" };\n" + " };\n" +
" int k = switch (i) {\n" + " int k = switch (i) {\n" +
" case 0:\n" + " case 0:\n" +
" break i + 1;\n" + " yield i + 1;\n" +
" \n" + " \n" +
" case 1:\n" + " case 1:\n" +
" {\n" + " {\n" +
" break i + 1;\n" + " yield i + 1;\n" +
" }\n" + " }\n" +
" \n" + " \n" +
" default:\n" + " default:\n" +

View file

@ -54,7 +54,7 @@ public class BreakTest {
" int t2(Integer i) {" + " int t2(Integer i) {" +
" return switch (i) {" + " return switch (i) {" +
" case null: break LABEL;" + " case null: break LABEL;" +
" default: break 2;" + " default: yield 2;" +
" }" + " }" +
" }" + " }" +
"}"; "}";
@ -79,7 +79,7 @@ public class BreakTest {
} }
}.scan(ct.parse(), null); }.scan(ct.parse(), null);
List<String> expected = Arrays.asList("LABEL", null, "LABEL", null); List<String> expected = Arrays.asList("LABEL", null, "LABEL");
if (!expected.equals(labels)) { if (!expected.equals(labels)) {
throw new AssertionError("Unexpected labels found: " + labels); throw new AssertionError("Unexpected labels found: " + labels);

View file

@ -37,8 +37,8 @@ public class DefiniteAssignment1 {
int x; int x;
boolean t1 = (b && switch(a) { boolean t1 = (b && switch(a) {
case 0: break (x = 1) == 1 || true; case 0: yield (x = 1) == 1 || true;
default: break false; default: yield false;
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
if (!t1) { if (!t1) {
@ -50,8 +50,8 @@ public class DefiniteAssignment1 {
int x; int x;
boolean t1 = (b && switch(a) { boolean t1 = (b && switch(a) {
case 0: break (x = 1) == 1 || isTrue(); case 0: yield (x = 1) == 1 || isTrue();
default: break false; default: yield false;
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
if (!t1) { if (!t1) {
@ -63,8 +63,8 @@ public class DefiniteAssignment1 {
int x; int x;
boolean t1a = (b && switch(a) { boolean t1a = (b && switch(a) {
case 0: break (x = 1) == 1; case 0: yield (x = 1) == 1;
default: break false; default: yield false;
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
if (!t1a) { if (!t1a) {
@ -76,8 +76,8 @@ public class DefiniteAssignment1 {
int x; int x;
boolean t1b = (switch(a) { boolean t1b = (switch(a) {
case 0: break (x = 1) == 1; case 0: yield (x = 1) == 1;
default: break false; default: yield false;
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
if (!t1b) { if (!t1b) {
@ -89,8 +89,8 @@ public class DefiniteAssignment1 {
int x; int x;
boolean t2 = !(b && switch(a) { boolean t2 = !(b && switch(a) {
case 0: break (x = 1) == 1 || true; case 0: yield (x = 1) == 1 || true;
default: break false; default: yield false;
}) || x == 1; }) || x == 1;
if (!t2) { if (!t2) {
@ -102,8 +102,8 @@ public class DefiniteAssignment1 {
int x; int x;
boolean t2 = !(b && switch(a) { boolean t2 = !(b && switch(a) {
case 0: break (x = 1) == 1 || isTrue(); case 0: yield (x = 1) == 1 || isTrue();
default: break false; default: yield false;
}) || x == 1; }) || x == 1;
if (!t2) { if (!t2) {
@ -115,8 +115,8 @@ public class DefiniteAssignment1 {
int x; int x;
boolean t3 = !(switch(a) { boolean t3 = !(switch(a) {
case 0: break (x = 1) == 1 || true; case 0: yield (x = 1) == 1 || true;
default: break false; default: yield false;
}) || x == 2; }) || x == 2;
if (t3) { if (t3) {
@ -128,8 +128,8 @@ public class DefiniteAssignment1 {
int x; int x;
boolean t3 = !(switch(a) { boolean t3 = !(switch(a) {
case 0: break (x = 1) == 1 || isTrue(); case 0: yield (x = 1) == 1 || isTrue();
default: break false; default: yield false;
}) || x == 2; }) || x == 2;
if (t3) { if (t3) {
@ -141,7 +141,7 @@ public class DefiniteAssignment1 {
int x; int x;
boolean t4 = (b && switch(a) { boolean t4 = (b && switch(a) {
case 0: break (x = 1) == 1 || true; case 0: yield (x = 1) == 1 || true;
default: throw new IllegalStateException(); default: throw new IllegalStateException();
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
@ -155,7 +155,7 @@ public class DefiniteAssignment1 {
int x; int x;
boolean t4 = (b && switch(a) { boolean t4 = (b && switch(a) {
case 0: break (x = 1) == 1 || isTrue(); case 0: yield (x = 1) == 1 || isTrue();
default: throw new IllegalStateException(); default: throw new IllegalStateException();
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
@ -170,8 +170,8 @@ public class DefiniteAssignment1 {
String s = "a"; String s = "a";
boolean t5 = (switch(s) { boolean t5 = (switch(s) {
case "a": break (x = 1) == 1 || true; case "a": yield (x = 1) == 1 || true;
default: break false; default: yield false;
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
if (!t5) { if (!t5) {
@ -185,8 +185,8 @@ public class DefiniteAssignment1 {
String s = "a"; String s = "a";
boolean t5 = (switch(s) { boolean t5 = (switch(s) {
case "a": break (x = 1) == 1 || isTrue(); case "a": yield (x = 1) == 1 || isTrue();
default: break false; default: yield false;
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
if (!t5) { if (!t5) {
@ -199,8 +199,8 @@ public class DefiniteAssignment1 {
E e = E.B; E e = E.B;
boolean t6 = (switch(e) { boolean t6 = (switch(e) {
case B: break (x = 1) == 1 || true; case B: yield (x = 1) == 1 || true;
default: break false; default: yield false;
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
if (!t6) { if (!t6) {
@ -213,8 +213,8 @@ public class DefiniteAssignment1 {
E e = E.B; E e = E.B;
boolean t6 = (switch(e) { boolean t6 = (switch(e) {
case B: break (x = 1) == 1 || isTrue(); case B: yield (x = 1) == 1 || isTrue();
default: break false; default: yield false;
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
if (!t6) { if (!t6) {
@ -251,9 +251,9 @@ public class DefiniteAssignment1 {
E e = E.B; E e = E.B;
boolean t8 = (switch(e) { boolean t8 = (switch(e) {
case A: x = 1; break true; case A: x = 1; yield true;
case B: break (x = 1) == 1 || true; case B: yield (x = 1) == 1 || true;
default: break false; default: yield false;
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
if (!t8) { if (!t8) {
@ -266,9 +266,9 @@ public class DefiniteAssignment1 {
E e = E.B; E e = E.B;
boolean t8 = (switch(e) { boolean t8 = (switch(e) {
case A: x = 1; break isTrue(); case A: x = 1; yield isTrue();
case B: break (x = 1) == 1 || isTrue(); case B: yield (x = 1) == 1 || isTrue();
default: break false; default: yield false;
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
if (!t8) { if (!t8) {
@ -281,9 +281,9 @@ public class DefiniteAssignment1 {
E e = E.A; E e = E.A;
boolean t9 = (switch(e) { boolean t9 = (switch(e) {
case A: x = 1; break true; case A: x = 1; yield true;
case B: break (x = 1) == 1 || true; case B: yield (x = 1) == 1 || true;
default: break false; default: yield false;
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
if (!t9) { if (!t9) {
@ -296,9 +296,9 @@ public class DefiniteAssignment1 {
E e = E.A; E e = E.A;
boolean t9 = (switch(e) { boolean t9 = (switch(e) {
case A: x = 1; break isTrue(); case A: x = 1; yield isTrue();
case B: break (x = 1) == 1 || isTrue(); case B: yield (x = 1) == 1 || isTrue();
default: break false; default: yield false;
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
if (!t9) { if (!t9) {
@ -311,9 +311,9 @@ public class DefiniteAssignment1 {
E e = E.C; E e = E.C;
boolean tA = (switch(e) { boolean tA = (switch(e) {
case A: x = 1; break true; case A: x = 1; yield true;
case B: break (x = 1) == 1 || true; case B: yield (x = 1) == 1 || true;
default: break false; default: yield false;
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
if (tA) { if (tA) {
@ -326,9 +326,9 @@ public class DefiniteAssignment1 {
E e = E.C; E e = E.C;
boolean tA = (switch(e) { boolean tA = (switch(e) {
case A: x = 1; break isTrue(); case A: x = 1; yield isTrue();
case B: break (x = 1) == 1 || isTrue(); case B: yield (x = 1) == 1 || isTrue();
default: break false; default: yield false;
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
if (tA) { if (tA) {
@ -341,9 +341,9 @@ public class DefiniteAssignment1 {
E e = E.C; E e = E.C;
boolean tA = (switch(e) { boolean tA = (switch(e) {
case A: x = 1; break true; case A: x = 1; yield true;
case B: break (x = 2) == 2 || true; case B: yield (x = 2) == 2 || true;
default: break false; default: yield false;
}) || (x = 3) == 3; //x is definitelly unassigned here }) || (x = 3) == 3; //x is definitelly unassigned here
if (x != 3) { if (x != 3) {
@ -356,9 +356,9 @@ public class DefiniteAssignment1 {
E e = E.A; E e = E.A;
boolean tA = (switch(e) { boolean tA = (switch(e) {
case A: break isTrue() && (x = 1) == 1; case A: yield isTrue() && (x = 1) == 1;
case B: break (x = 1) == 1 || isTrue(); case B: yield (x = 1) == 1 || isTrue();
default: break false; default: yield false;
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
if (!tA) { if (!tA) {
@ -371,9 +371,9 @@ public class DefiniteAssignment1 {
E e = E.A; E e = E.A;
boolean tA = (switch(e) { boolean tA = (switch(e) {
case A: break isTrue() && e != E.C ? (x = 1) == 1 && e != E.B : false; case A: yield isTrue() && e != E.C ? (x = 1) == 1 && e != E.B : false;
case B: break (x = 1) == 1 || true; case B: yield (x = 1) == 1 || true;
default: break false; default: yield false;
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
if (!tA) { if (!tA) {
@ -386,9 +386,9 @@ public class DefiniteAssignment1 {
E e = E.A; E e = E.A;
boolean tA = (switch(e) { boolean tA = (switch(e) {
case A: break isTrue() && e != E.C ? (x = 1) == 1 && e != E.B : false; case A: yield isTrue() && e != E.C ? (x = 1) == 1 && e != E.B : false;
case B: break (x = 1) == 1 || isTrue(); case B: yield (x = 1) == 1 || isTrue();
default: break false; default: yield false;
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
if (!tA) { if (!tA) {
@ -416,9 +416,9 @@ public class DefiniteAssignment1 {
E e = E.A; E e = E.A;
boolean tA = (switch(e) { boolean tA = (switch(e) {
case A -> { x = 1; break true; } case A -> { x = 1; yield true; }
case B -> { x = 1; break true; } case B -> { x = 1; yield true; }
case C -> { x = 1; break true; } case C -> { x = 1; yield true; }
}) && x == 1; //x is definitelly assigned here }) && x == 1; //x is definitelly assigned here
if (!tA) { if (!tA) {

View file

@ -15,8 +15,8 @@ public class DefiniteAssignment2 {
int x; int x;
t = (b && switch(a) { t = (b && switch(a) {
case 0: break (x = 1) == 1 || true; case 0: yield (x = 1) == 1 || true;
default: break false; default: yield false;
}) || x == 1; }) || x == 1;
} }
@ -24,8 +24,8 @@ public class DefiniteAssignment2 {
int x; int x;
t = (switch(a) { t = (switch(a) {
case 0: break (x = 1) == 1; case 0: yield (x = 1) == 1;
default: break false; default: yield false;
}) || x == 1; }) || x == 1;
} }
@ -33,9 +33,9 @@ public class DefiniteAssignment2 {
int x; int x;
t = (switch(a) { t = (switch(a) {
case 0: x = 1; break true; case 0: x = 1; yield true;
case 1: break (x = 1) == 1; case 1: yield (x = 1) == 1;
default: break false; default: yield false;
}) || x == 1; }) || x == 1;
} }
@ -43,9 +43,9 @@ public class DefiniteAssignment2 {
int x; int x;
t = (switch(a) { t = (switch(a) {
case 0: break true; case 0: yield true;
case 1: break (x = 1) == 1; case 1: yield (x = 1) == 1;
default: break false; default: yield false;
}) && x == 1; }) && x == 1;
} }
@ -53,9 +53,9 @@ public class DefiniteAssignment2 {
int x; int x;
t = (switch(a) { t = (switch(a) {
case 0: break false; case 0: yield false;
case 1: break isTrue() || (x = 1) == 1; case 1: yield isTrue() || (x = 1) == 1;
default: break false; default: yield false;
}) && x == 1; }) && x == 1;
} }
@ -63,9 +63,9 @@ public class DefiniteAssignment2 {
int x; int x;
t = (switch(a) { t = (switch(a) {
case 0: break false; case 0: yield false;
case 1: break isTrue() ? true : (x = 1) == 1; case 1: yield isTrue() ? true : (x = 1) == 1;
default: break false; default: yield false;
}) && x == 1; }) && x == 1;
} }
@ -73,9 +73,9 @@ public class DefiniteAssignment2 {
final int x; final int x;
t = (switch(a) { t = (switch(a) {
case 0: break false; case 0: yield false;
case 1: break isTrue() ? true : (x = 1) == 1; case 1: yield isTrue() ? true : (x = 1) == 1;
default: break false; default: yield false;
}) && (x = 1) == 1; }) && (x = 1) == 1;
} }
} }

View file

@ -39,15 +39,15 @@ public class ExpressionSwitch {
private String print(T t) { private String print(T t) {
return switch (t) { return switch (t) {
case A -> "A"; case A -> "A";
case B -> { break "B"; } case B -> { yield "B"; }
default -> { break "other"; } default -> { yield "other"; }
}; };
} }
private String exhaustive1(T t) { private String exhaustive1(T t) {
return switch (t) { return switch (t) {
case A -> "A"; case A -> "A";
case B -> { break "B"; } case B -> { yield "B"; }
case C -> "C"; case C -> "C";
case D -> "D"; case D -> "D";
}; };
@ -64,25 +64,25 @@ public class ExpressionSwitch {
private String scopesIsolated(T t) { private String scopesIsolated(T t) {
return switch (t) { return switch (t) {
case A -> { String res = "A"; break res;} case A -> { String res = "A"; yield res;}
case B -> { String res = "B"; break res;} case B -> { String res = "B"; yield res;}
default -> { String res = "default"; break res;} default -> { String res = "default"; yield res;}
}; };
} }
private Supplier<String> lambdas1(T t) { private Supplier<String> lambdas1(T t) {
return switch (t) { return switch (t) {
case A -> () -> "A"; case A -> () -> "A";
case B -> { break () -> "B"; } case B -> { yield () -> "B"; }
default -> () -> "default"; default -> () -> "default";
}; };
} }
private Supplier<String> lambdas2(T t) { private Supplier<String> lambdas2(T t) {
return switch (t) { return switch (t) {
case A: break () -> "A"; case A: yield () -> "A";
case B: { break () -> "B"; } case B: { yield () -> "B"; }
default: break () -> "default"; default: yield () -> "default";
}; };
} }
@ -91,16 +91,16 @@ public class ExpressionSwitch {
? -2 ? -2
: switch (s) { : switch (s) {
case "A", "B" -> 0; case "A", "B" -> 0;
case "C" -> { break 1; } case "C" -> { yield 1; }
default -> -1; default -> -1;
}; };
} }
private int convert2(String s) { private int convert2(String s) {
return switch (s) { return switch (s) {
case "A", "B": break 0; case "A", "B": yield 0;
case "C": break 1; case "C": yield 1;
default: break -1; default: yield -1;
}; };
} }
@ -112,7 +112,7 @@ public class ExpressionSwitch {
default: break STOP; default: break STOP;
} }
return switch (t) { return switch (t) {
default: break good; default: yield good;
}; };
} }
} }

View file

@ -58,11 +58,11 @@ public class ExpressionSwitchBreaks1 {
case 0: case 0:
return switch (j) { return switch (j) {
case 0: case 0:
if (true) break "0-0"; if (true) yield "0-0";
case 1: case 1:
break "0-1"; yield "0-1";
default: default:
break "0-X"; yield "0-X";
}; };
default: return "X"; default: return "X";
} }
@ -90,9 +90,9 @@ public class ExpressionSwitchBreaks1 {
r = "0-X"; r = "0-X";
break; break;
} }
break r; yield r;
case 1: case 1:
break "1"; yield "1";
case 2: case 2:
LOP: while (j-- > 0) { LOP: while (j-- > 0) {
if (k == 5) { if (k == 5) {
@ -102,9 +102,9 @@ public class ExpressionSwitchBreaks1 {
break LOP; break LOP;
} }
Supplier<String> getter = () -> { return "2-X-5"; }; Supplier<String> getter = () -> { return "2-X-5"; };
break getter.get(); yield getter.get();
default: default:
break "X"; yield "X";
}; };
} }

View file

@ -12,7 +12,7 @@ public class ExpressionSwitchBreaks2 {
case 0: case 0:
return switch (j) { return switch (j) {
case 0: case 0:
break "0-0"; yield "0-0";
case 1: case 1:
break ; //error: missing value break ; //error: missing value
case 2: case 2:
@ -20,9 +20,9 @@ public class ExpressionSwitchBreaks2 {
case 3: { case 3: {
int x = -1; int x = -1;
x: switch (i + j) { x: switch (i + j) {
case 0: break x; //error: cannot disambiguate, wrong type as well case 0: break x;
} }
break "X"; yield "X";
} }
case 4: return "X"; //error: no returns from inside of the switch expression case 4: return "X"; //error: no returns from inside of the switch expression
case 5: continue; //error: no continue out of the switch expression case 5: continue; //error: no continue out of the switch expression
@ -31,17 +31,17 @@ public class ExpressionSwitchBreaks2 {
default: { default: {
String x = "X"; String x = "X";
x: switch (i + j) { x: switch (i + j) {
case 0: break ""; //error: cannot break from switch expression that is not immediatelly enclosing case 0: yield ""; //error: cannot yield from switch expression that is not immediatelly enclosing
} }
break "X"; yield "X";
} }
}; };
case 1: case 1:
break "1" + undef; //error: complex value and no switch expression yield "1" + undef; //error: complex value and no switch expression
} }
} }
j: print(switch (i) { j: print(switch (i) {
default: break j; //error: "j" is ambiguous (expression/label) default: break j;
}, 0); }, 0);
j2: print(switch (i) { j2: print(switch (i) {
default: break j2; default: break j2;

View file

@ -1,15 +1,12 @@
ExpressionSwitchBreaks2.java:17:25: compiler.err.break.missing.value
ExpressionSwitchBreaks2.java:19:25: compiler.err.break.outside.switch.expression ExpressionSwitchBreaks2.java:19:25: compiler.err.break.outside.switch.expression
ExpressionSwitchBreaks2.java:23:37: compiler.err.break.ambiguous.target: x
ExpressionSwitchBreaks2.java:27:29: compiler.err.return.outside.switch.expression ExpressionSwitchBreaks2.java:27:29: compiler.err.return.outside.switch.expression
ExpressionSwitchBreaks2.java:28:29: compiler.err.continue.outside.switch.expression ExpressionSwitchBreaks2.java:28:29: compiler.err.continue.outside.switch.expression
ExpressionSwitchBreaks2.java:29:29: compiler.err.continue.outside.switch.expression ExpressionSwitchBreaks2.java:29:29: compiler.err.continue.outside.switch.expression
ExpressionSwitchBreaks2.java:30:29: compiler.err.undef.label: UNKNOWN ExpressionSwitchBreaks2.java:30:29: compiler.err.undef.label: UNKNOWN
ExpressionSwitchBreaks2.java:34:37: compiler.err.break.expr.not.immediate: compiler.misc.tree.tag.switch ExpressionSwitchBreaks2.java:40:17: compiler.err.no.switch.expression
ExpressionSwitchBreaks2.java:40:17: compiler.err.break.complex.value.no.switch.expression
ExpressionSwitchBreaks2.java:40:29: compiler.err.cant.resolve.location: kindname.variable, undef, , , (compiler.misc.location: kindname.class, ExpressionSwitchBreaks2, null) ExpressionSwitchBreaks2.java:40:29: compiler.err.cant.resolve.location: kindname.variable, undef, , , (compiler.misc.location: kindname.class, ExpressionSwitchBreaks2, null)
ExpressionSwitchBreaks2.java:44:22: compiler.err.break.ambiguous.target: j ExpressionSwitchBreaks2.java:44:22: compiler.err.break.outside.switch.expression
ExpressionSwitchBreaks2.java:47:22: compiler.err.break.outside.switch.expression ExpressionSwitchBreaks2.java:47:22: compiler.err.break.outside.switch.expression
- compiler.note.preview.filename: ExpressionSwitchBreaks2.java - compiler.note.preview.filename: ExpressionSwitchBreaks2.java
- compiler.note.preview.recompile - compiler.note.preview.recompile
12 errors 9 errors

View file

@ -34,47 +34,49 @@ public class ExpressionSwitchBugs {
new ExpressionSwitchBugs().testNested(); new ExpressionSwitchBugs().testNested();
new ExpressionSwitchBugs().testAnonymousClasses(); new ExpressionSwitchBugs().testAnonymousClasses();
new ExpressionSwitchBugs().testFields(); new ExpressionSwitchBugs().testFields();
check(3, new C(-1, 3).test(false));
check(3, new C(3, -1).test(true));
} }
private void testNested() { private void testNested() {
int i = 0; int i = 0;
check(42, id(switch (42) { check(42, id(switch (42) {
default: i++; break 42; default: i++; yield 42;
})); }));
i = 0; i = 0;
check(43, id(switch (42) { check(43, id(switch (42) {
case 42: while (i == 0) { case 42: while (i == 0) {
i++; i++;
} }
break 42 + i; yield 42 + i;
default: i++; break 42; default: i++; yield 42;
})); }));
i = 0; i = 0;
check(42, id(switch (42) { check(42, id(switch (42) {
case 42: if (i == 0) { case 42: if (i == 0) {
break 42; yield 42;
} }
default: i++; break 43; default: i++; yield 43;
})); }));
i = 0; i = 0;
check(42, id(switch (42) { check(42, id(switch (42) {
case 42: if (i == 0) { case 42: if (i == 0) {
break 41 + switch (0) { yield 41 + switch (0) {
case 0 -> 1; case 0 -> 1;
default -> -1; default -> -1;
}; };
} }
default: i++; break 43; default: i++; yield 43;
})); }));
} }
private void testAnonymousClasses() { private void testAnonymousClasses() {
for (int i : new int[] {1, 2}) { for (int i : new int[] {1, 2}) {
check(3, id((switch (i) { check(3, id((switch (i) {
case 1: break new I() { case 1: yield new I() {
public int g() { return 3; } public int g() { return 3; }
}; };
default: break (I) () -> { return 3; }; default: yield (I) () -> { return 3; };
}).g())); }).g()));
check(3, id((switch (i) { check(3, id((switch (i) {
case 1 -> new I() { case 1 -> new I() {
@ -96,7 +98,7 @@ public class ExpressionSwitchBugs {
case 2 -> { case 2 -> {
int temp = 0; int temp = 0;
temp += 3; temp += 3;
break temp; yield temp;
} }
default -> throw new IllegalStateException(); default -> throw new IllegalStateException();
}); });
@ -107,7 +109,7 @@ public class ExpressionSwitchBugs {
case 2 -> { case 2 -> {
int temp = 0; int temp = 0;
temp += 3; temp += 3;
break temp; yield temp;
} }
default -> throw new IllegalStateException(); default -> throw new IllegalStateException();
}); });
@ -120,7 +122,7 @@ public class ExpressionSwitchBugs {
return -1; return -1;
} }
private void check(int actual, int expected) { private static void check(int actual, int expected) {
if (actual != expected) { if (actual != expected) {
throw new AssertionError("Unexpected result: " + actual); throw new AssertionError("Unexpected result: " + actual);
} }
@ -129,4 +131,32 @@ public class ExpressionSwitchBugs {
public interface I { public interface I {
public int g(); public int g();
} }
static class Super {
public final int i;
public Super(int i) {
this.i = i;
}
}
static class C extends Super {
public final int i;
public C(int superI, int i) {
super(superI);
this.i = i;
}
public int test(boolean fromSuper) {
return switch (fromSuper ? 0 : 1) {
case 0 -> {
yield super.i;
}
default -> {
yield this.i;
}
};
}
}
} }

View file

@ -70,7 +70,7 @@ public class ExpressionSwitchDA {
int i; int i;
int j = 0; int j = 0;
int k = switch (j) { int k = switch (j) {
case 0 -> { i=42; break 42; } case 0 -> { i=42; yield 42; }
default -> i=42; default -> i=42;
}; };
System.out.println(i); System.out.println(i);
@ -80,7 +80,7 @@ public class ExpressionSwitchDA {
int j = 0; int j = 0;
int k = switch (j) { int k = switch (j) {
case 0 -> i=42; case 0 -> i=42;
default -> { i=42; break 42; } default -> { i=42; yield 42; }
}; };
System.out.println(i); System.out.println(i);
} }
@ -88,8 +88,8 @@ public class ExpressionSwitchDA {
int i; int i;
int j = 0; int j = 0;
int k = switch (j) { int k = switch (j) {
case 0 -> { i=42; break 42; } case 0 -> { i=42; yield 42; }
default -> { i=42; break 42; } default -> { i=42; yield 42; }
}; };
System.out.println(i); System.out.println(i);
} }

View file

@ -39,19 +39,19 @@ public class ExpressionSwitchEmbedding {
int i = 6; int i = 6;
int o = 0; int o = 0;
while (switch (i) { while (switch (i) {
case 1: i = 0; break true; case 1: i = 0; yield true;
case 2: i = 1; break true; case 2: i = 1; yield true;
case 3, 4: i--; case 3, 4: i--;
if (i == 2 || i == 4) { if (i == 2 || i == 4) {
break switch (i) { yield switch (i) {
case 2 -> true; case 2 -> true;
case 4 -> false; case 4 -> false;
default -> throw new IllegalStateException(); default -> throw new IllegalStateException();
}; };
} else { } else {
break true; yield true;
} }
default: i--; break switch (i) { default: i--; yield switch (i) {
case -1 -> false; case -1 -> false;
case 3 -> true; case 3 -> true;
default -> true; default -> true;
@ -67,8 +67,8 @@ public class ExpressionSwitchEmbedding {
int i = 6; int i = 6;
int o = 0; int o = 0;
while (switch (i) { while (switch (i) {
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; break true; } case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; yield true; }
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; break true; } case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; yield true; }
case 3, 4: case 3, 4:
try { try {
new ExpressionSwitchEmbedding().throwException(); new ExpressionSwitchEmbedding().throwException();
@ -76,16 +76,16 @@ public class ExpressionSwitchEmbedding {
i--; i--;
if (i == 2 || i == 4) { if (i == 2 || i == 4) {
try { try {
break switch (i) { yield switch (i) {
case 2 -> throw new ResultException(true); case 2 -> throw new ResultException(true);
case 4 -> false; case 4 -> false;
default -> throw new IllegalStateException(); default -> throw new IllegalStateException();
}; };
} catch (ResultException ex) { } catch (ResultException ex) {
break ex.result; yield ex.result;
} }
} else { } else {
break true; yield true;
} }
} }
default: default:
@ -93,7 +93,7 @@ public class ExpressionSwitchEmbedding {
new ExpressionSwitchEmbedding().throwException(); new ExpressionSwitchEmbedding().throwException();
} catch (Throwable t) { } catch (Throwable t) {
i--; i--;
break switch (i) { yield switch (i) {
case -1 -> false; case -1 -> false;
case 3 -> true; case 3 -> true;
default -> true; default -> true;
@ -111,19 +111,19 @@ public class ExpressionSwitchEmbedding {
int i = 6; int i = 6;
int o = 0; int o = 0;
if (switch (i) { if (switch (i) {
case 1: i = 0; break true; case 1: i = 0; yield true;
case 2: i = 1; break true; case 2: i = 1; yield true;
case 3, 4: i--; case 3, 4: i--;
if (i == 2 || i == 4) { if (i == 2 || i == 4) {
break (switch (i) { yield (switch (i) {
case 2 -> 3; case 2 -> 3;
case 4 -> 5; case 4 -> 5;
default -> throw new IllegalStateException(); default -> throw new IllegalStateException();
}) == i + 1; }) == i + 1;
} else { } else {
break true; yield true;
} }
default: i--; break switch (i) { default: i--; yield switch (i) {
case -1 -> false; case -1 -> false;
case 3 -> true; case 3 -> true;
default -> true; default -> true;
@ -139,8 +139,8 @@ public class ExpressionSwitchEmbedding {
int i = 6; int i = 6;
int o = 0; int o = 0;
if (switch (i) { if (switch (i) {
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; break true; } case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; yield true; }
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; break true; } case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; yield true; }
case 3, 4: case 3, 4:
try { try {
new ExpressionSwitchEmbedding().throwException(); new ExpressionSwitchEmbedding().throwException();
@ -148,16 +148,16 @@ public class ExpressionSwitchEmbedding {
i--; i--;
if (i == 2 || i == 4) { if (i == 2 || i == 4) {
try { try {
break switch (i) { yield switch (i) {
case 2 -> throw new ResultException(true); case 2 -> throw new ResultException(true);
case 4 -> false; case 4 -> false;
default -> throw new IllegalStateException(); default -> throw new IllegalStateException();
}; };
} catch (ResultException ex) { } catch (ResultException ex) {
break ex.result; yield ex.result;
} }
} else { } else {
break true; yield true;
} }
} }
default: default:
@ -165,7 +165,7 @@ public class ExpressionSwitchEmbedding {
new ExpressionSwitchEmbedding().throwException(); new ExpressionSwitchEmbedding().throwException();
} catch (Throwable t) { } catch (Throwable t) {
i--; i--;
break switch (i) { yield switch (i) {
case -1 -> false; case -1 -> false;
case 3 -> true; case 3 -> true;
default -> true; default -> true;
@ -182,19 +182,19 @@ public class ExpressionSwitchEmbedding {
{ {
int o = 0; int o = 0;
for (int i = 6; (switch (i) { for (int i = 6; (switch (i) {
case 1: i = 0; break true; case 1: i = 0; yield true;
case 2: i = 1; break true; case 2: i = 1; yield true;
case 3, 4: i--; case 3, 4: i--;
if (i == 2 || i == 4) { if (i == 2 || i == 4) {
break switch (i) { yield switch (i) {
case 2 -> true; case 2 -> true;
case 4 -> false; case 4 -> false;
default -> throw new IllegalStateException(); default -> throw new IllegalStateException();
}; };
} else { } else {
break true; yield true;
} }
default: i--; break switch (i) { default: i--; yield switch (i) {
case -1 -> false; case -1 -> false;
case 3 -> true; case 3 -> true;
default -> true; default -> true;
@ -209,8 +209,8 @@ public class ExpressionSwitchEmbedding {
{ {
int o = 0; int o = 0;
for (int i = 6; (switch (i) { for (int i = 6; (switch (i) {
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; break true; } case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; yield true; }
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; break true; } case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; yield true; }
case 3, 4: case 3, 4:
try { try {
new ExpressionSwitchEmbedding().throwException(); new ExpressionSwitchEmbedding().throwException();
@ -218,16 +218,16 @@ public class ExpressionSwitchEmbedding {
i--; i--;
if (i == 2 || i == 4) { if (i == 2 || i == 4) {
try { try {
break switch (i) { yield switch (i) {
case 2 -> throw new ResultException(true); case 2 -> throw new ResultException(true);
case 4 -> false; case 4 -> false;
default -> throw new IllegalStateException(); default -> throw new IllegalStateException();
}; };
} catch (ResultException ex) { } catch (ResultException ex) {
break ex.result; yield ex.result;
} }
} else { } else {
break true; yield true;
} }
} }
default: default:
@ -235,7 +235,7 @@ public class ExpressionSwitchEmbedding {
new ExpressionSwitchEmbedding().throwException(); new ExpressionSwitchEmbedding().throwException();
} catch (Throwable t) { } catch (Throwable t) {
i--; i--;
break switch (i) { yield switch (i) {
case -1 -> false; case -1 -> false;
case 3 -> true; case 3 -> true;
default -> true; default -> true;
@ -255,19 +255,19 @@ public class ExpressionSwitchEmbedding {
do { do {
o++; o++;
} while (switch (i) { } while (switch (i) {
case 1: i = 0; break true; case 1: i = 0; yield true;
case 2: i = 1; break true; case 2: i = 1; yield true;
case 3, 4: i--; case 3, 4: i--;
if (i == 2 || i == 4) { if (i == 2 || i == 4) {
break switch (i) { yield switch (i) {
case 2 -> true; case 2 -> true;
case 4 -> false; case 4 -> false;
default -> throw new IllegalStateException(); default -> throw new IllegalStateException();
}; };
} else { } else {
break true; yield true;
} }
default: i--; break switch (i) { default: i--; yield switch (i) {
case -1 -> false; case -1 -> false;
case 3 -> true; case 3 -> true;
default -> true; default -> true;
@ -283,8 +283,8 @@ public class ExpressionSwitchEmbedding {
do { do {
o++; o++;
} while (switch (i) { } while (switch (i) {
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; break true; } case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; yield true; }
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; break true; } case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; yield true; }
case 3, 4: case 3, 4:
try { try {
new ExpressionSwitchEmbedding().throwException(); new ExpressionSwitchEmbedding().throwException();
@ -292,16 +292,16 @@ public class ExpressionSwitchEmbedding {
i--; i--;
if (i == 2 || i == 4) { if (i == 2 || i == 4) {
try { try {
break switch (i) { yield switch (i) {
case 2 -> throw new ResultException(true); case 2 -> throw new ResultException(true);
case 4 -> false; case 4 -> false;
default -> throw new IllegalStateException(); default -> throw new IllegalStateException();
}; };
} catch (ResultException ex) { } catch (ResultException ex) {
break ex.result; yield ex.result;
} }
} else { } else {
break true; yield true;
} }
} }
default: default:
@ -309,7 +309,7 @@ public class ExpressionSwitchEmbedding {
new ExpressionSwitchEmbedding().throwException(); new ExpressionSwitchEmbedding().throwException();
} catch (Throwable t) { } catch (Throwable t) {
i--; i--;
break switch (i) { yield switch (i) {
case -1 -> false; case -1 -> false;
case 3 -> true; case 3 -> true;
default -> true; default -> true;

View file

@ -53,7 +53,7 @@ public class ExpressionSwitchFallThrough {
return switch (t) { return switch (t) {
case A: help = "a"; case A: help = "a";
case B: help += "b"; case B: help += "b";
default: break help; default: yield help;
}; };
} }
@ -62,7 +62,7 @@ public class ExpressionSwitchFallThrough {
return switch (t) { return switch (t) {
case A: help = "a"; case A: help = "a";
case B: help += "b"; case B: help += "b";
default: break help; default: yield help;
}; };
} }

View file

@ -50,8 +50,8 @@ public class ExpressionSwitchFallThrough1 {
return switch (p) { return switch (p) {
case 0: result += "0"; case 0: result += "0";
case 1: result += "1"; case 1: result += "1";
break result; yield result;
default: break "other"; default: yield "other";
}; };
} }
@ -60,7 +60,7 @@ public class ExpressionSwitchFallThrough1 {
switch (p) { switch (p) {
case 0: result += "0"; case 0: result += "0";
case 1: result += "1"; case 1: result += "1";
break ; break;
default: result = "other"; default: result = "other";
break; break;
} }

View file

@ -9,7 +9,7 @@ public class ExpressionSwitchFlow {
private String test1(int i) { private String test1(int i) {
return switch (i) { return switch (i) {
case 0 -> {} case 0 -> {}
default -> { break "other"; } default -> { yield "other"; }
}; };
} }
private String test2(int i) { private String test2(int i) {
@ -27,7 +27,7 @@ public class ExpressionSwitchFlow {
} }
private String test4(int i) { private String test4(int i) {
return switch (i) { return switch (i) {
case 0 -> { break "other"; } case 0 -> { yield "other"; }
default -> {} default -> {}
}; };
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -43,11 +43,11 @@ public class ExpressionSwitchInExpressionSwitch {
default -> { default -> {
int k = switch (j) { int k = switch (j) {
default -> { default -> {
break 42; yield 42;
} }
}; };
System.out.println("didn't break to the top level"); System.out.println("didn't yield to the top level");
break 43; yield 43;
} }
}; };
if (i!=43) { if (i!=43) {

View file

@ -27,7 +27,7 @@ public class ExpressionSwitchInfer {
String str = switch (param) { String str = switch (param) {
case "" -> { case "" -> {
break 0; yield 0;
} default ->"default"; } default ->"default";
}; };

View file

@ -26,9 +26,9 @@ public class ExpressionSwitchNotExhaustive {
s = "42"; s = "42";
break; break;
} }
break s; yield s;
default: default:
break "43"; yield "43";
}; };
} }
enum E { enum E {

View file

@ -0,0 +1,125 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8223305
* @summary Verify Tree.toString() related to switch expressions
* @modules jdk.compiler
*/
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import javax.tools.*;
import com.sun.source.util.JavacTask;
public class ExpressionSwitchToString {
private static final String CODE =
"public class C {" +
" void t1(Integer i) {" +
" switch (i) {" +
" case null: i++; break;" +
" case 0, 1: i++; break;" +
" default: i++; break;" +
" }" +
" }" +
" int t2(Integer i) {" +
" return switch (i) {" +
" case null: yield 0;" +
" case 0, 1: yield 1;" +
" default: yield 2;" +
" }" +
" }" +
"}";
private static final String EXPECTED =
"\n" +
"public class C {\n" +
" \n" +
" void t1(Integer i) {\n" +
" switch (i) {\n" +
" case null:\n" +
" i++;\n" +
" break;\n" +
" \n" +
" case 0, 1:\n" +
" i++;\n" +
" break;\n" +
" \n" +
" default:\n" +
" i++;\n" +
" break;\n" +
" \n" +
" }\n" +
" }\n" +
" \n" +
" int t2(Integer i) {\n" +
" return switch (i) {\n" +
" case null:\n" +
" yield 0;\n" +
" \n" +
" case 0, 1:\n" +
" yield 1;\n" +
" \n" +
" default:\n" +
" yield 2;\n" +
" \n" +
" };\n" +
" }\n" +
"}";
public static void main(String[] args) throws Exception {
final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
assert tool != null;
DiagnosticListener<JavaFileObject> noErrors = d -> {};
String sourceVersion = Integer.toString(Runtime.version().feature());
JavacTask ct = (JavacTask) tool.getTask(null, null, noErrors,
List.of("-XDdev", "--enable-preview", "-source", sourceVersion), null,
Arrays.asList(new MyFileObject(CODE)));
String actualCode = ct.parse().iterator().next().toString();
actualCode = actualCode.replace(System.getProperty("line.separator"), "\n");
if (!EXPECTED.equals(actualCode)) {
throw new AssertionError("Unexpected toString outcome: " +
actualCode);
}
}
static class MyFileObject extends SimpleJavaFileObject {
private String text;
public MyFileObject(String text) {
super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
this.text = text;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return text;
}
}
}

View file

@ -11,44 +11,44 @@ public class ExpressionSwitchUnreachable {
int z = 42; int z = 42;
int i = switch (z) { int i = switch (z) {
case 0 -> { case 0 -> {
break 42; yield 42;
System.out.println("Unreachable"); //Unreachable System.out.println("Unreachable"); //Unreachable
} }
default -> 0; default -> 0;
}; };
i = switch (z) { i = switch (z) {
case 0 -> { case 0 -> {
break 42; yield 42;
break 42; //Unreachable yield 42; //Unreachable
} }
default -> 0; default -> 0;
}; };
i = switch (z) { i = switch (z) {
case 0: case 0:
System.out.println("0"); System.out.println("0");
break 42; yield 42;
System.out.println("1"); //Unreachable System.out.println("1"); //Unreachable
default : break 42; default : yield 42;
}; };
i = switch (z) { i = switch (z) {
case 0 -> 42; case 0 -> 42;
default -> { default -> {
break 42; yield 42;
System.out.println("Unreachable"); //Unreachable System.out.println("Unreachable"); //Unreachable
} }
}; };
i = switch (z) { i = switch (z) {
case 0: break 42; case 0: yield 42;
default: default:
System.out.println("0"); System.out.println("0");
break 42; yield 42;
System.out.println("1"); //Unreachable System.out.println("1"); //Unreachable
}; };
i = switch (z) { i = switch (z) {
case 0: case 0:
default: default:
System.out.println("0"); System.out.println("0");
break 42; yield 42;
System.out.println("1"); //Unreachable System.out.println("1"); //Unreachable
}; };
} }

View file

@ -50,9 +50,9 @@ public class ParseIncomplete {
" }" + " }" +
" int t2(Integer i) {" + " int t2(Integer i) {" +
" return switch (i) {" + " return switch (i) {" +
" case null: break 0;" + " case null: yield 0;" +
" case 0, 1: break 1;" + " case 0, 1: yield 1;" +
" default: break 2;" + " default: yield 2;" +
" }" + " }" +
" }" + " }" +
"}"; "}";

View file

@ -38,7 +38,7 @@ public class SwitchExpressionIsNotAConstant {
int dummy = 1 + switch (i) { int dummy = 1 + switch (i) {
default -> { default -> {
i++; i++;
break 1; yield 1;
} }
}; };
if (i != 1) { if (i != 1) {
@ -51,7 +51,7 @@ public class SwitchExpressionIsNotAConstant {
case -1 -> 1; case -1 -> 1;
default -> { default -> {
i++; i++;
break 1; yield 1;
} }
}; };
if (i != 1) { if (i != 1) {
@ -63,7 +63,7 @@ public class SwitchExpressionIsNotAConstant {
int dummy = 1 + switch (i) { int dummy = 1 + switch (i) {
default : default :
i++; i++;
break 1; yield 1;
}; };
if (i != 1) { if (i != 1) {
throw new IllegalStateException("Side effects missing."); throw new IllegalStateException("Side effects missing.");
@ -72,10 +72,10 @@ public class SwitchExpressionIsNotAConstant {
{ {
i = 0; i = 0;
int dummy = 1 + switch (i) { int dummy = 1 + switch (i) {
case -1: break 1; case -1: yield 1;
default: default:
i++; i++;
break 1; yield 1;
}; };
if (i != 1) { if (i != 1) {
throw new IllegalStateException("Side effects missing."); throw new IllegalStateException("Side effects missing.");

View file

@ -9,9 +9,9 @@ public class SwitchExpressionScopesIsolated {
private String scopesIsolated(int i) { private String scopesIsolated(int i) {
return switch (i) { return switch (i) {
case 0 -> { String res = ""; break res; } case 0 -> { String res = ""; yield res; }
case 1 -> { res = ""; break res; } case 1 -> { res = ""; yield res; }
default -> { res = ""; break res; } default -> { res = ""; yield res; }
}; };
} }

View file

@ -38,6 +38,7 @@ import javax.tools.*;
import com.sun.source.tree.CompilationUnitTree; import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.SwitchExpressionTree; import com.sun.source.tree.SwitchExpressionTree;
import com.sun.source.tree.YieldTree;
import com.sun.source.tree.Tree; import com.sun.source.tree.Tree;
import com.sun.source.util.JavacTask; import com.sun.source.util.JavacTask;
import com.sun.source.util.SimpleTreeVisitor; import com.sun.source.util.SimpleTreeVisitor;
@ -53,12 +54,13 @@ public class SwitchExpressionSimpleVisitorTest {
String code = "class Test {\n" + String code = "class Test {\n" +
" int t(int i) {\n" + " int t(int i) {\n" +
" return switch(i) {\n" + " return switch(i) {\n" +
" default: break -1;\n" + " default: yield -1;\n" +
" }\n" + " }\n" +
" }\n" + " }\n" +
"}\n"; "}\n";
int[] callCount = new int[1]; int[] callCount = new int[1];
int[] switchExprNodeCount = new int[1]; int[] switchExprNodeCount = new int[1];
int[] yieldNodeCount = new int[1];
new TreePathScanner<Void, Void>() { new TreePathScanner<Void, Void>() {
@Override @Override
public Void visitSwitchExpression(SwitchExpressionTree node, Void p) { public Void visitSwitchExpression(SwitchExpressionTree node, Void p) {
@ -74,11 +76,27 @@ public class SwitchExpressionSimpleVisitorTest {
}, null); }, null);
return super.visitSwitchExpression(node, p); return super.visitSwitchExpression(node, p);
} }
@Override
public Void visitYield(YieldTree node, Void p) {
node.accept(new SimpleTreeVisitor<Void, Void>() {
@Override
protected Void defaultAction(Tree defaultActionNode, Void p) {
callCount[0]++;
if (node == defaultActionNode) {
yieldNodeCount[0]++;
}
return null;
}
}, null);
return super.visitYield(node, p);
}
}.scan(parse(code), null); }.scan(parse(code), null);
if (callCount[0] != 1 || switchExprNodeCount[0] != 1) { if (callCount[0] != 2 || switchExprNodeCount[0] != 1 ||
yieldNodeCount[0] != 1) {
throw new AssertionError("Unexpected counts; callCount=" + callCount[0] + throw new AssertionError("Unexpected counts; callCount=" + callCount[0] +
", switchExprNodeCount=" + switchExprNodeCount[0]); ", switchExprNodeCount=" + switchExprNodeCount[0] +
", yieldNodeCount=" + yieldNodeCount[0]);
} }
} }

View file

@ -38,34 +38,34 @@ public class TryCatch {
case 1: case 1:
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break -1; yield -1;
} catch(Throwable ex) { } catch(Throwable ex) {
break val; yield val;
} }
default: break -1; default: yield -1;
}; };
case 1 -> { case 1 -> {
try { try {
break new TryCatch().id(switch (p + 1) { yield new TryCatch().id(switch (p + 1) {
case 2: case 2:
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break -1; yield -1;
} catch(Throwable ex) { } catch(Throwable ex) {
throw ex; throw ex;
} }
default: break -1; default: yield -1;
}); });
} catch(Throwable ex) { } catch(Throwable ex) {
break val; yield val;
} }
} }
default -> { default -> {
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break -1; yield -1;
} catch(Throwable ex) { } catch(Throwable ex) {
break val; yield val;
} }
} }
} - 1); } - 1);
@ -83,34 +83,34 @@ public class TryCatch {
case 1: case 1:
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break false; yield false;
} catch(Throwable ex) { } catch(Throwable ex) {
break true; yield true;
} }
default: break false; default: yield false;
}; };
case 1 -> { case 1 -> {
try { try {
break new TryCatch().id(switch (p + 1) { yield new TryCatch().id(switch (p + 1) {
case 2: case 2:
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break false; yield false;
} catch(Throwable ex) { } catch(Throwable ex) {
throw ex; throw ex;
} }
default: break false; default: yield false;
}); });
} catch(Throwable ex) { } catch(Throwable ex) {
break true; yield true;
} }
} }
default -> { default -> {
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break false; yield false;
} catch(Throwable ex) { } catch(Throwable ex) {
break true; yield true;
} }
} }
} && (x = 1) == 1 && x == 1 ? val : -1); } && (x = 1) == 1 && x == 1 ? val : -1);
@ -127,34 +127,34 @@ public class TryCatch {
case B: case B:
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break -1; yield -1;
} catch(Throwable ex) { } catch(Throwable ex) {
break val; yield val;
} }
default: break -1; default: yield -1;
}; };
case B -> { case B -> {
try { try {
break new TryCatch().id(switch (e.next()) { yield new TryCatch().id(switch (e.next()) {
case C: case C:
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break -1; yield -1;
} catch(Throwable ex) { } catch(Throwable ex) {
throw ex; throw ex;
} }
default: break -1; default: yield -1;
}); });
} catch(Throwable ex) { } catch(Throwable ex) {
break val; yield val;
} }
} }
default -> { default -> {
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break -1; yield -1;
} catch(Throwable ex) { } catch(Throwable ex) {
break val; yield val;
} }
} }
} - 1); } - 1);
@ -172,34 +172,34 @@ public class TryCatch {
case B: case B:
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break false; yield false;
} catch(Throwable ex) { } catch(Throwable ex) {
break true; yield true;
} }
default: break false; default: yield false;
}; };
case B -> { case B -> {
try { try {
break new TryCatch().id(switch (e.next()) { yield new TryCatch().id(switch (e.next()) {
case C: case C:
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break false; yield false;
} catch(Throwable ex) { } catch(Throwable ex) {
throw ex; throw ex;
} }
default: break false; default: yield false;
}); });
} catch(Throwable ex) { } catch(Throwable ex) {
break true; yield true;
} }
} }
default -> { default -> {
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break false; yield false;
} catch(Throwable ex) { } catch(Throwable ex) {
break true; yield true;
} }
} }
} && (x = 1) == 1 && x == 1 ? val : -1); } && (x = 1) == 1 && x == 1 ? val : -1);
@ -216,34 +216,34 @@ public class TryCatch {
case "c": case "c":
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break -1; yield -1;
} catch(Throwable ex) { } catch(Throwable ex) {
break val; yield val;
} }
default: break -1; default: yield -1;
}; };
case "a" -> { case "a" -> {
try { try {
break new TryCatch().id(switch (s + "c") { yield new TryCatch().id(switch (s + "c") {
case "ac": case "ac":
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break -1; yield -1;
} catch(Throwable ex) { } catch(Throwable ex) {
throw ex; throw ex;
} }
default: break -1; default: yield -1;
}); });
} catch(Throwable ex) { } catch(Throwable ex) {
break val; yield val;
} }
} }
default -> { default -> {
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break -1; yield -1;
} catch(Throwable ex) { } catch(Throwable ex) {
break val; yield val;
} }
} }
} - 1); } - 1);
@ -261,34 +261,34 @@ public class TryCatch {
case "c": case "c":
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break false; yield false;
} catch(Throwable ex) { } catch(Throwable ex) {
break true; yield true;
} }
default: break false; default: yield false;
}; };
case "a" -> { case "a" -> {
try { try {
break new TryCatch().id(switch (s + "c") { yield new TryCatch().id(switch (s + "c") {
case "ac": case "ac":
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break false; yield false;
} catch(Throwable ex) { } catch(Throwable ex) {
throw ex; throw ex;
} }
default: break false; default: yield false;
}); });
} catch(Throwable ex) { } catch(Throwable ex) {
break true; yield true;
} }
} }
default -> { default -> {
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break false; yield false;
} catch(Throwable ex) { } catch(Throwable ex) {
break true; yield true;
} }
} }
} && (x = 1) == 1 && x == 1 ? val : -1); } && (x = 1) == 1 && x == 1 ? val : -1);
@ -330,75 +330,75 @@ public class TryCatch {
static class FieldHolder { static class FieldHolder {
private final int intTest = switch (0) { private final int intTest = switch (0) {
case -1: break -1; case -1: yield -1;
default: default:
try { try {
break new TryCatch().id(switch (2) { yield new TryCatch().id(switch (2) {
case 2: case 2:
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break -1; yield -1;
} catch(Throwable ex) { } catch(Throwable ex) {
throw ex; throw ex;
} }
default: break -1; default: yield -1;
}); });
} catch(Throwable ex) { } catch(Throwable ex) {
break 3; yield 3;
} }
}; };
private static final int intStaticTest = switch (0) { private static final int intStaticTest = switch (0) {
case -1: break -1; case -1: yield -1;
default: default:
try { try {
break new TryCatch().id(switch (2) { yield new TryCatch().id(switch (2) {
case 2: case 2:
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break -1; yield -1;
} catch(Throwable ex) { } catch(Throwable ex) {
throw ex; throw ex;
} }
default: break -1; default: yield -1;
}); });
} catch(Throwable ex) { } catch(Throwable ex) {
break 3; yield 3;
} }
}; };
private final boolean booleanTest = switch (0) { private final boolean booleanTest = switch (0) {
case -1: break false; case -1: yield false;
default: default:
try { try {
break new TryCatch().id(switch (2) { yield new TryCatch().id(switch (2) {
case 2: case 2:
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break false; yield false;
} catch(Throwable ex) { } catch(Throwable ex) {
throw ex; throw ex;
} }
default: break false; default: yield false;
}); });
} catch(Throwable ex) { } catch(Throwable ex) {
break true; yield true;
} }
}; };
private static final boolean booleanStaticTest = switch (0) { private static final boolean booleanStaticTest = switch (0) {
case -1: break false; case -1: yield false;
default: default:
try { try {
break new TryCatch().id(switch (2) { yield new TryCatch().id(switch (2) {
case 2: case 2:
try { try {
new TryCatch().throwException(); new TryCatch().throwException();
break false; yield false;
} catch(Throwable ex) { } catch(Throwable ex) {
throw ex; throw ex;
} }
default: break false; default: yield false;
}); });
} catch(Throwable ex) { } catch(Throwable ex) {
break true; yield true;
} }
}; };
} }

View file

@ -0,0 +1,162 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8223305
* @summary Verify correct warnings w.r.t. yield
* @compile/ref=WarnWrongYieldTest.out -source 13 -XDrawDiagnostics -XDshould-stop.at=ATTR WarnWrongYieldTest.java
*/
package t;
//ERROR - type called yield:
import t.WarnWrongYieldTest.yield;
public class WarnWrongYieldTest {
// ERROR - class called yield
class yield { }
// OK to have fields called yield
String[] yield = null;
// ERROR - field of type yield
yield y;
// OK to have methods called yield
// Nullary yield method
String[] yield() {
return null;
}
// Unary yield method
String[] yield(int i) {
return null;
}
// Binary yield method
String[] yield(int i, int j) {
return null;
}
// OK to declare a local called yield
void LocalDeclaration1() {
int yield;
}
// OK to declare and initialise a local called yield
void LocalDeclaration2() {
int yield = 42;
}
void YieldTypedLocals(int i) {
// ERROR - Parsed as yield statement, and y1 is unknown
yield y1 = null;
// ERROR - Parsed as yield statement, and y2 is unknown
yield y2 = new yield();
// ERROR - can not create an yield-valued local of type Object
Object y3 = new yield();
// ERROR - can not create a final yield-valued local of type yield
final yield y4 = new yield();
// ERROR - can create a non-final local of type yield using qualified typename
WarnWrongYieldTest.yield y5 = new yield();
}
void MethodInvocation(int i) {
// OK - can access a field called yield
String[] x = this.yield;
// ERROR - calling nullary yield method using simple name parsed as yield statement
yield();
// OK - can call nullary yield method using qualified name
this.yield();
// ERROR - Calling unary yield method using simple name is parsed as yield statement
yield(2);
// OK - calling unary yield method using qualified name
this.yield(2);
// ERROR - Calling binary yield method using simple name is parsed as yield statement
yield(2, 2); //error
// OK - calling binary yield method using qualified name
this.yield(2, 2);
// ERROR - nullary yield method as receiver is parsed as yield statement
yield().toString();
// OK - nullary yield method as receiver using qualified name
this.yield().toString();
// ERROR - unary yield method as receiver is parsed as yield statement
yield(2).toString();
// OK - unary yield method as receiver using qualified name
this.yield(2).toString();
// ERROR - binary yield method as receiver is parsed as yield statement
yield(2, 2).toString();
// OK - binary yield method as receiver using qualified name
this.yield(2, 2).toString();
// OK - yield method call is in an expression position
String str = yield(2).toString();
//OK - yield is a variable
yield.toString();
// OK - parsed as method call (with qualified local yield as receiver)
this.yield.toString();
yield[0].toString(); //error
}
private void yieldLocalVar1(int i) {
int yield = 0;
//OK - yield is a variable:
yield++;
yield--;
//OK - yield is a variable:
yield = 3;
//OK - yield is a variable:
for (int j = 0; j < 3; j++)
yield += 1;
//OK - yield is a variable and not at the beginning of the statement:
yieldLocalVar1(yield);
//ERROR - unqualified yield method invocation:
yieldLocalVar1(yield().length);
yieldLocalVar1(yield.class.getModifiers());
}
private void yieldLocalVar2(int i) {
int[] yield = new int[1];
//OK - yield is a variable:
yield[0] = 5;
}
}

View file

@ -0,0 +1,25 @@
WarnWrongYieldTest.java:39:11: compiler.warn.restricted.type.not.allowed.preview: yield, 13
WarnWrongYieldTest.java:45:5: compiler.warn.restricted.type.not.allowed.preview: yield, 13
WarnWrongYieldTest.java:72:15: compiler.warn.restricted.type.not.allowed.preview: yield, 13
WarnWrongYieldTest.java:75:15: compiler.warn.restricted.type.not.allowed.preview: yield, 13
WarnWrongYieldTest.java:81:21: compiler.warn.restricted.type.not.allowed.preview: yield, 13
WarnWrongYieldTest.java:93:9: compiler.warn.invalid.yield
WarnWrongYieldTest.java:98:9: compiler.warn.invalid.yield
WarnWrongYieldTest.java:103:9: compiler.warn.invalid.yield
WarnWrongYieldTest.java:108:9: compiler.warn.invalid.yield
WarnWrongYieldTest.java:113:9: compiler.warn.invalid.yield
WarnWrongYieldTest.java:118:9: compiler.warn.invalid.yield
WarnWrongYieldTest.java:123:22: compiler.warn.invalid.yield
WarnWrongYieldTest.java:152:24: compiler.warn.invalid.yield
WarnWrongYieldTest.java:34:28: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:45:5: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:72:9: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:75:9: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:75:24: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:78:25: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:81:15: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:81:30: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:84:27: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:84:43: compiler.warn.illegal.ref.to.restricted.type: yield
WarnWrongYieldTest.java:153:24: compiler.warn.illegal.ref.to.restricted.type: yield
24 warnings

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8223305
* @summary Ensure javac is not crashing for wrong breaks.
* @compile/fail/ref=WrongBreakTest.out --enable-preview -source ${jdk.version} -XDrawDiagnostics -XDshould-stop.at=FLOW WrongBreakTest.java
*/
public class WrongBreakTest {
void test(int i) {
int s = 0;
int j = switch (s) { default: break; };
test(switch (s) { default: yield; });
Runnable r = () -> {
yield 15;
};
while (true) {
yield 15;
}
}
void test(Object o) {}
}

View file

@ -0,0 +1,8 @@
WrongBreakTest.java:36:41: compiler.err.illegal.start.of.expr
WrongBreakTest.java:35:39: compiler.err.break.outside.switch.expression
WrongBreakTest.java:36:9: compiler.err.ref.ambiguous: test, kindname.method, test(int), WrongBreakTest, kindname.method, test(java.lang.Object), WrongBreakTest
WrongBreakTest.java:38:13: compiler.err.no.switch.expression
WrongBreakTest.java:41:13: compiler.err.no.switch.expression
- compiler.note.preview.filename: WrongBreakTest.java
- compiler.note.preview.recompile
5 errors

View file

@ -0,0 +1,225 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8223305
* @summary Ensure proper errors are returned for yields.
* @compile/fail/ref=WrongYieldTest.out --enable-preview -source ${jdk.version} -XDrawDiagnostics -XDshould-stop.at=ATTR WrongYieldTest.java
*/
package t;
//ERROR - type called yield:
import t.WrongYieldTest.yield;
public class WrongYieldTest {
// ERROR - class called yield
class yield { }
// OK to have fields called yield
String[] yield = null;
// ERROR - field of type yield
yield y;
// OK to have methods called yield
// Nullary yield method
String[] yield() {
return null;
}
// Unary yield method
String[] yield(int i) {
return null;
}
// Binary yield method
String[] yield(int i, int j) {
return null;
}
// OK to declare a local called yield
void LocalDeclaration1() {
int yield;
}
// OK to declare and initialise a local called yield
void LocalDeclaration2() {
int yield = 42;
}
// ERROR can't refer to a local called yield in the initialiser
void LocalDeclaration3() {
int yield = yield + 1;
}
// OK yield gets interpreted as an identifier in a local declaration
void LocalDeclaration4(int i) {
int local = switch (i) {
default -> {
int yield = yield + 1;
yield 42;
}
};
}
// OK - yield a local called yield
void LocalDeclaration5(int i) {
int yield = 42;
int temp = switch (i) {
default -> {
yield yield;
}
};
}
void YieldTypedLocals(int i) {
// ERROR - Parsed as yield statement, and y1 is unknown
yield y1 = null;
// ..whereas..
// ERROR - parsed as yield statement, which has no switch target
Object y1;
yield y1 = null;
// ERROR - Parsed as yield statement, and y2 is unknown
yield y2 = new yield();
// OK - Parsed as yield statement that assigns local y
Object y;
Object o = switch (i) {
default :
yield y = null;
};
// ERROR - Parsed as yield statement that assigns local y,
//but the initializer refers to restricted identifier:
Object y2;
Object o2 = switch (i) {
default :
yield y2 = new yield();
};
// ERROR - can not create an yield-valued local of type Object
Object y3 = new yield();
// ERROR - can not create a final yield-valued local of type yield
final yield y4 = new yield();
// ERROR - can create a non-final local of type yield using qualified typename
WrongYieldTest.yield y5 = new yield();
}
void MethodInvocation(int i) {
// OK - can access a field called yield
String[] x = this.yield;
// ERROR - calling nullary yield method using simple name parsed as yield statement
yield();
// OK - can call nullary yield method using qualified name
this.yield();
// ERROR - Calling unary yield method using simple name is parsed as yield statement
yield(2);
// OK - calling unary yield method using qualified name
this.yield(2);
// ERROR - Calling binary yield method using simple name is parsed as yield statement
yield(2, 2); //error
// OK - calling binary yield method using qualified name
this.yield(2, 2);
// ERROR - nullary yield method as receiver is parsed as yield statement
yield().toString();
// OK - nullary yield method as receiver using qualified name
this.yield().toString();
// ERROR - unary yield method as receiver is parsed as yield statement
yield(2).toString();
// OK - unary yield method as receiver using qualified name
this.yield(2).toString();
// ERROR - binary yield method as receiver is parsed as yield statement
yield(2, 2).toString();
// OK - binary yield method as receiver using qualified name
this.yield(2, 2).toString();
// OK - yield method call is in an expression position
String str = yield(2).toString();
//OK - yield is a variable
yield.toString();
// OK - parsed as method call (with qualified local yield as receiver)
this.yield.toString();
yield[0].toString(); //error
// OK - parsed as yield statement in switch expression
int j = switch (i) {
default:
yield(2);
};
// ERROR - second yield is an unreachable statement.
x = switch (i) {
default: {
yield x = null;
yield null;
}
};
}
private void yieldLocalVar1(int i) {
int yield = 0;
//OK - yield is a variable:
yield++;
yield--;
//ERROR - yield is a statement, but no enclosing switch expr:
yield ++i;
yield --i;
//OK - yield is a variable:
yield = 3;
//OK - yield is a variable:
for (int j = 0; j < 3; j++)
yield += 1;
//OK - yield is a variable and not at the beginning of the statement:
yieldLocalVar1(yield);
//ERROR - unqualified yield method invocation:
yieldLocalVar1(yield().length);
yieldLocalVar1(yield.class.getModifiers());
}
private void yieldLocalVar2(int i) {
int[] yield = new int[1];
//OK - yield is a variable:
yield[0] = 5;
}
}

View file

@ -0,0 +1,29 @@
WrongYieldTest.java:39:11: compiler.err.restricted.type.not.allowed: yield, 13
WrongYieldTest.java:45:5: compiler.err.restricted.type.not.allowed.here: yield
WrongYieldTest.java:136:9: compiler.err.invalid.yield
WrongYieldTest.java:146:9: compiler.err.invalid.yield
WrongYieldTest.java:151:9: compiler.err.invalid.yield
WrongYieldTest.java:161:9: compiler.err.invalid.yield
WrongYieldTest.java:166:22: compiler.err.invalid.yield
WrongYieldTest.java:215:24: compiler.err.invalid.yield
WrongYieldTest.java:34:24: compiler.err.illegal.ref.to.restricted.type: yield
WrongYieldTest.java:95:9: compiler.err.no.switch.expression
WrongYieldTest.java:95:15: compiler.err.cant.resolve.location: kindname.variable, y1, , , (compiler.misc.location: kindname.class, t.WrongYieldTest, null)
WrongYieldTest.java:99:9: compiler.err.no.switch.expression
WrongYieldTest.java:102:9: compiler.err.no.switch.expression
WrongYieldTest.java:102:15: compiler.err.cant.resolve.location: kindname.variable, y2, , , (compiler.misc.location: kindname.class, t.WrongYieldTest, null)
WrongYieldTest.java:102:24: compiler.err.illegal.ref.to.restricted.type: yield
WrongYieldTest.java:116:32: compiler.err.illegal.ref.to.restricted.type: yield
WrongYieldTest.java:120:25: compiler.err.illegal.ref.to.restricted.type: yield
WrongYieldTest.java:123:30: compiler.err.illegal.ref.to.restricted.type: yield
WrongYieldTest.java:126:23: compiler.err.illegal.ref.to.restricted.type: yield
WrongYieldTest.java:126:39: compiler.err.illegal.ref.to.restricted.type: yield
WrongYieldTest.java:141:9: compiler.err.no.switch.expression.qualify
WrongYieldTest.java:156:9: compiler.err.no.switch.expression
WrongYieldTest.java:156:17: compiler.err.cant.deref: int
WrongYieldTest.java:201:9: compiler.err.no.switch.expression
WrongYieldTest.java:202:9: compiler.err.no.switch.expression
WrongYieldTest.java:216:24: compiler.err.illegal.ref.to.restricted.type: yield
- compiler.note.preview.filename: WrongYieldTest.java
- compiler.note.preview.recompile
26 errors

View file

@ -0,0 +1,116 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @summary Verify that definite assignment works (legal code)
* @compile --enable-preview -source ${jdk.version} DefiniteAssignment1.java
* @run main/othervm --enable-preview DefiniteAssignment1
*/
public class DefiniteAssignment1 {
public static void main(String[] args) {
int a = 0;
{
int x;
switch(a) {
case 0: x = 0; break;
default: x = 1; break;
}
if (x != 0)
throw new IllegalStateException("Unexpected value.");
}
{
int x;
switch(a) {
case 1: x = 1; break;
case 0:
default: x = 0; break;
}
if (x != 0)
throw new IllegalStateException("Unexpected value.");
}
{
int x;
switch(a) {
case 1: x = 1; break;
case 0:
default: x = 0;
}
if (x != 0)
throw new IllegalStateException("Unexpected value.");
}
{
int x;
switch(a) {
case 0 -> x = 0;
default -> x = 1;
}
if (x != 0)
throw new IllegalStateException("Unexpected value.");
}
{
int x;
try {
switch(a) {
case 1: x = 1; break;
case 0:
default: throw new UnsupportedOperationException();
}
throw new IllegalStateException("Unexpected value: " + x);
} catch (UnsupportedOperationException ex) {
//OK
}
}
{
int x;
switch(a) {
case 0 -> x = 0;
default -> throw new IllegalStateException();
}
if (x != 0)
throw new IllegalStateException("Unexpected value.");
}
}
enum E {
A, B, C;
}
}

View file

@ -0,0 +1,80 @@
/**
* @test /nodynamiccopyright/
* @summary Verify that definite assignment works (illegal code)
* @compile/fail/ref=DefiniteAssignment2.out -XDrawDiagnostics --enable-preview -source ${jdk.version} DefiniteAssignment2.java
*/
public class DefiniteAssignment2 {
public static void main(String[] args) {
int a = 0;
E e = E.A;
{
int x;
switch(a) {
case 0: break;
default: x = 1; break;
}
System.err.println(x);
}
{
int x;
switch(a) {
case 0 -> {}
default -> x = 1;
}
System.err.println(x);
}
{
int x;
switch(a) {
case 0: x = 0; break;
default:
}
System.err.println(x);
}
{
int x;
switch(e) {
case A, B, C -> x = 0;
}
System.err.println(x);
}
{
int x;
switch(e) {
case A, B, C -> { x = 0; }
}
System.err.println(x);
}
{
int x;
switch(e) {
case A, B -> { x = 0; }
case C -> throw new IllegalStateException();
}
System.err.println(x);
}
}
enum E {
A, B, C;
}
}

View file

@ -0,0 +1,9 @@
DefiniteAssignment2.java:20:28: compiler.err.var.might.not.have.been.initialized: x
DefiniteAssignment2.java:31:28: compiler.err.var.might.not.have.been.initialized: x
DefiniteAssignment2.java:42:28: compiler.err.var.might.not.have.been.initialized: x
DefiniteAssignment2.java:52:28: compiler.err.var.might.not.have.been.initialized: x
DefiniteAssignment2.java:62:28: compiler.err.var.might.not.have.been.initialized: x
DefiniteAssignment2.java:73:28: compiler.err.var.might.not.have.been.initialized: x
- compiler.note.preview.filename: DefiniteAssignment2.java
- compiler.note.preview.recompile
6 errors

View file

@ -30,7 +30,7 @@ public class MultipleLabelsExpression {
private String expression1(T t) { private String expression1(T t) {
return switch (t) { return switch (t) {
case A -> "A"; case A -> "A";
case B, C -> { break "B-C"; } case B, C -> { yield "B-C"; }
case D -> "D"; case D -> "D";
default -> "other"; default -> "other";
}; };

View file

@ -2,5 +2,5 @@ VarInImplicitLambdaNegTest01.java:12:28: compiler.err.invalid.lambda.parameter.d
VarInImplicitLambdaNegTest01.java:13:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.var.and.implicit.not.allowed) VarInImplicitLambdaNegTest01.java:13:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.var.and.implicit.not.allowed)
VarInImplicitLambdaNegTest01.java:14:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.var.and.explicit.not.allowed) VarInImplicitLambdaNegTest01.java:14:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.var.and.explicit.not.allowed)
VarInImplicitLambdaNegTest01.java:15:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.implicit.and.explicit.not.allowed) VarInImplicitLambdaNegTest01.java:15:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.implicit.and.explicit.not.allowed)
VarInImplicitLambdaNegTest01.java:17:52: compiler.err.var.not.allowed.array VarInImplicitLambdaNegTest01.java:17:52: compiler.err.restricted.type.not.allowed.array: var
5 errors 5 errors

View file

@ -1,6 +1,6 @@
- compiler.warn.source.no.bootclasspath: 10 - compiler.warn.source.no.bootclasspath: 10
VarInImplicitLambdaNegTest01.java:12:36: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.var.syntax.in.implicit.lambda), 10, 11 VarInImplicitLambdaNegTest01.java:12:36: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.var.syntax.in.implicit.lambda), 10, 11
VarInImplicitLambdaNegTest01.java:15:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.implicit.and.explicit.not.allowed) VarInImplicitLambdaNegTest01.java:15:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.implicit.and.explicit.not.allowed)
VarInImplicitLambdaNegTest01.java:17:52: compiler.err.var.not.allowed.here VarInImplicitLambdaNegTest01.java:17:52: compiler.err.restricted.type.not.allowed.here: var
3 errors 3 errors
1 warning 1 warning