# HG changeset patch # User duke # Date 1499270874 -7200 # Node ID 122a0aede7503727c730cefd4210a50a6f476d49 # Parent c529d3f99946921d67b98e5a492b795de4df6ff7# Parent 61eccc72f402cacd98a0ccf6c709094d8ce5b997 Merge diff -r 61eccc72f402 -r 122a0aede750 langtools/.hgtags --- a/langtools/.hgtags Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/.hgtags Wed Jul 05 18:07:54 2017 +0200 @@ -154,3 +154,4 @@ 08a3425f39f829502ca0ddbfb2d051c31710cb19 jdk8-b30 b28cfbe7e8b196da954bed9a22bfd790e55333aa jdk8-b31 be069d72dde2bfe6f996c46325a320961ca854c2 jdk8-b32 +46831c72b7f6c69fef2cc2935001863643a65f94 jdk8-b33 diff -r 61eccc72f402 -r 122a0aede750 langtools/makefiles/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/makefiles/Makefile Wed Jul 05 18:07:54 2017 +0200 @@ -0,0 +1,203 @@ +# +# Copyright (c) 2011, 2012, 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. +# + +include $(SPEC) +include MakeBase.gmk +include JavaCompilation.gmk + +default: all + +# The BOOT_JAVAC setup uses the bootdir compiler to compile the tools +# and the bootstrap javac, to be run by the bootdir jvm. +$(eval $(call SetupJavaCompiler,BOOT_JAVAC,\ + JAVAC:=$(JAVAC),\ + FLAGS:=-Xprefer:source -XDignore.symbol.file=true -g,\ + MODE:=SINGLE_THREADED_BATCH)) + +# Now setup the compilation of the properties compilation tool. You can depend +# upon $(BUILD_TOOLS) to trigger a compilation of the tools. Note that we +# add src/share/classes to the sourcepath. This is necessary since the GenStubs +# program needs to be linked and run towards the new javac sources. +$(eval $(call SetupJavaCompilation,BUILD_TOOLS,\ + SETUP:=BOOT_JAVAC,\ + SRC:=$(LANGTOOLS_TOPDIR)/make/tools $(LANGTOOLS_TOPDIR)/src/share/classes,\ + INCLUDES:=compileproperties genstubs,\ + BIN:=$(LANGTOOLS_OUTPUTDIR)/btclasses)) + +# The compileprops tools compiles a properties file into a resource bundle. +TOOL_COMPILEPROPS_CMD:=$(JAVA) -cp $(LANGTOOLS_OUTPUTDIR)/btclasses compileproperties.CompileProperties -quiet +# Lookup the properties that need to be compiled into resource bundles. +PROPSOURCES:=$(shell find $(LANGTOOLS_TOPDIR)/src/share/classes -name "*.properties") +# Strip away prefix and suffix, leaving for example only: "com/sun/tools/javac/resources/javac_zh_CN" +PROPPATHS:=$(patsubst $(LANGTOOLS_TOPDIR)/src/share/classes/%.properties,%,$(PROPSOURCES)) +# Generate the list of java files to be created. +PROPJAVAS:=$(patsubst %,$(LANGTOOLS_OUTPUTDIR)/gensrc/%.java,$(PROPPATHS)) +# Generate the package dirs for the tobe generated java files. +PROPDIRS:=$(dir $(PROPJAVAS)) +# Now generate a sequence of "-compile ...javac_zh_CN.properties ...javac_zh_CN.java java.util.ListResourceBundle" +# suitable to be fed into the CompileProperties command. +PROPCMDLINE:=$(subst _SPACE_,$(SPACE),$(join $(addprefix -compile_SPACE_,$(PROPSOURCES)), \ + $(addsuffix _SPACE_java.util.ListResourceBundle,$(addprefix _SPACE_$(LANGTOOLS_OUTPUTDIR)/gensrc/,$(addsuffix .java,$(PROPPATHS)))))) + +# Now setup the rule for the generation of the resource bundles. +$(LANGTOOLS_OUTPUTDIR)/gensrc/_the_props.d : $(PROPSOURCES) $(BUILD_TOOLS) + rm -rf $(@D)/* + mkdir -p $(@D) $(PROPDIRS) + printf "jdk=$(JDK_VERSION)\nfull=$(FULL_VERSION)\nrelease=$(RELEASE)\n" > $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javah/resources/version.properties + printf "jdk=$(JDK_VERSION)\nfull=$(FULL_VERSION)\nrelease=$(RELEASE)\n" > $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javap/resources/version.properties + printf "jdk=$(JDK_VERSION)\nfull=$(FULL_VERSION)\nrelease=$(RELEASE)\n" > $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javac/resources/version.properties + echo Compiling $(words $(PROPSOURCES) v1 v2 v3) properties into resource bundles + $(TOOL_COMPILEPROPS_CMD) $(PROPCMDLINE) \ + -compile $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javah/resources/version.properties \ + $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javah/resources/version.java \ + java.util.ListResourceBundle \ + -compile $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javap/resources/version.properties \ + $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javap/resources/version.java \ + java.util.ListResourceBundle \ + -compile $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javac/resources/version.properties \ + $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javac/resources/version.java \ + java.util.ListResourceBundle + echo PROPS_ARE_CREATED=yes > $@ + +# Trigger the generation of the resource bundles. After the resource bundles have +# been compiled, then the makefile will restart and the newly created java files +# will become part of the build further along in the makefile. +-include $(LANGTOOLS_OUTPUTDIR)/gensrc/_the_props.d + +ifeq ($(PROPS_ARE_CREATED),yes) + # Setup the rules to build a dist/bootstrap/lib/javac.jar, ie a smaller intermediate javac + # that can be compiled with an old javac. The intermediate javac is then used + # to compile javac again and to build the complete new jdk. + $(eval $(call SetupJavaCompilation,BUILD_BOOTSTRAP_LANGTOOLS,\ + SETUP:=BOOT_JAVAC,\ + SRC:=$(LANGTOOLS_TOPDIR)/src/share/classes $(LANGTOOLS_OUTPUTDIR)/gensrc,\ + EXCLUDES:=com/sun/tools/javac/nio,\ + BIN:=$(LANGTOOLS_OUTPUTDIR)/btclasses/bootstrap)) + + $(eval $(call SetupArchive,ARCHIVE_BOOTSTRAP_JAVAC,$(BUILD_BOOTSTRAP_LANGTOOLS),\ + SRCS:=$(LANGTOOLS_OUTPUTDIR)/btclasses/bootstrap,\ + JAR:=$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar,\ + JARMAIN:=com.sun.tools.javac.Main)) + + $(eval $(call SetupArchive,ARCHIVE_BOOTSTRAP_JAVAH,$(BUILD_BOOTSTRAP_LANGTOOLS),\ + SRCS:=$(LANGTOOLS_OUTPUTDIR)/btclasses/bootstrap,\ + JAR:=$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javah.jar,\ + JARMAIN:=com.sun.tools.javah.Main)) + + $(eval $(call SetupArchive,ARCHIVE_BOOTSTRAP_JAVAP,$(BUILD_BOOTSTRAP_LANGTOOLS),\ + SRCS:=$(LANGTOOLS_OUTPUTDIR)/btclasses/bootstrap,\ + JAR:=$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javap.jar,\ + JARMAIN:=com.sun.tools.javap.Main)) + + $(eval $(call SetupArchive,ARCHIVE_BOOTSTRAP_JAVADOC,$(BUILD_BOOTSTRAP_LANGTOOLS),\ + SRCS:=$(LANGTOOLS_OUTPUTDIR)/btclasses/bootstrap,\ + JAR:=$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javadoc.jar,\ + JARMAIN:=com.sun.tools.javadoc.Main)) + + # GenStubs is used to bootstrap any dependencies from javac to the new JDK that is not + # yet built. It is currently not needed but might be again in the future. The following + # exercises the functionality to verify that it works. + TOOL_GENSTUBS_CMD=$(JAVA) \ + "-Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar" \ + -cp "$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar$(PATH_SEP)$(LANGTOOLS_OUTPUTDIR)/btclasses" \ + genstubs.GenStubs + # We fetch source from the JDK... + JDKS=$(JDK_TOPDIR)/src/share/classes + # Build the list of classes to generate stubs from. java/util/Objects.java isn't + # currently needed, but is used as a demo for now. + STUBSOURCES:=$(shell $(FIND) $(JDKS) -name "*.java" | $(GREP) \ + -e "$(JDKS)/java/util/Objects.java") + # Rewrite the file names into class names because the GenStubs tool require this. + STUBCLASSES:=$(subst /,.,$(patsubst $(JDKS)/%.java,%,$(STUBSOURCES))) + + # Now setup the build recipe for genstubs. + $(LANGTOOLS_OUTPUTDIR)/genstubs/_the_stubs.d : $(STUBSOURCES) $(BUILD_TOOLS) \ + $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar \ + $(LANGTOOLS_OUTPUTDIR)/gensrc/_the_props.d + mkdir -p $(@D) + mkdir -p $(LANGTOOLS_OUTPUTDIR)/tmpstubs + echo Generating stubs from JDK sources. + ($(TOOL_GENSTUBS_CMD) -s $(LANGTOOLS_OUTPUTDIR)/tmpstubs -sourcepath $(JDKS) $(STUBCLASSES) && echo STUBS_ARE_CREATED=yes > $@) + if $(DIFF) -x "_the*" -rq $(LANGTOOLS_OUTPUTDIR)/tmpstubs $(LANGTOOLS_OUTPUTDIR)/genstubs > /dev/null 2>&1; then \ + echo No changes in the stubs!; \ + rm -rf $(LANGTOOLS_OUTPUTDIR)/tmpstubs; \ + else \ + echo Changes in stubs detected!; \ + rm -rf $(@D); \ + mv $(LANGTOOLS_OUTPUTDIR)/tmpstubs $(@D); \ + fi + echo STUBS_ARE_CREATED=yes > $@ + + # Trigger a generation of the genstubs java source code and a restart + # of the makefile to make sure that the following build setup use the + # newly created java files. + -include $(LANGTOOLS_OUTPUTDIR)/genstubs/_the_stubs.d + + ifeq ($(STUBS_ARE_CREATED),yes) + # Setup a compiler configuration using the intermediate javac in dist/bootstrap/lib/javac.jar + # that generates code for the new jdk that is being built. + # The code compiled by this compiler setup, cannot necessarily be run with the bootstrap jvm. + $(eval $(call SetupJavaCompiler,GENERATE_NEWBYTECODE,\ + JVM:=$(JAVA),\ + JAVAC:="-Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar" \ + -jar $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar,\ + FLAGS:=-Xprefer:source -XDignore.symbol.file=true,\ + SERVER_DIR:=$(JAVAC_SERVERS),\ + SERVER_JVM:=$(SERVER_JAVA),\ + MODE:=$(JAVAC_USE_MODE),\ + USE_DEPS:=$(JAVAC_USE_DEPS))) + + # javax.tools.JavaCompilerTool isn't really a suffix but this gets the file copied. + RESOURCE_SUFFIXES:=.gif .xml .css javax.tools.JavaCompilerTool + + $(eval $(call SetupJavaCompilation,BUILD_FULL_JAVAC,\ + SETUP:=GENERATE_NEWBYTECODE,\ + SRC:=$(LANGTOOLS_TOPDIR)/src/share/classes $(LANGTOOLS_OUTPUTDIR)/gensrc \ + $(LANGTOOLS_OUTPUTDIR)/genstubs,\ + EXCLUDES:=java/util java/io java/nio,\ + COPY:=$(RESOURCE_SUFFIXES),\ + BIN:=$(LANGTOOLS_OUTPUTDIR)/classes)) + + $(eval $(call SetupArchive,ARCHIVE_FULL_JAVAC,$(BUILD_FULL_JAVAC),\ + SETUP:=GENERATE_NEWBYTECODE,\ + SRCS:=$(LANGTOOLS_OUTPUTDIR)/classes,\ + SUFFIXES:=.class $(RESOURCE_SUFFIXES),\ + JAR:=$(LANGTOOLS_OUTPUTDIR)/dist/lib/classes.jar,\ + HEADERS:=$(LANGTOOLS_OUTPUTDIR)/gensrc_headers)) + + $(eval $(call SetupZipArchive,ZIP_FULL_JAVAC_SOURCE,\ + SRC:=$(LANGTOOLS_TOPDIR)/src/share/classes $(LANGTOOLS_OUTPUTDIR)/gensrc,\ + ZIP:=$(LANGTOOLS_OUTPUTDIR)/dist/lib/src.zip)) + + all: $(LANGTOOLS_OUTPUTDIR)/dist/lib/classes.jar \ + $(LANGTOOLS_OUTPUTDIR)/dist/lib/src.zip \ + $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar \ + $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javah.jar \ + $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javap.jar \ + $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javadoc.jar + + + endif +endif diff -r 61eccc72f402 -r 122a0aede750 langtools/src/share/classes/com/sun/tools/javac/code/Flags.java --- a/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java Wed Jul 05 18:07:54 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, 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 @@ -221,7 +221,7 @@ /** Flag that marks a hypothetical method that need not really be * generated in the binary, but is present in the symbol table to - * simplify checking for erasure clashes. + * simplify checking for erasure clashes - also used for 292 poly sig methods. */ public static final long HYPOTHETICAL = 1L<<37; @@ -236,26 +236,20 @@ public static final long UNION = 1L<<39; /** - * Flag that marks a signature-polymorphic invoke method. - * (These occur inside java.lang.invoke.MethodHandle.) - */ - public static final long POLYMORPHIC_SIGNATURE = 1L<<40; - - /** * Flag that marks a special kind of bridge methods (the ones that * come from restricted supertype bounds) */ - public static final long OVERRIDE_BRIDGE = 1L<<41; + public static final long OVERRIDE_BRIDGE = 1L<<40; /** * Flag that marks an 'effectively final' local variable */ - public static final long EFFECTIVELY_FINAL = 1L<<42; + public static final long EFFECTIVELY_FINAL = 1L<<41; /** * Flag that marks non-override equivalent methods with the same signature */ - public static final long CLASH = 1L<<43; + public static final long CLASH = 1L<<42; /** Modifier masks. */ diff -r 61eccc72f402 -r 122a0aede750 langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java --- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java Wed Jul 05 18:07:54 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, 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 @@ -202,16 +202,6 @@ return (flags() & INTERFACE) != 0; } - /** Recognize if this symbol was marked @PolymorphicSignature in the source. */ - public boolean isPolymorphicSignatureGeneric() { - return (flags() & (POLYMORPHIC_SIGNATURE | HYPOTHETICAL)) == POLYMORPHIC_SIGNATURE; - } - - /** Recognize if this symbol was split from a @PolymorphicSignature symbol in the source. */ - public boolean isPolymorphicSignatureInstance() { - return (flags() & (POLYMORPHIC_SIGNATURE | HYPOTHETICAL)) == (POLYMORPHIC_SIGNATURE | HYPOTHETICAL); - } - /** Is this symbol declared (directly or indirectly) local * to a method or variable initializer? * Also includes fields of inner classes which are in @@ -1316,6 +1306,25 @@ getKind() == ElementKind.INSTANCE_INIT; } + /** + * A polymorphic signature method (JLS SE 7, 8.4.1) is a method that + * (i) is declared in the java.lang.invoke.MethodHandle class, (ii) takes + * a single variable arity parameter (iii) whose declared type is Object[], + * (iv) has a return type of Object and (v) is native. + */ + public boolean isSignaturePolymorphic(Types types) { + List argtypes = type.getParameterTypes(); + Type firstElemType = argtypes.nonEmpty() ? + types.elemtype(argtypes.head) : + null; + return owner == types.syms.methodHandleType.tsym && + argtypes.length() == 1 && + firstElemType != null && + types.isSameType(firstElemType, types.syms.objectType) && + types.isSameType(type.getReturnType(), types.syms.objectType) && + (flags() & NATIVE) != 0; + } + public Attribute getDefaultValue() { return defaultValue; } diff -r 61eccc72f402 -r 122a0aede750 langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java --- a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java Wed Jul 05 18:07:54 2017 +0200 @@ -127,7 +127,6 @@ public final Type serializableType; public final Type methodHandleType; public final Type nativeHeaderType; - public final Type polymorphicSignatureType; public final Type throwableType; public final Type errorType; public final Type interruptedExceptionType; @@ -436,7 +435,6 @@ throwableType = enterClass("java.lang.Throwable"); serializableType = enterClass("java.io.Serializable"); methodHandleType = enterClass("java.lang.invoke.MethodHandle"); - polymorphicSignatureType = enterClass("java.lang.invoke.MethodHandle$PolymorphicSignature"); errorType = enterClass("java.lang.Error"); illegalArgumentExceptionType = enterClass("java.lang.IllegalArgumentException"); interruptedExceptionType = enterClass("java.lang.InterruptedException"); @@ -483,7 +481,6 @@ synthesizeEmptyInterfaceIfMissing(autoCloseableType); synthesizeEmptyInterfaceIfMissing(cloneableType); synthesizeEmptyInterfaceIfMissing(serializableType); - synthesizeEmptyInterfaceIfMissing(polymorphicSignatureType); synthesizeBoxTypeIfMissing(doubleType); synthesizeBoxTypeIfMissing(floatType); synthesizeBoxTypeIfMissing(voidType); diff -r 61eccc72f402 -r 122a0aede750 langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Wed Jul 05 18:07:54 2017 +0200 @@ -42,6 +42,7 @@ import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.code.Type.*; +import com.sun.tools.javac.comp.Check.CheckContext; import com.sun.source.tree.IdentifierTree; import com.sun.source.tree.MemberSelectTree; @@ -132,6 +133,11 @@ findDiamonds = options.get("findDiamond") != null && source.allowDiamond(); useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning"); + + statInfo = new ResultInfo(NIL, Type.noType); + varInfo = new ResultInfo(VAR, Type.noType); + unknownExprInfo = new ResultInfo(VAL, Type.noType); + unknownTypeInfo = new ResultInfo(TYP, Type.noType); } /** Switch: relax some constraints for retrofit mode. @@ -204,7 +210,7 @@ Type check(JCTree tree, Type owntype, int ownkind, ResultInfo resultInfo) { if (owntype.tag != ERROR && resultInfo.pt.tag != METHOD && resultInfo.pt.tag != FORALL) { if ((ownkind & ~resultInfo.pkind) == 0) { - owntype = chk.checkType(tree.pos(), owntype, resultInfo.pt, errKey); + owntype = resultInfo.check(tree, owntype); } else { log.error(tree.pos(), "unexpected.type", kindNames(resultInfo.pkind), @@ -394,20 +400,30 @@ } } - static class ResultInfo { + class ResultInfo { int pkind; Type pt; + CheckContext checkContext; ResultInfo(int pkind, Type pt) { + this(pkind, pt, chk.basicHandler); + } + + protected ResultInfo(int pkind, Type pt, CheckContext checkContext) { this.pkind = pkind; this.pt = pt; + this.checkContext = checkContext; + } + + protected Type check(DiagnosticPosition pos, Type found) { + return chk.checkType(pos, found, pt, checkContext); } } - private final ResultInfo statInfo = new ResultInfo(NIL, Type.noType); - private final ResultInfo varInfo = new ResultInfo(VAR, Type.noType); - private final ResultInfo unknownExprInfo = new ResultInfo(VAL, Type.noType); - private final ResultInfo unknownTypeInfo = new ResultInfo(TYP, Type.noType); + private final ResultInfo statInfo; + private final ResultInfo varInfo; + private final ResultInfo unknownExprInfo; + private final ResultInfo unknownTypeInfo; Type pt() { return resultInfo.pt; @@ -429,10 +445,6 @@ */ ResultInfo resultInfo; - /** Visitor argument: the error key to be generated when a type error occurs - */ - String errKey; - /** Visitor result: the computed type. */ Type result; @@ -445,17 +457,11 @@ * @param resultInfo The result info visitor argument. */ private Type attribTree(JCTree tree, Env env, ResultInfo resultInfo) { - return attribTree(tree, env, resultInfo, "incompatible.types"); - } - - private Type attribTree(JCTree tree, Env env, ResultInfo resultInfo, String errKey) { Env prevEnv = this.env; ResultInfo prevResult = this.resultInfo; - String prevErrKey = this.errKey; try { this.env = env; this.resultInfo = resultInfo; - this.errKey = errKey; tree.accept(this); if (tree == breakTree) throw new BreakAttr(env); @@ -466,18 +472,13 @@ } finally { this.env = prevEnv; this.resultInfo = prevResult; - this.errKey = prevErrKey; } } /** Derived visitor method: attribute an expression tree. */ public Type attribExpr(JCTree tree, Env env, Type pt) { - return attribExpr(tree, env, pt, "incompatible.types"); - } - - public Type attribExpr(JCTree tree, Env env, Type pt, String key) { - return attribTree(tree, env, new ResultInfo(VAL, pt.tag != ERROR ? pt : Type.noType), key); + return attribTree(tree, env, new ResultInfo(VAL, pt.tag != ERROR ? pt : Type.noType)); } /** Derived visitor method: attribute an expression tree with @@ -1121,9 +1122,16 @@ localEnv; // Attribute resource declarations for (JCTree resource : tree.resources) { + CheckContext twrContext = new Check.NestedCheckContext(resultInfo.checkContext) { + @Override + public void report(DiagnosticPosition pos, Type found, Type req, JCDiagnostic details) { + chk.basicHandler.report(pos, found, req, diags.fragment("try.not.applicable.to.type", found)); + } + }; + ResultInfo twrResult = new ResultInfo(VAL, syms.autoCloseableType, twrContext); if (resource.hasTag(VARDEF)) { attribStat(resource, tryEnv); - chk.checkType(resource, resource.type, syms.autoCloseableType, "try.not.applicable.to.type"); + twrResult.check(resource, resource.type); //check that resource type cannot throw InterruptedException checkAutoCloseable(resource.pos(), localEnv, resource.type); @@ -1131,7 +1139,7 @@ VarSymbol var = (VarSymbol)TreeInfo.symbolFor(resource); var.setData(ElementKind.RESOURCE_VARIABLE); } else { - attribExpr(resource, tryEnv, syms.autoCloseableType, "try.not.applicable.to.type"); + attribTree(resource, tryEnv, twrResult); } } // Attribute body @@ -1846,7 +1854,7 @@ } Type attribDiamond(Env env, - JCNewClass tree, + final JCNewClass tree, Type clazztype, List argtypes, List typeargtypes) { @@ -1886,25 +1894,17 @@ clazztype = syms.errType; } - if (clazztype.tag == FORALL && !pt().isErroneous()) { - //if the resolved constructor's return type has some uninferred - //type-variables, infer them using the expected type and declared - //bounds (JLS 15.12.2.8). + if (clazztype.tag == FORALL && !resultInfo.pt.isErroneous()) { try { - clazztype = infer.instantiateExpr((ForAll) clazztype, - pt().tag == NONE ? syms.objectType : pt(), - Warner.noWarnings); + clazztype = resultInfo.checkContext.rawInstantiatePoly((ForAll)clazztype, pt(), Warner.noWarnings); } catch (Infer.InferenceException ex) { //an error occurred while inferring uninstantiated type-variables - log.error(tree.clazz.pos(), - "cant.apply.diamond.1", - diags.fragment("diamond", clazztype.tsym), - ex.diagnostic); + resultInfo.checkContext.report(tree.clazz.pos(), clazztype, resultInfo.pt, + diags.fragment("cant.apply.diamond.1", diags.fragment("diamond", clazztype.tsym), ex.diagnostic)); } } - return chk.checkClassType(tree.clazz.pos(), - clazztype, - true); + + return chk.checkClassType(tree.clazz.pos(), clazztype, true); } /** Make an attributed null check tree. @@ -2106,6 +2106,7 @@ if (exprtype.constValue() != null) owntype = cfolder.coerce(exprtype, owntype); result = check(tree, capture(owntype), VAL, resultInfo); + chk.checkRedundantCast(localEnv, tree); } public void visitTypeTest(JCInstanceOf tree) { diff -r 61eccc72f402 -r 122a0aede750 langtools/src/share/classes/com/sun/tools/javac/comp/Check.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Wed Jul 05 18:07:54 2017 +0200 @@ -269,23 +269,6 @@ else return syms.errType; } - /** Report a type error. - * @param pos Position to be used for error reporting. - * @param problem A string describing the error. - * @param found The type that was found. - * @param req The type that was required. - */ - Type typeError(DiagnosticPosition pos, Object problem, Type found, Type req) { - log.error(pos, "prob.found.req", - problem, found, req); - return types.createErrorType(found); - } - - Type typeError(DiagnosticPosition pos, String problem, Type found, Type req, Object explanation) { - log.error(pos, "prob.found.req.1", problem, found, req, explanation); - return types.createErrorType(found); - } - /** Report an error that wrong type tag was found. * @param pos Position to be used for error reporting. * @param required An internationalized string describing the type tag @@ -430,6 +413,86 @@ * Type Checking **************************************************************************/ + /** + * A check context is an object that can be used to perform compatibility + * checks - depending on the check context, meaning of 'compatibility' might + * vary significantly. + */ + interface CheckContext { + /** + * Is type 'found' compatible with type 'req' in given context + */ + boolean compatible(Type found, Type req, Warner warn); + /** + * Instantiate a ForAll type against a given target type 'req' in given context + */ + Type rawInstantiatePoly(ForAll found, Type req, Warner warn); + /** + * Report a check error + */ + void report(DiagnosticPosition pos, Type found, Type req, JCDiagnostic details); + /** + * Obtain a warner for this check context + */ + public Warner checkWarner(DiagnosticPosition pos, Type found, Type req); + } + + /** + * This class represent a check context that is nested within another check + * context - useful to check sub-expressions. The default behavior simply + * redirects all method calls to the enclosing check context leveraging + * the forwarding pattern. + */ + static class NestedCheckContext implements CheckContext { + CheckContext enclosingContext; + + NestedCheckContext(CheckContext enclosingContext) { + this.enclosingContext = enclosingContext; + } + + public boolean compatible(Type found, Type req, Warner warn) { + return enclosingContext.compatible(found, req, warn); + } + + public Type rawInstantiatePoly(ForAll found, Type req, Warner warn) { + return enclosingContext.rawInstantiatePoly(found, req, warn); + } + + public void report(DiagnosticPosition pos, Type found, Type req, JCDiagnostic details) { + enclosingContext.report(pos, found, req, details); + } + + public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { + return enclosingContext.checkWarner(pos, found, req); + } + } + + /** + * Check context to be used when evaluating assignment/return statements + */ + CheckContext basicHandler = new CheckContext() { + public void report(DiagnosticPosition pos, Type found, Type req, JCDiagnostic details) { + if (details == null) { + log.error(pos, "prob.found.req", found, req); + } else { + log.error(pos, "prob.found.req.1", details); + } + } + public boolean compatible(Type found, Type req, Warner warn) { + return types.isAssignable(found, req, warn); + } + + public Type rawInstantiatePoly(ForAll found, Type req, Warner warn) { + if (req.tag == NONE) + req = found.qtype.tag <= VOID ? found.qtype : syms.objectType; + return infer.instantiateExpr(found, req, warn); + } + + public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { + return convertWarner(pos, found, req); + } + }; + /** Check that a given type is assignable to a given proto-type. * If it is, return the type, otherwise return errType. * @param pos Position to be used for error reporting. @@ -437,64 +500,54 @@ * @param req The type that was required. */ Type checkType(DiagnosticPosition pos, Type found, Type req) { - return checkType(pos, found, req, "incompatible.types"); + return checkType(pos, found, req, basicHandler); } - Type checkType(DiagnosticPosition pos, Type found, Type req, String errKey) { + Type checkType(final DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) { if (req.tag == ERROR) return req; - if (found.tag == FORALL) - return instantiatePoly(pos, (ForAll)found, req, convertWarner(pos, found, req)); + if (found.tag == FORALL) { + ForAll fa = (ForAll)found; + Type owntype = instantiatePoly(pos, checkContext, fa, req, checkContext.checkWarner(pos, found, req)); + return checkType(pos, owntype, req, checkContext); + } if (req.tag == NONE) return found; - if (types.isAssignable(found, req, convertWarner(pos, found, req))) + if (checkContext.compatible(found, req, checkContext.checkWarner(pos, found, req))) { return found; - if (found.tag <= DOUBLE && req.tag <= DOUBLE) - return typeError(pos, diags.fragment("possible.loss.of.precision"), found, req); - if (found.isSuperBound()) { - log.error(pos, "assignment.from.super-bound", found); + } else { + if (found.tag <= DOUBLE && req.tag <= DOUBLE) { + checkContext.report(pos, found, req, diags.fragment("possible.loss.of.precision")); + return types.createErrorType(found); + } + checkContext.report(pos, found, req, null); return types.createErrorType(found); } - if (req.isExtendsBound()) { - log.error(pos, "assignment.to.extends-bound", req); - return types.createErrorType(found); - } - return typeError(pos, diags.fragment(errKey), found, req); } /** Instantiate polymorphic type to some prototype, unless * prototype is `anyPoly' in which case polymorphic type * is returned unchanged. */ - Type instantiatePoly(DiagnosticPosition pos, ForAll t, Type pt, Warner warn) throws Infer.NoInstanceException { - if (pt == Infer.anyPoly && complexInference) { - return t; - } else if (pt == Infer.anyPoly || pt.tag == NONE) { - Type newpt = t.qtype.tag <= VOID ? t.qtype : syms.objectType; - return instantiatePoly(pos, t, newpt, warn); - } else if (pt.tag == ERROR) { - return pt; - } else { - try { - return infer.instantiateExpr(t, pt, warn); - } catch (Infer.NoInstanceException ex) { + Type instantiatePoly(DiagnosticPosition pos, CheckContext checkContext, ForAll t, Type pt, Warner warn) throws Infer.NoInstanceException { + try { + return checkContext.rawInstantiatePoly(t, pt, warn); + } catch (final Infer.NoInstanceException ex) { + JCDiagnostic d = ex.getDiagnostic(); + if (d != null) { if (ex.isAmbiguous) { - JCDiagnostic d = ex.getDiagnostic(); - log.error(pos, - "undetermined.type" + (d!=null ? ".1" : ""), - t, d); - return types.createErrorType(pt); - } else { - JCDiagnostic d = ex.getDiagnostic(); - return typeError(pos, - diags.fragment("incompatible.types" + (d!=null ? ".1" : ""), d), - t, pt); + d = diags.fragment("undetermined.type", t, d); } - } catch (Infer.InvalidInstanceException ex) { - JCDiagnostic d = ex.getDiagnostic(); - log.error(pos, "invalid.inferred.types", t.tvars, d); - return types.createErrorType(pt); } + checkContext.report(pos, t, pt, d); + return types.createErrorType(pt); + } catch (Infer.InvalidInstanceException ex) { + JCDiagnostic d = ex.getDiagnostic(); + if (d != null) { + d = diags.fragment("invalid.inferred.types", t.tvars, d); + } + checkContext.report(pos, t, pt, d); + return types.createErrorType(pt); } } @@ -505,17 +558,48 @@ * @param req The target type of the cast. */ Type checkCastable(DiagnosticPosition pos, Type found, Type req) { + return checkCastable(pos, found, req, basicHandler); + } + Type checkCastable(DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) { if (found.tag == FORALL) { - instantiatePoly(pos, (ForAll) found, req, castWarner(pos, found, req)); + instantiatePoly(pos, basicHandler, (ForAll) found, req, castWarner(pos, found, req)); return req; } else if (types.isCastable(found, req, castWarner(pos, found, req))) { return req; } else { - return typeError(pos, - diags.fragment("inconvertible.types"), - found, req); + checkContext.report(pos, found, req, diags.fragment("inconvertible.types", found, req)); + return types.createErrorType(found); + } + } + + /** Check for redundant casts (i.e. where source type is a subtype of target type) + * The problem should only be reported for non-292 cast + */ + public void checkRedundantCast(Env env, JCTypeCast tree) { + if (!tree.type.isErroneous() && + (env.info.lint == null || env.info.lint.isEnabled(Lint.LintCategory.CAST)) + && types.isSameType(tree.expr.type, tree.clazz.type) + && !is292targetTypeCast(tree)) { + log.warning(Lint.LintCategory.CAST, + tree.pos(), "redundant.cast", tree.expr.type); } } + //where + private boolean is292targetTypeCast(JCTypeCast tree) { + boolean is292targetTypeCast = false; + JCExpression expr = TreeInfo.skipParens(tree.expr); + if (expr.hasTag(APPLY)) { + JCMethodInvocation apply = (JCMethodInvocation)expr; + Symbol sym = TreeInfo.symbol(apply.meth); + is292targetTypeCast = sym != null && + sym.kind == MTH && + (sym.flags() & HYPOTHETICAL) != 0; + } + return is292targetTypeCast; + } + + + //where /** Is type a type variable, or a (possibly multi-dimensional) array of * type variables? @@ -838,14 +922,6 @@ && types.isSubtype(actual, types.supertype(formal)) && types.isSubtypeUnchecked(actual, types.interfaces(formal), warn)) return; - - if (false) { - // TODO: make assertConvertible work - typeError(tree.pos(), diags.fragment("incompatible.types"), actual, formal); - throw new AssertionError("Tree: " + tree - + " actual:" + actual - + " formal: " + formal); - } } /** diff -r 61eccc72f402 -r 122a0aede750 langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java Wed Jul 05 18:07:54 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, 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 @@ -28,8 +28,6 @@ package com.sun.tools.javac.comp; import java.util.HashMap; -import java.util.Map; -import java.util.LinkedHashMap; import com.sun.tools.javac.code.*; import com.sun.tools.javac.tree.*; @@ -179,7 +177,7 @@ * This code and its internal interfaces are subject to change or * deletion without notice. */ -public class Flow extends TreeScanner { +public class Flow { protected static final Context.Key flowKey = new Context.Key(); @@ -202,6 +200,11 @@ return instance; } + public void analyzeTree(Env env, TreeMaker make) { + new FlowAnalyzer().analyzeTree(env, make); + new AssignAnalyzer().analyzeTree(env, make); + } + protected Flow(Context context) { context.put(flowKey, this); names = Names.instance(context); @@ -216,1268 +219,1572 @@ allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis(); } - /** A flag that indicates whether the last statement could - * complete normally. - */ - private boolean alive; - - /** The set of definitely assigned variables. - */ - Bits inits; - - /** The set of definitely unassigned variables. - */ - Bits uninits; - - HashMap> preciseRethrowTypes; - - /** The set of variables that are definitely unassigned everywhere - * in current try block. This variable is maintained lazily; it is - * updated only when something gets removed from uninits, - * typically by being assigned in reachable code. To obtain the - * correct set of variables which are definitely unassigned - * anywhere in current try block, intersect uninitsTry and - * uninits. - */ - Bits uninitsTry; - - /** When analyzing a condition, inits and uninits are null. - * Instead we have: - */ - Bits initsWhenTrue; - Bits initsWhenFalse; - Bits uninitsWhenTrue; - Bits uninitsWhenFalse; - - /** A mapping from addresses to variable symbols. - */ - VarSymbol[] vars; - - /** The current class being defined. - */ - JCClassDecl classDef; - - /** The first variable sequence number in this class definition. + /** + * Base visitor class for all visitors implementing dataflow analysis logic. + * This class define the shared logic for handling jumps (break/continue statements). */ - int firstadr; + static abstract class BaseAnalyzer

extends TreeScanner { - /** The next available variable sequence number. - */ - int nextadr; + enum JumpKind { + BREAK(JCTree.Tag.BREAK) { + @Override + JCTree getTarget(JCTree tree) { + return ((JCBreak)tree).target; + } + }, + CONTINUE(JCTree.Tag.CONTINUE) { + @Override + JCTree getTarget(JCTree tree) { + return ((JCContinue)tree).target; + } + }; - /** The list of possibly thrown declarable exceptions. - */ - List thrown; + JCTree.Tag treeTag; - /** The list of exceptions that are either caught or declared to be - * thrown. - */ - List caught; + private JumpKind(Tag treeTag) { + this.treeTag = treeTag; + } + + abstract JCTree getTarget(JCTree tree); + } - /** The list of unreferenced automatic resources. - */ - Scope unrefdResources; + /** The currently pending exits that go from current inner blocks + * to an enclosing block, in source order. + */ + ListBuffer

pendingExits; - /** Set when processing a loop body the second time for DU analysis. */ - boolean loopPassTwo = false; + /** A pending exit. These are the statements return, break, and + * continue. In addition, exception-throwing expressions or + * statements are put here when not known to be caught. This + * will typically result in an error unless it is within a + * try-finally whose finally block cannot complete normally. + */ + abstract static class PendingExit { + JCTree tree; - /*-------------------- Environments ----------------------*/ + PendingExit(JCTree tree) { + this.tree = tree; + } + + abstract void resolveJump(); + } + + abstract void markDead(); + + /** Record an outward transfer of control. */ + void recordExit(JCTree tree, P pe) { + pendingExits.append(pe); + markDead(); + } - /** A pending exit. These are the statements return, break, and - * continue. In addition, exception-throwing expressions or - * statements are put here when not known to be caught. This - * will typically result in an error unless it is within a - * try-finally whose finally block cannot complete normally. - */ - static class PendingExit { - JCTree tree; - Bits inits; - Bits uninits; - Type thrown; - PendingExit(JCTree tree, Bits inits, Bits uninits) { - this.tree = tree; - this.inits = inits.dup(); - this.uninits = uninits.dup(); + /** Resolve all jumps of this statement. */ + private boolean resolveJump(JCTree tree, + ListBuffer

oldPendingExits, + JumpKind jk) { + boolean resolved = false; + List

exits = pendingExits.toList(); + pendingExits = oldPendingExits; + for (; exits.nonEmpty(); exits = exits.tail) { + P exit = exits.head; + if (exit.tree.hasTag(jk.treeTag) && + jk.getTarget(exit.tree) == tree) { + exit.resolveJump(); + resolved = true; + } else { + pendingExits.append(exit); + } + } + return resolved; } - PendingExit(JCTree tree, Type thrown) { - this.tree = tree; - this.thrown = thrown; + + /** Resolve all breaks of this statement. */ + boolean resolveContinues(JCTree tree) { + return resolveJump(tree, new ListBuffer

(), JumpKind.CONTINUE); + } + + /** Resolve all continues of this statement. */ + boolean resolveBreaks(JCTree tree, ListBuffer

oldPendingExits) { + return resolveJump(tree, oldPendingExits, JumpKind.BREAK); } } - /** The currently pending exits that go from current inner blocks - * to an enclosing block, in source order. - */ - ListBuffer pendingExits; - - /*-------------------- Exceptions ----------------------*/ - - /** Complain that pending exceptions are not caught. + /** + * This pass implements the first two steps of the dataflow analysis: + * (i) liveness analysis checks that every statement is reachable and (ii) + * exception analysis to ensure that every checked exception that is + * thrown is declared or caught. */ - void errorUncaught() { - for (PendingExit exit = pendingExits.next(); - exit != null; - exit = pendingExits.next()) { - if (classDef != null && - classDef.pos == exit.tree.pos) { - log.error(exit.tree.pos(), - "unreported.exception.default.constructor", - exit.thrown); - } else if (exit.tree.hasTag(VARDEF) && - ((JCVariableDecl)exit.tree).sym.isResourceVariable()) { - log.error(exit.tree.pos(), - "unreported.exception.implicit.close", - exit.thrown, - ((JCVariableDecl)exit.tree).sym.name); - } else { - log.error(exit.tree.pos(), - "unreported.exception.need.to.catch.or.throw", - exit.thrown); + class FlowAnalyzer extends BaseAnalyzer { + + /** A flag that indicates whether the last statement could + * complete normally. + */ + private boolean alive; + + HashMap> preciseRethrowTypes; + + /** The current class being defined. + */ + JCClassDecl classDef; + + /** The list of possibly thrown declarable exceptions. + */ + List thrown; + + /** The list of exceptions that are either caught or declared to be + * thrown. + */ + List caught; + + class FlowPendingExit extends BaseAnalyzer.PendingExit { + + Type thrown; + + FlowPendingExit(JCTree tree, Type thrown) { + super(tree); + this.thrown = thrown; + } + + void resolveJump() { /*do nothing*/ } + } + + @Override + void markDead() { + alive = false; + } + + /*-------------------- Exceptions ----------------------*/ + + /** Complain that pending exceptions are not caught. + */ + void errorUncaught() { + for (FlowPendingExit exit = pendingExits.next(); + exit != null; + exit = pendingExits.next()) { + if (classDef != null && + classDef.pos == exit.tree.pos) { + log.error(exit.tree.pos(), + "unreported.exception.default.constructor", + exit.thrown); + } else if (exit.tree.hasTag(VARDEF) && + ((JCVariableDecl)exit.tree).sym.isResourceVariable()) { + log.error(exit.tree.pos(), + "unreported.exception.implicit.close", + exit.thrown, + ((JCVariableDecl)exit.tree).sym.name); + } else { + log.error(exit.tree.pos(), + "unreported.exception.need.to.catch.or.throw", + exit.thrown); + } + } + } + + /** Record that exception is potentially thrown and check that it + * is caught. + */ + void markThrown(JCTree tree, Type exc) { + if (!chk.isUnchecked(tree.pos(), exc)) { + if (!chk.isHandled(exc, caught)) + pendingExits.append(new FlowPendingExit(tree, exc)); + thrown = chk.incl(exc, thrown); + } + } + + /************************************************************************* + * Visitor methods for statements and definitions + *************************************************************************/ + + /** Analyze a definition. + */ + void scanDef(JCTree tree) { + scanStat(tree); + if (tree != null && tree.hasTag(JCTree.Tag.BLOCK) && !alive) { + log.error(tree.pos(), + "initializer.must.be.able.to.complete.normally"); + } + } + + /** Analyze a statement. Check that statement is reachable. + */ + void scanStat(JCTree tree) { + if (!alive && tree != null) { + log.error(tree.pos(), "unreachable.stmt"); + if (!tree.hasTag(SKIP)) alive = true; + } + scan(tree); + } + + /** Analyze list of statements. + */ + void scanStats(List trees) { + if (trees != null) + for (List l = trees; l.nonEmpty(); l = l.tail) + scanStat(l.head); + } + + /* ------------ Visitor methods for various sorts of trees -------------*/ + + public void visitClassDef(JCClassDecl tree) { + if (tree.sym == null) return; + + JCClassDecl classDefPrev = classDef; + List thrownPrev = thrown; + List caughtPrev = caught; + boolean alivePrev = alive; + ListBuffer pendingExitsPrev = pendingExits; + Lint lintPrev = lint; + + pendingExits = new ListBuffer(); + if (tree.name != names.empty) { + caught = List.nil(); + } + classDef = tree; + thrown = List.nil(); + lint = lint.augment(tree.sym.attributes_field); + + try { + // process all the static initializers + for (List l = tree.defs; l.nonEmpty(); l = l.tail) { + if (!l.head.hasTag(METHODDEF) && + (TreeInfo.flags(l.head) & STATIC) != 0) { + scanDef(l.head); + errorUncaught(); + } + } + + // add intersection of all thrown clauses of initial constructors + // to set of caught exceptions, unless class is anonymous. + if (tree.name != names.empty) { + boolean firstConstructor = true; + for (List l = tree.defs; l.nonEmpty(); l = l.tail) { + if (TreeInfo.isInitialConstructor(l.head)) { + List mthrown = + ((JCMethodDecl) l.head).sym.type.getThrownTypes(); + if (firstConstructor) { + caught = mthrown; + firstConstructor = false; + } else { + caught = chk.intersect(mthrown, caught); + } + } + } + } + + // process all the instance initializers + for (List l = tree.defs; l.nonEmpty(); l = l.tail) { + if (!l.head.hasTag(METHODDEF) && + (TreeInfo.flags(l.head) & STATIC) == 0) { + scanDef(l.head); + errorUncaught(); + } + } + + // in an anonymous class, add the set of thrown exceptions to + // the throws clause of the synthetic constructor and propagate + // outwards. + // Changing the throws clause on the fly is okay here because + // the anonymous constructor can't be invoked anywhere else, + // and its type hasn't been cached. + if (tree.name == names.empty) { + for (List l = tree.defs; l.nonEmpty(); l = l.tail) { + if (TreeInfo.isInitialConstructor(l.head)) { + JCMethodDecl mdef = (JCMethodDecl)l.head; + mdef.thrown = make.Types(thrown); + mdef.sym.type = types.createMethodTypeWithThrown(mdef.sym.type, thrown); + } + } + thrownPrev = chk.union(thrown, thrownPrev); + } + + // process all the methods + for (List l = tree.defs; l.nonEmpty(); l = l.tail) { + if (l.head.hasTag(METHODDEF)) { + scan(l.head); + errorUncaught(); + } + } + + thrown = thrownPrev; + } finally { + pendingExits = pendingExitsPrev; + alive = alivePrev; + caught = caughtPrev; + classDef = classDefPrev; + lint = lintPrev; + } + } + + public void visitMethodDef(JCMethodDecl tree) { + if (tree.body == null) return; + + List caughtPrev = caught; + List mthrown = tree.sym.type.getThrownTypes(); + Lint lintPrev = lint; + + lint = lint.augment(tree.sym.attributes_field); + + Assert.check(pendingExits.isEmpty()); + + try { + for (List l = tree.params; l.nonEmpty(); l = l.tail) { + JCVariableDecl def = l.head; + scan(def); + } + if (TreeInfo.isInitialConstructor(tree)) + caught = chk.union(caught, mthrown); + else if ((tree.sym.flags() & (BLOCK | STATIC)) != BLOCK) + caught = mthrown; + // else we are in an instance initializer block; + // leave caught unchanged. + + alive = true; + scanStat(tree.body); + + if (alive && tree.sym.type.getReturnType().tag != VOID) + log.error(TreeInfo.diagEndPos(tree.body), "missing.ret.stmt"); + + List exits = pendingExits.toList(); + pendingExits = new ListBuffer(); + while (exits.nonEmpty()) { + FlowPendingExit exit = exits.head; + exits = exits.tail; + if (exit.thrown == null) { + Assert.check(exit.tree.hasTag(RETURN)); + } else { + // uncaught throws will be reported later + pendingExits.append(exit); + } + } + } finally { + caught = caughtPrev; + lint = lintPrev; + } + } + + public void visitVarDef(JCVariableDecl tree) { + if (tree.init != null) { + Lint lintPrev = lint; + lint = lint.augment(tree.sym.attributes_field); + try{ + scan(tree.init); + } finally { + lint = lintPrev; + } } } - } + + public void visitBlock(JCBlock tree) { + scanStats(tree.stats); + } - /** Record that exception is potentially thrown and check that it - * is caught. - */ - void markThrown(JCTree tree, Type exc) { - if (!chk.isUnchecked(tree.pos(), exc)) { - if (!chk.isHandled(exc, caught)) - pendingExits.append(new PendingExit(tree, exc)); - thrown = chk.incl(exc, thrown); + public void visitDoLoop(JCDoWhileLoop tree) { + ListBuffer prevPendingExits = pendingExits; + pendingExits = new ListBuffer(); + scanStat(tree.body); + alive |= resolveContinues(tree); + scan(tree.cond); + alive = alive && !tree.cond.type.isTrue(); + alive |= resolveBreaks(tree, prevPendingExits); } - } - /*-------------- Processing variables ----------------------*/ + public void visitWhileLoop(JCWhileLoop tree) { + ListBuffer prevPendingExits = pendingExits; + pendingExits = new ListBuffer(); + scan(tree.cond); + alive = !tree.cond.type.isFalse(); + scanStat(tree.body); + alive |= resolveContinues(tree); + alive = resolveBreaks(tree, prevPendingExits) || + !tree.cond.type.isTrue(); + } - /** Do we need to track init/uninit state of this symbol? - * I.e. is symbol either a local or a blank final variable? - */ - boolean trackable(VarSymbol sym) { - return - (sym.owner.kind == MTH || - ((sym.flags() & (FINAL | HASINIT | PARAMETER)) == FINAL && - classDef.sym.isEnclosedBy((ClassSymbol)sym.owner))); - } + public void visitForLoop(JCForLoop tree) { + ListBuffer prevPendingExits = pendingExits; + scanStats(tree.init); + pendingExits = new ListBuffer(); + if (tree.cond != null) { + scan(tree.cond); + alive = !tree.cond.type.isFalse(); + } else { + alive = true; + } + scanStat(tree.body); + alive |= resolveContinues(tree); + scan(tree.step); + alive = resolveBreaks(tree, prevPendingExits) || + tree.cond != null && !tree.cond.type.isTrue(); + } - /** Initialize new trackable variable by setting its address field - * to the next available sequence number and entering it under that - * index into the vars array. - */ - void newVar(VarSymbol sym) { - if (nextadr == vars.length) { - VarSymbol[] newvars = new VarSymbol[nextadr * 2]; - System.arraycopy(vars, 0, newvars, 0, nextadr); - vars = newvars; + public void visitForeachLoop(JCEnhancedForLoop tree) { + visitVarDef(tree.var); + ListBuffer prevPendingExits = pendingExits; + scan(tree.expr); + pendingExits = new ListBuffer(); + scanStat(tree.body); + alive |= resolveContinues(tree); + resolveBreaks(tree, prevPendingExits); + alive = true; + } + + public void visitLabelled(JCLabeledStatement tree) { + ListBuffer prevPendingExits = pendingExits; + pendingExits = new ListBuffer(); + scanStat(tree.body); + alive |= resolveBreaks(tree, prevPendingExits); } - sym.adr = nextadr; - vars[nextadr] = sym; - inits.excl(nextadr); - uninits.incl(nextadr); - nextadr++; - } + + public void visitSwitch(JCSwitch tree) { + ListBuffer prevPendingExits = pendingExits; + pendingExits = new ListBuffer(); + scan(tree.selector); + boolean hasDefault = false; + for (List l = tree.cases; l.nonEmpty(); l = l.tail) { + alive = true; + JCCase c = l.head; + if (c.pat == null) + hasDefault = true; + else + scan(c.pat); + scanStats(c.stats); + // Warn about fall-through if lint switch fallthrough enabled. + if (alive && + lint.isEnabled(Lint.LintCategory.FALLTHROUGH) && + c.stats.nonEmpty() && l.tail.nonEmpty()) + log.warning(Lint.LintCategory.FALLTHROUGH, + l.tail.head.pos(), + "possible.fall-through.into.case"); + } + if (!hasDefault) { + alive = true; + } + alive |= resolveBreaks(tree, prevPendingExits); + } - /** Record an initialization of a trackable variable. - */ - void letInit(DiagnosticPosition pos, VarSymbol sym) { - if (sym.adr >= firstadr && trackable(sym)) { - if ((sym.flags() & FINAL) != 0) { - if ((sym.flags() & PARAMETER) != 0) { - if ((sym.flags() & UNION) != 0) { //multi-catch parameter - log.error(pos, "multicatch.parameter.may.not.be.assigned", - sym); + public void visitTry(JCTry tree) { + List caughtPrev = caught; + List thrownPrev = thrown; + thrown = List.nil(); + for (List l = tree.catchers; l.nonEmpty(); l = l.tail) { + List subClauses = TreeInfo.isMultiCatch(l.head) ? + ((JCTypeUnion)l.head.param.vartype).alternatives : + List.of(l.head.param.vartype); + for (JCExpression ct : subClauses) { + caught = chk.incl(ct.type, caught); + } + } + + ListBuffer prevPendingExits = pendingExits; + pendingExits = new ListBuffer(); + for (JCTree resource : tree.resources) { + if (resource instanceof JCVariableDecl) { + JCVariableDecl vdecl = (JCVariableDecl) resource; + visitVarDef(vdecl); + } else if (resource instanceof JCExpression) { + scan((JCExpression) resource); + } else { + throw new AssertionError(tree); // parser error + } + } + for (JCTree resource : tree.resources) { + List closeableSupertypes = resource.type.isCompound() ? + types.interfaces(resource.type).prepend(types.supertype(resource.type)) : + List.of(resource.type); + for (Type sup : closeableSupertypes) { + if (types.asSuper(sup, syms.autoCloseableType.tsym) != null) { + Symbol closeMethod = rs.resolveQualifiedMethod(tree, + attrEnv, + sup, + names.close, + List.nil(), + List.nil()); + if (closeMethod.kind == MTH) { + for (Type t : ((MethodSymbol)closeMethod).getThrownTypes()) { + markThrown(resource, t); + } + } } - else { - log.error(pos, "final.parameter.may.not.be.assigned", - sym); - } - } else if (!uninits.isMember(sym.adr)) { - log.error(pos, - loopPassTwo - ? "var.might.be.assigned.in.loop" - : "var.might.already.be.assigned", - sym); - } else if (!inits.isMember(sym.adr)) { - // reachable assignment - uninits.excl(sym.adr); - uninitsTry.excl(sym.adr); - } else { - //log.rawWarning(pos, "unreachable assignment");//DEBUG - uninits.excl(sym.adr); } } - inits.incl(sym.adr); - } else if ((sym.flags() & FINAL) != 0) { - log.error(pos, "var.might.already.be.assigned", sym); + scanStat(tree.body); + List thrownInTry = allowImprovedCatchAnalysis ? + chk.union(thrown, List.of(syms.runtimeExceptionType, syms.errorType)) : + thrown; + thrown = thrownPrev; + caught = caughtPrev; + boolean aliveEnd = alive; + + List caughtInTry = List.nil(); + for (List l = tree.catchers; l.nonEmpty(); l = l.tail) { + alive = true; + JCVariableDecl param = l.head.param; + List subClauses = TreeInfo.isMultiCatch(l.head) ? + ((JCTypeUnion)l.head.param.vartype).alternatives : + List.of(l.head.param.vartype); + List ctypes = List.nil(); + List rethrownTypes = chk.diff(thrownInTry, caughtInTry); + for (JCExpression ct : subClauses) { + Type exc = ct.type; + if (exc != syms.unknownType) { + ctypes = ctypes.append(exc); + if (types.isSameType(exc, syms.objectType)) + continue; + checkCaughtType(l.head.pos(), exc, thrownInTry, caughtInTry); + caughtInTry = chk.incl(exc, caughtInTry); + } + } + scan(param); + preciseRethrowTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes)); + scanStat(l.head.body); + preciseRethrowTypes.remove(param.sym); + aliveEnd |= alive; + } + if (tree.finalizer != null) { + List savedThrown = thrown; + thrown = List.nil(); + ListBuffer exits = pendingExits; + pendingExits = prevPendingExits; + alive = true; + scanStat(tree.finalizer); + if (!alive) { + // discard exits and exceptions from try and finally + thrown = chk.union(thrown, thrownPrev); + if (lint.isEnabled(Lint.LintCategory.FINALLY)) { + log.warning(Lint.LintCategory.FINALLY, + TreeInfo.diagEndPos(tree.finalizer), + "finally.cannot.complete"); + } + } else { + thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry)); + thrown = chk.union(thrown, savedThrown); + // FIX: this doesn't preserve source order of exits in catch + // versus finally! + while (exits.nonEmpty()) { + pendingExits.append(exits.next()); + } + alive = aliveEnd; + } + tree.finallyCanCompleteNormally = alive; + } else { + thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry)); + alive = aliveEnd; + ListBuffer exits = pendingExits; + pendingExits = prevPendingExits; + while (exits.nonEmpty()) pendingExits.append(exits.next()); + } } - } + + @Override + public void visitIf(JCIf tree) { + scan(tree.cond); + scanStat(tree.thenpart); + if (tree.elsepart != null) { + boolean aliveAfterThen = alive; + alive = true; + scanStat(tree.elsepart); + alive = alive | aliveAfterThen; + } else { + alive = true; + } + } - /** If tree is either a simple name or of the form this.name or - * C.this.name, and tree represents a trackable variable, - * record an initialization of the variable. - */ - void letInit(JCTree tree) { - tree = TreeInfo.skipParens(tree); - if (tree.hasTag(IDENT) || tree.hasTag(SELECT)) { - Symbol sym = TreeInfo.symbol(tree); - if (sym.kind == VAR) { - letInit(tree.pos(), (VarSymbol)sym); + void checkCaughtType(DiagnosticPosition pos, Type exc, List thrownInTry, List caughtInTry) { + if (chk.subset(exc, caughtInTry)) { + log.error(pos, "except.already.caught", exc); + } else if (!chk.isUnchecked(pos, exc) && + !isExceptionOrThrowable(exc) && + !chk.intersects(exc, thrownInTry)) { + log.error(pos, "except.never.thrown.in.try", exc); + } else if (allowImprovedCatchAnalysis) { + List catchableThrownTypes = chk.intersect(List.of(exc), thrownInTry); + // 'catchableThrownTypes' cannnot possibly be empty - if 'exc' was an + // unchecked exception, the result list would not be empty, as the augmented + // thrown set includes { RuntimeException, Error }; if 'exc' was a checked + // exception, that would have been covered in the branch above + if (chk.diff(catchableThrownTypes, caughtInTry).isEmpty() && + !isExceptionOrThrowable(exc)) { + String key = catchableThrownTypes.length() == 1 ? + "unreachable.catch" : + "unreachable.catch.1"; + log.warning(pos, key, catchableThrownTypes); + } + } + } + //where + private boolean isExceptionOrThrowable(Type exc) { + return exc.tsym == syms.throwableType.tsym || + exc.tsym == syms.exceptionType.tsym; + } + + public void visitBreak(JCBreak tree) { + recordExit(tree, new FlowPendingExit(tree, null)); + } + + public void visitContinue(JCContinue tree) { + recordExit(tree, new FlowPendingExit(tree, null)); + } + + public void visitReturn(JCReturn tree) { + scan(tree.expr); + // if not initial constructor, should markDead instead of recordExit + recordExit(tree, new FlowPendingExit(tree, null)); + } + + public void visitThrow(JCThrow tree) { + scan(tree.expr); + Symbol sym = TreeInfo.symbol(tree.expr); + if (sym != null && + sym.kind == VAR && + (sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 && + preciseRethrowTypes.get(sym) != null && + allowImprovedRethrowAnalysis) { + for (Type t : preciseRethrowTypes.get(sym)) { + markThrown(tree, t); + } + } + else { + markThrown(tree, tree.expr.type); + } + markDead(); + } + + public void visitApply(JCMethodInvocation tree) { + scan(tree.meth); + scan(tree.args); + for (List l = tree.meth.type.getThrownTypes(); l.nonEmpty(); l = l.tail) + markThrown(tree, l.head); + } + + public void visitNewClass(JCNewClass tree) { + scan(tree.encl); + scan(tree.args); + // scan(tree.def); + for (List l = tree.constructorType.getThrownTypes(); + l.nonEmpty(); + l = l.tail) { + markThrown(tree, l.head); + } + List caughtPrev = caught; + try { + // If the new class expression defines an anonymous class, + // analysis of the anonymous constructor may encounter thrown + // types which are unsubstituted type variables. + // However, since the constructor's actual thrown types have + // already been marked as thrown, it is safe to simply include + // each of the constructor's formal thrown types in the set of + // 'caught/declared to be thrown' types, for the duration of + // the class def analysis. + if (tree.def != null) + for (List l = tree.constructor.type.getThrownTypes(); + l.nonEmpty(); + l = l.tail) { + caught = chk.incl(l.head, caught); + } + scan(tree.def); + } + finally { + caught = caughtPrev; + } + } + + public void visitTopLevel(JCCompilationUnit tree) { + // Do nothing for TopLevel since each class is visited individually + } + + /************************************************************************** + * main method + *************************************************************************/ + + /** Perform definite assignment/unassignment analysis on a tree. + */ + public void analyzeTree(Env env, TreeMaker make) { + try { + attrEnv = env; + JCTree tree = env.tree; + Flow.this.make = make; + pendingExits = new ListBuffer(); + preciseRethrowTypes = new HashMap>(); + alive = true; + this.thrown = this.caught = null; + this.classDef = null; + scan(tree); + } finally { + pendingExits = null; + Flow.this.make = null; + this.thrown = this.caught = null; + this.classDef = null; } } } - /** Check that trackable variable is initialized. + /** + * This pass implements (i) definite assignment analysis, which ensures that + * each variable is assigned when used and (ii) definite unassignment analysis, + * which ensures that no final variable is assigned more than once. This visitor + * depends on the results of the liveliness analyzer. */ - void checkInit(DiagnosticPosition pos, VarSymbol sym) { - if ((sym.adr >= firstadr || sym.owner.kind != TYP) && - trackable(sym) && - !inits.isMember(sym.adr)) { - log.error(pos, "var.might.not.have.been.initialized", - sym); - inits.incl(sym.adr); - } - } + class AssignAnalyzer extends BaseAnalyzer { + + /** The set of definitely assigned variables. + */ + Bits inits; + + /** The set of definitely unassigned variables. + */ + Bits uninits; - /*-------------------- Handling jumps ----------------------*/ + /** The set of variables that are definitely unassigned everywhere + * in current try block. This variable is maintained lazily; it is + * updated only when something gets removed from uninits, + * typically by being assigned in reachable code. To obtain the + * correct set of variables which are definitely unassigned + * anywhere in current try block, intersect uninitsTry and + * uninits. + */ + Bits uninitsTry; - /** Record an outward transfer of control. */ - void recordExit(JCTree tree) { - pendingExits.append(new PendingExit(tree, inits, uninits)); - markDead(); - } + /** When analyzing a condition, inits and uninits are null. + * Instead we have: + */ + Bits initsWhenTrue; + Bits initsWhenFalse; + Bits uninitsWhenTrue; + Bits uninitsWhenFalse; - /** Resolve all breaks of this statement. */ - boolean resolveBreaks(JCTree tree, - ListBuffer oldPendingExits) { - boolean result = false; - List exits = pendingExits.toList(); - pendingExits = oldPendingExits; - for (; exits.nonEmpty(); exits = exits.tail) { - PendingExit exit = exits.head; - if (exit.tree.hasTag(BREAK) && - ((JCBreak) exit.tree).target == tree) { - inits.andSet(exit.inits); - uninits.andSet(exit.uninits); - result = true; - } else { - pendingExits.append(exit); + /** A mapping from addresses to variable symbols. + */ + VarSymbol[] vars; + + /** The current class being defined. + */ + JCClassDecl classDef; + + /** The first variable sequence number in this class definition. + */ + int firstadr; + + /** The next available variable sequence number. + */ + int nextadr; + + /** The list of unreferenced automatic resources. + */ + Scope unrefdResources; + + /** Set when processing a loop body the second time for DU analysis. */ + boolean loopPassTwo = false; + + class AssignPendingExit extends BaseAnalyzer.PendingExit { + + Bits exit_inits; + Bits exit_uninits; + + AssignPendingExit(JCTree tree, Bits inits, Bits uninits) { + super(tree); + this.exit_inits = inits.dup(); + this.exit_uninits = uninits.dup(); } - } - return result; - } - /** Resolve all continues of this statement. */ - boolean resolveContinues(JCTree tree) { - boolean result = false; - List exits = pendingExits.toList(); - pendingExits = new ListBuffer(); - for (; exits.nonEmpty(); exits = exits.tail) { - PendingExit exit = exits.head; - if (exit.tree.hasTag(CONTINUE) && - ((JCContinue) exit.tree).target == tree) { - inits.andSet(exit.inits); - uninits.andSet(exit.uninits); - result = true; - } else { - pendingExits.append(exit); + void resolveJump() { + inits.andSet(exit_inits); + uninits.andSet(exit_uninits); } } - return result; - } - /** Record that statement is unreachable. - */ - void markDead() { - inits.inclRange(firstadr, nextadr); - uninits.inclRange(firstadr, nextadr); - alive = false; - } + @Override + void markDead() { + inits.inclRange(firstadr, nextadr); + uninits.inclRange(firstadr, nextadr); + } + + /*-------------- Processing variables ----------------------*/ - /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets - */ - void split(boolean setToNull) { - initsWhenFalse = inits.dup(); - uninitsWhenFalse = uninits.dup(); - initsWhenTrue = inits; - uninitsWhenTrue = uninits; - if (setToNull) - inits = uninits = null; - } + /** Do we need to track init/uninit state of this symbol? + * I.e. is symbol either a local or a blank final variable? + */ + boolean trackable(VarSymbol sym) { + return + (sym.owner.kind == MTH || + ((sym.flags() & (FINAL | HASINIT | PARAMETER)) == FINAL && + classDef.sym.isEnclosedBy((ClassSymbol)sym.owner))); + } - /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets. - */ - void merge() { - inits = initsWhenFalse.andSet(initsWhenTrue); - uninits = uninitsWhenFalse.andSet(uninitsWhenTrue); - } - -/* ************************************************************************ - * Visitor methods for statements and definitions - *************************************************************************/ - - /** Analyze a definition. - */ - void scanDef(JCTree tree) { - scanStat(tree); - if (tree != null && tree.hasTag(JCTree.Tag.BLOCK) && !alive) { - log.error(tree.pos(), - "initializer.must.be.able.to.complete.normally"); + /** Initialize new trackable variable by setting its address field + * to the next available sequence number and entering it under that + * index into the vars array. + */ + void newVar(VarSymbol sym) { + if (nextadr == vars.length) { + VarSymbol[] newvars = new VarSymbol[nextadr * 2]; + System.arraycopy(vars, 0, newvars, 0, nextadr); + vars = newvars; + } + sym.adr = nextadr; + vars[nextadr] = sym; + inits.excl(nextadr); + uninits.incl(nextadr); + nextadr++; } - } - /** Analyze a statement. Check that statement is reachable. - */ - void scanStat(JCTree tree) { - if (!alive && tree != null) { - log.error(tree.pos(), "unreachable.stmt"); - if (!tree.hasTag(SKIP)) alive = true; - } - scan(tree); - } - - /** Analyze list of statements. - */ - void scanStats(List trees) { - if (trees != null) - for (List l = trees; l.nonEmpty(); l = l.tail) - scanStat(l.head); - } - - /** Analyze an expression. Make sure to set (un)inits rather than - * (un)initsWhenTrue(WhenFalse) on exit. - */ - void scanExpr(JCTree tree) { - if (tree != null) { - scan(tree); - if (inits == null) merge(); + /** Record an initialization of a trackable variable. + */ + void letInit(DiagnosticPosition pos, VarSymbol sym) { + if (sym.adr >= firstadr && trackable(sym)) { + if ((sym.flags() & FINAL) != 0) { + if ((sym.flags() & PARAMETER) != 0) { + if ((sym.flags() & UNION) != 0) { //multi-catch parameter + log.error(pos, "multicatch.parameter.may.not.be.assigned", + sym); + } + else { + log.error(pos, "final.parameter.may.not.be.assigned", + sym); + } + } else if (!uninits.isMember(sym.adr)) { + log.error(pos, + loopPassTwo + ? "var.might.be.assigned.in.loop" + : "var.might.already.be.assigned", + sym); + } else if (!inits.isMember(sym.adr)) { + // reachable assignment + uninits.excl(sym.adr); + uninitsTry.excl(sym.adr); + } else { + //log.rawWarning(pos, "unreachable assignment");//DEBUG + uninits.excl(sym.adr); + } + } + inits.incl(sym.adr); + } else if ((sym.flags() & FINAL) != 0) { + log.error(pos, "var.might.already.be.assigned", sym); + } } - } - /** Analyze a list of expressions. - */ - void scanExprs(List trees) { - if (trees != null) - for (List l = trees; l.nonEmpty(); l = l.tail) - scanExpr(l.head); - } + /** If tree is either a simple name or of the form this.name or + * C.this.name, and tree represents a trackable variable, + * record an initialization of the variable. + */ + void letInit(JCTree tree) { + tree = TreeInfo.skipParens(tree); + if (tree.hasTag(IDENT) || tree.hasTag(SELECT)) { + Symbol sym = TreeInfo.symbol(tree); + if (sym.kind == VAR) { + letInit(tree.pos(), (VarSymbol)sym); + } + } + } - /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse) - * rather than (un)inits on exit. - */ - void scanCond(JCTree tree) { - if (tree.type.isFalse()) { - if (inits == null) merge(); - initsWhenTrue = inits.dup(); - initsWhenTrue.inclRange(firstadr, nextadr); - uninitsWhenTrue = uninits.dup(); - uninitsWhenTrue.inclRange(firstadr, nextadr); - initsWhenFalse = inits; - uninitsWhenFalse = uninits; - } else if (tree.type.isTrue()) { - if (inits == null) merge(); + /** Check that trackable variable is initialized. + */ + void checkInit(DiagnosticPosition pos, VarSymbol sym) { + if ((sym.adr >= firstadr || sym.owner.kind != TYP) && + trackable(sym) && + !inits.isMember(sym.adr)) { + log.error(pos, "var.might.not.have.been.initialized", + sym); + inits.incl(sym.adr); + } + } + + /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets + */ + void split(boolean setToNull) { initsWhenFalse = inits.dup(); - initsWhenFalse.inclRange(firstadr, nextadr); uninitsWhenFalse = uninits.dup(); - uninitsWhenFalse.inclRange(firstadr, nextadr); initsWhenTrue = inits; uninitsWhenTrue = uninits; - } else { - scan(tree); - if (inits != null) - split(tree.type != syms.unknownType); + if (setToNull) + inits = uninits = null; } - if (tree.type != syms.unknownType) - inits = uninits = null; - } - /* ------------ Visitor methods for various sorts of trees -------------*/ + /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets. + */ + void merge() { + inits = initsWhenFalse.andSet(initsWhenTrue); + uninits = uninitsWhenFalse.andSet(uninitsWhenTrue); + } - public void visitClassDef(JCClassDecl tree) { - if (tree.sym == null) return; + /* ************************************************************************ + * Visitor methods for statements and definitions + *************************************************************************/ - JCClassDecl classDefPrev = classDef; - List thrownPrev = thrown; - List caughtPrev = caught; - boolean alivePrev = alive; - int firstadrPrev = firstadr; - int nextadrPrev = nextadr; - ListBuffer pendingExitsPrev = pendingExits; - Lint lintPrev = lint; + /** Analyze an expression. Make sure to set (un)inits rather than + * (un)initsWhenTrue(WhenFalse) on exit. + */ + void scanExpr(JCTree tree) { + if (tree != null) { + scan(tree); + if (inits == null) merge(); + } + } - pendingExits = new ListBuffer(); - if (tree.name != names.empty) { - caught = List.nil(); - firstadr = nextadr; + /** Analyze a list of expressions. + */ + void scanExprs(List trees) { + if (trees != null) + for (List l = trees; l.nonEmpty(); l = l.tail) + scanExpr(l.head); } - classDef = tree; - thrown = List.nil(); - lint = lint.augment(tree.sym.attributes_field); - try { - // define all the static fields - for (List l = tree.defs; l.nonEmpty(); l = l.tail) { - if (l.head.hasTag(VARDEF)) { - JCVariableDecl def = (JCVariableDecl)l.head; - if ((def.mods.flags & STATIC) != 0) { - VarSymbol sym = def.sym; - if (trackable(sym)) - newVar(sym); - } - } + /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse) + * rather than (un)inits on exit. + */ + void scanCond(JCTree tree) { + if (tree.type.isFalse()) { + if (inits == null) merge(); + initsWhenTrue = inits.dup(); + initsWhenTrue.inclRange(firstadr, nextadr); + uninitsWhenTrue = uninits.dup(); + uninitsWhenTrue.inclRange(firstadr, nextadr); + initsWhenFalse = inits; + uninitsWhenFalse = uninits; + } else if (tree.type.isTrue()) { + if (inits == null) merge(); + initsWhenFalse = inits.dup(); + initsWhenFalse.inclRange(firstadr, nextadr); + uninitsWhenFalse = uninits.dup(); + uninitsWhenFalse.inclRange(firstadr, nextadr); + initsWhenTrue = inits; + uninitsWhenTrue = uninits; + } else { + scan(tree); + if (inits != null) + split(tree.type != syms.unknownType); } + if (tree.type != syms.unknownType) + inits = uninits = null; + } - // process all the static initializers - for (List l = tree.defs; l.nonEmpty(); l = l.tail) { - if (!l.head.hasTag(METHODDEF) && - (TreeInfo.flags(l.head) & STATIC) != 0) { - scanDef(l.head); - errorUncaught(); - } - } + /* ------------ Visitor methods for various sorts of trees -------------*/ + + public void visitClassDef(JCClassDecl tree) { + if (tree.sym == null) return; + + JCClassDecl classDefPrev = classDef; + int firstadrPrev = firstadr; + int nextadrPrev = nextadr; + ListBuffer pendingExitsPrev = pendingExits; + Lint lintPrev = lint; - // add intersection of all thrown clauses of initial constructors - // to set of caught exceptions, unless class is anonymous. + pendingExits = new ListBuffer(); if (tree.name != names.empty) { - boolean firstConstructor = true; + firstadr = nextadr; + } + classDef = tree; + lint = lint.augment(tree.sym.attributes_field); + + try { + // define all the static fields for (List l = tree.defs; l.nonEmpty(); l = l.tail) { - if (TreeInfo.isInitialConstructor(l.head)) { - List mthrown = - ((JCMethodDecl) l.head).sym.type.getThrownTypes(); - if (firstConstructor) { - caught = mthrown; - firstConstructor = false; - } else { - caught = chk.intersect(mthrown, caught); + if (l.head.hasTag(VARDEF)) { + JCVariableDecl def = (JCVariableDecl)l.head; + if ((def.mods.flags & STATIC) != 0) { + VarSymbol sym = def.sym; + if (trackable(sym)) + newVar(sym); } } } - } - // define all the instance fields - for (List l = tree.defs; l.nonEmpty(); l = l.tail) { - if (l.head.hasTag(VARDEF)) { - JCVariableDecl def = (JCVariableDecl)l.head; - if ((def.mods.flags & STATIC) == 0) { - VarSymbol sym = def.sym; - if (trackable(sym)) - newVar(sym); + // process all the static initializers + for (List l = tree.defs; l.nonEmpty(); l = l.tail) { + if (!l.head.hasTag(METHODDEF) && + (TreeInfo.flags(l.head) & STATIC) != 0) { + scan(l.head); } } - } - // process all the instance initializers - for (List l = tree.defs; l.nonEmpty(); l = l.tail) { - if (!l.head.hasTag(METHODDEF) && - (TreeInfo.flags(l.head) & STATIC) == 0) { - scanDef(l.head); - errorUncaught(); + // define all the instance fields + for (List l = tree.defs; l.nonEmpty(); l = l.tail) { + if (l.head.hasTag(VARDEF)) { + JCVariableDecl def = (JCVariableDecl)l.head; + if ((def.mods.flags & STATIC) == 0) { + VarSymbol sym = def.sym; + if (trackable(sym)) + newVar(sym); + } + } } - } - // in an anonymous class, add the set of thrown exceptions to - // the throws clause of the synthetic constructor and propagate - // outwards. - // Changing the throws clause on the fly is okay here because - // the anonymous constructor can't be invoked anywhere else, - // and its type hasn't been cached. - if (tree.name == names.empty) { + // process all the instance initializers for (List l = tree.defs; l.nonEmpty(); l = l.tail) { - if (TreeInfo.isInitialConstructor(l.head)) { - JCMethodDecl mdef = (JCMethodDecl)l.head; - mdef.thrown = make.Types(thrown); - mdef.sym.type = types.createMethodTypeWithThrown(mdef.sym.type, thrown); + if (!l.head.hasTag(METHODDEF) && + (TreeInfo.flags(l.head) & STATIC) == 0) { + scan(l.head); + } + } + + // process all the methods + for (List l = tree.defs; l.nonEmpty(); l = l.tail) { + if (l.head.hasTag(METHODDEF)) { + scan(l.head); } } - thrownPrev = chk.union(thrown, thrownPrev); + } finally { + pendingExits = pendingExitsPrev; + nextadr = nextadrPrev; + firstadr = firstadrPrev; + classDef = classDefPrev; + lint = lintPrev; } + } - // process all the methods - for (List l = tree.defs; l.nonEmpty(); l = l.tail) { - if (l.head.hasTag(METHODDEF)) { - scan(l.head); - errorUncaught(); - } - } + public void visitMethodDef(JCMethodDecl tree) { + if (tree.body == null) return; - thrown = thrownPrev; - } finally { - pendingExits = pendingExitsPrev; - alive = alivePrev; - nextadr = nextadrPrev; - firstadr = firstadrPrev; - caught = caughtPrev; - classDef = classDefPrev; - lint = lintPrev; - } - } + Bits initsPrev = inits.dup(); + Bits uninitsPrev = uninits.dup(); + int nextadrPrev = nextadr; + int firstadrPrev = firstadr; + Lint lintPrev = lint; - public void visitMethodDef(JCMethodDecl tree) { - if (tree.body == null) return; + lint = lint.augment(tree.sym.attributes_field); + + Assert.check(pendingExits.isEmpty()); - List caughtPrev = caught; - List mthrown = tree.sym.type.getThrownTypes(); - Bits initsPrev = inits.dup(); - Bits uninitsPrev = uninits.dup(); - int nextadrPrev = nextadr; - int firstadrPrev = firstadr; - Lint lintPrev = lint; - - lint = lint.augment(tree.sym.attributes_field); - - Assert.check(pendingExits.isEmpty()); + try { + boolean isInitialConstructor = + TreeInfo.isInitialConstructor(tree); - try { - boolean isInitialConstructor = - TreeInfo.isInitialConstructor(tree); - - if (!isInitialConstructor) - firstadr = nextadr; - for (List l = tree.params; l.nonEmpty(); l = l.tail) { - JCVariableDecl def = l.head; - scan(def); - inits.incl(def.sym.adr); - uninits.excl(def.sym.adr); - } - if (isInitialConstructor) - caught = chk.union(caught, mthrown); - else if ((tree.sym.flags() & (BLOCK | STATIC)) != BLOCK) - caught = mthrown; - // else we are in an instance initializer block; - // leave caught unchanged. + if (!isInitialConstructor) + firstadr = nextadr; + for (List l = tree.params; l.nonEmpty(); l = l.tail) { + JCVariableDecl def = l.head; + scan(def); + inits.incl(def.sym.adr); + uninits.excl(def.sym.adr); + } + // else we are in an instance initializer block; + // leave caught unchanged. + scan(tree.body); - alive = true; - scanStat(tree.body); - - if (alive && tree.sym.type.getReturnType().tag != VOID) - log.error(TreeInfo.diagEndPos(tree.body), "missing.ret.stmt"); - - if (isInitialConstructor) { - for (int i = firstadr; i < nextadr; i++) - if (vars[i].owner == classDef.sym) - checkInit(TreeInfo.diagEndPos(tree.body), vars[i]); - } - List exits = pendingExits.toList(); - pendingExits = new ListBuffer(); - while (exits.nonEmpty()) { - PendingExit exit = exits.head; - exits = exits.tail; - if (exit.thrown == null) { - Assert.check(exit.tree.hasTag(RETURN)); + if (isInitialConstructor) { + for (int i = firstadr; i < nextadr; i++) + if (vars[i].owner == classDef.sym) + checkInit(TreeInfo.diagEndPos(tree.body), vars[i]); + } + List exits = pendingExits.toList(); + pendingExits = new ListBuffer(); + while (exits.nonEmpty()) { + AssignPendingExit exit = exits.head; + exits = exits.tail; + Assert.check(exit.tree.hasTag(RETURN), exit.tree); if (isInitialConstructor) { - inits = exit.inits; + inits = exit.exit_inits; for (int i = firstadr; i < nextadr; i++) checkInit(exit.tree.pos(), vars[i]); } - } else { - // uncaught throws will be reported later - pendingExits.append(exit); } - } - } finally { - inits = initsPrev; - uninits = uninitsPrev; - nextadr = nextadrPrev; - firstadr = firstadrPrev; - caught = caughtPrev; - lint = lintPrev; - } - } - - public void visitVarDef(JCVariableDecl tree) { - boolean track = trackable(tree.sym); - if (track && tree.sym.owner.kind == MTH) newVar(tree.sym); - if (tree.init != null) { - Lint lintPrev = lint; - lint = lint.augment(tree.sym.attributes_field); - try{ - scanExpr(tree.init); - if (track) letInit(tree.pos(), tree.sym); } finally { + inits = initsPrev; + uninits = uninitsPrev; + nextadr = nextadrPrev; + firstadr = firstadrPrev; lint = lintPrev; } } - } - - public void visitBlock(JCBlock tree) { - int nextadrPrev = nextadr; - scanStats(tree.stats); - nextadr = nextadrPrev; - } - public void visitDoLoop(JCDoWhileLoop tree) { - ListBuffer prevPendingExits = pendingExits; - boolean prevLoopPassTwo = loopPassTwo; - pendingExits = new ListBuffer(); - int prevErrors = log.nerrors; - do { - Bits uninitsEntry = uninits.dup(); - uninitsEntry.excludeFrom(nextadr); - scanStat(tree.body); - alive |= resolveContinues(tree); - scanCond(tree.cond); - if (log.nerrors != prevErrors || - loopPassTwo || - uninitsEntry.dup().diffSet(uninitsWhenTrue).nextBit(firstadr)==-1) - break; - inits = initsWhenTrue; - uninits = uninitsEntry.andSet(uninitsWhenTrue); - loopPassTwo = true; - alive = true; - } while (true); - loopPassTwo = prevLoopPassTwo; - inits = initsWhenFalse; - uninits = uninitsWhenFalse; - alive = alive && !tree.cond.type.isTrue(); - alive |= resolveBreaks(tree, prevPendingExits); - } + public void visitVarDef(JCVariableDecl tree) { + boolean track = trackable(tree.sym); + if (track && tree.sym.owner.kind == MTH) newVar(tree.sym); + if (tree.init != null) { + Lint lintPrev = lint; + lint = lint.augment(tree.sym.attributes_field); + try{ + scanExpr(tree.init); + if (track) letInit(tree.pos(), tree.sym); + } finally { + lint = lintPrev; + } + } + } + + public void visitBlock(JCBlock tree) { + int nextadrPrev = nextadr; + scan(tree.stats); + nextadr = nextadrPrev; + } - public void visitWhileLoop(JCWhileLoop tree) { - ListBuffer prevPendingExits = pendingExits; - boolean prevLoopPassTwo = loopPassTwo; - Bits initsCond; - Bits uninitsCond; - pendingExits = new ListBuffer(); - int prevErrors = log.nerrors; - do { - Bits uninitsEntry = uninits.dup(); - uninitsEntry.excludeFrom(nextadr); - scanCond(tree.cond); - initsCond = initsWhenFalse; - uninitsCond = uninitsWhenFalse; - inits = initsWhenTrue; - uninits = uninitsWhenTrue; - alive = !tree.cond.type.isFalse(); - scanStat(tree.body); - alive |= resolveContinues(tree); - if (log.nerrors != prevErrors || - loopPassTwo || - uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) - break; - uninits = uninitsEntry.andSet(uninits); - loopPassTwo = true; - alive = true; - } while (true); - loopPassTwo = prevLoopPassTwo; - inits = initsCond; - uninits = uninitsCond; - alive = resolveBreaks(tree, prevPendingExits) || - !tree.cond.type.isTrue(); - } + public void visitDoLoop(JCDoWhileLoop tree) { + ListBuffer prevPendingExits = pendingExits; + boolean prevLoopPassTwo = loopPassTwo; + pendingExits = new ListBuffer(); + int prevErrors = log.nerrors; + do { + Bits uninitsEntry = uninits.dup(); + uninitsEntry.excludeFrom(nextadr); + scan(tree.body); + resolveContinues(tree); + scanCond(tree.cond); + if (log.nerrors != prevErrors || + loopPassTwo || + uninitsEntry.dup().diffSet(uninitsWhenTrue).nextBit(firstadr)==-1) + break; + inits = initsWhenTrue; + uninits = uninitsEntry.andSet(uninitsWhenTrue); + loopPassTwo = true; + } while (true); + loopPassTwo = prevLoopPassTwo; + inits = initsWhenFalse; + uninits = uninitsWhenFalse; + resolveBreaks(tree, prevPendingExits); + } - public void visitForLoop(JCForLoop tree) { - ListBuffer prevPendingExits = pendingExits; - boolean prevLoopPassTwo = loopPassTwo; - int nextadrPrev = nextadr; - scanStats(tree.init); - Bits initsCond; - Bits uninitsCond; - pendingExits = new ListBuffer(); - int prevErrors = log.nerrors; - do { - Bits uninitsEntry = uninits.dup(); - uninitsEntry.excludeFrom(nextadr); - if (tree.cond != null) { + public void visitWhileLoop(JCWhileLoop tree) { + ListBuffer prevPendingExits = pendingExits; + boolean prevLoopPassTwo = loopPassTwo; + Bits initsCond; + Bits uninitsCond; + pendingExits = new ListBuffer(); + int prevErrors = log.nerrors; + do { + Bits uninitsEntry = uninits.dup(); + uninitsEntry.excludeFrom(nextadr); scanCond(tree.cond); initsCond = initsWhenFalse; uninitsCond = uninitsWhenFalse; inits = initsWhenTrue; uninits = uninitsWhenTrue; - alive = !tree.cond.type.isFalse(); - } else { - initsCond = inits.dup(); - initsCond.inclRange(firstadr, nextadr); - uninitsCond = uninits.dup(); - uninitsCond.inclRange(firstadr, nextadr); - alive = true; - } - scanStat(tree.body); - alive |= resolveContinues(tree); - scan(tree.step); - if (log.nerrors != prevErrors || - loopPassTwo || - uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) - break; - uninits = uninitsEntry.andSet(uninits); - loopPassTwo = true; - alive = true; - } while (true); - loopPassTwo = prevLoopPassTwo; - inits = initsCond; - uninits = uninitsCond; - alive = resolveBreaks(tree, prevPendingExits) || - tree.cond != null && !tree.cond.type.isTrue(); - nextadr = nextadrPrev; - } + scan(tree.body); + resolveContinues(tree); + if (log.nerrors != prevErrors || + loopPassTwo || + uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) + break; + uninits = uninitsEntry.andSet(uninits); + loopPassTwo = true; + } while (true); + loopPassTwo = prevLoopPassTwo; + inits = initsCond; + uninits = uninitsCond; + resolveBreaks(tree, prevPendingExits); + } - public void visitForeachLoop(JCEnhancedForLoop tree) { - visitVarDef(tree.var); + public void visitForLoop(JCForLoop tree) { + ListBuffer prevPendingExits = pendingExits; + boolean prevLoopPassTwo = loopPassTwo; + int nextadrPrev = nextadr; + scan(tree.init); + Bits initsCond; + Bits uninitsCond; + pendingExits = new ListBuffer(); + int prevErrors = log.nerrors; + do { + Bits uninitsEntry = uninits.dup(); + uninitsEntry.excludeFrom(nextadr); + if (tree.cond != null) { + scanCond(tree.cond); + initsCond = initsWhenFalse; + uninitsCond = uninitsWhenFalse; + inits = initsWhenTrue; + uninits = uninitsWhenTrue; + } else { + initsCond = inits.dup(); + initsCond.inclRange(firstadr, nextadr); + uninitsCond = uninits.dup(); + uninitsCond.inclRange(firstadr, nextadr); + } + scan(tree.body); + resolveContinues(tree); + scan(tree.step); + if (log.nerrors != prevErrors || + loopPassTwo || + uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) + break; + uninits = uninitsEntry.andSet(uninits); + loopPassTwo = true; + } while (true); + loopPassTwo = prevLoopPassTwo; + inits = initsCond; + uninits = uninitsCond; + resolveBreaks(tree, prevPendingExits); + nextadr = nextadrPrev; + } - ListBuffer prevPendingExits = pendingExits; - boolean prevLoopPassTwo = loopPassTwo; - int nextadrPrev = nextadr; - scan(tree.expr); - Bits initsStart = inits.dup(); - Bits uninitsStart = uninits.dup(); + public void visitForeachLoop(JCEnhancedForLoop tree) { + visitVarDef(tree.var); + + ListBuffer prevPendingExits = pendingExits; + boolean prevLoopPassTwo = loopPassTwo; + int nextadrPrev = nextadr; + scan(tree.expr); + Bits initsStart = inits.dup(); + Bits uninitsStart = uninits.dup(); + + letInit(tree.pos(), tree.var.sym); + pendingExits = new ListBuffer(); + int prevErrors = log.nerrors; + do { + Bits uninitsEntry = uninits.dup(); + uninitsEntry.excludeFrom(nextadr); + scan(tree.body); + resolveContinues(tree); + if (log.nerrors != prevErrors || + loopPassTwo || + uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) + break; + uninits = uninitsEntry.andSet(uninits); + loopPassTwo = true; + } while (true); + loopPassTwo = prevLoopPassTwo; + inits = initsStart; + uninits = uninitsStart.andSet(uninits); + resolveBreaks(tree, prevPendingExits); + nextadr = nextadrPrev; + } + + public void visitLabelled(JCLabeledStatement tree) { + ListBuffer prevPendingExits = pendingExits; + pendingExits = new ListBuffer(); + scan(tree.body); + resolveBreaks(tree, prevPendingExits); + } - letInit(tree.pos(), tree.var.sym); - pendingExits = new ListBuffer(); - int prevErrors = log.nerrors; - do { - Bits uninitsEntry = uninits.dup(); - uninitsEntry.excludeFrom(nextadr); - scanStat(tree.body); - alive |= resolveContinues(tree); - if (log.nerrors != prevErrors || - loopPassTwo || - uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) - break; - uninits = uninitsEntry.andSet(uninits); - loopPassTwo = true; - alive = true; - } while (true); - loopPassTwo = prevLoopPassTwo; - inits = initsStart; - uninits = uninitsStart.andSet(uninits); - resolveBreaks(tree, prevPendingExits); - alive = true; - nextadr = nextadrPrev; - } + public void visitSwitch(JCSwitch tree) { + ListBuffer prevPendingExits = pendingExits; + pendingExits = new ListBuffer(); + int nextadrPrev = nextadr; + scanExpr(tree.selector); + Bits initsSwitch = inits; + Bits uninitsSwitch = uninits.dup(); + boolean hasDefault = false; + for (List l = tree.cases; l.nonEmpty(); l = l.tail) { + inits = initsSwitch.dup(); + uninits = uninits.andSet(uninitsSwitch); + JCCase c = l.head; + if (c.pat == null) + hasDefault = true; + else + scanExpr(c.pat); + scan(c.stats); + addVars(c.stats, initsSwitch, uninitsSwitch); + // Warn about fall-through if lint switch fallthrough enabled. + } + if (!hasDefault) { + inits.andSet(initsSwitch); + } + resolveBreaks(tree, prevPendingExits); + nextadr = nextadrPrev; + } + // where + /** Add any variables defined in stats to inits and uninits. */ + private void addVars(List stats, Bits inits, + Bits uninits) { + for (;stats.nonEmpty(); stats = stats.tail) { + JCTree stat = stats.head; + if (stat.hasTag(VARDEF)) { + int adr = ((JCVariableDecl) stat).sym.adr; + inits.excl(adr); + uninits.incl(adr); + } + } + } - public void visitLabelled(JCLabeledStatement tree) { - ListBuffer prevPendingExits = pendingExits; - pendingExits = new ListBuffer(); - scanStat(tree.body); - alive |= resolveBreaks(tree, prevPendingExits); - } + public void visitTry(JCTry tree) { + ListBuffer resourceVarDecls = ListBuffer.lb(); + Bits uninitsTryPrev = uninitsTry; + ListBuffer prevPendingExits = pendingExits; + pendingExits = new ListBuffer(); + Bits initsTry = inits.dup(); + uninitsTry = uninits.dup(); + for (JCTree resource : tree.resources) { + if (resource instanceof JCVariableDecl) { + JCVariableDecl vdecl = (JCVariableDecl) resource; + visitVarDef(vdecl); + unrefdResources.enter(vdecl.sym); + resourceVarDecls.append(vdecl); + } else if (resource instanceof JCExpression) { + scanExpr((JCExpression) resource); + } else { + throw new AssertionError(tree); // parser error + } + } + scan(tree.body); + uninitsTry.andSet(uninits); + Bits initsEnd = inits; + Bits uninitsEnd = uninits; + int nextadrCatch = nextadr; + + if (!resourceVarDecls.isEmpty() && + lint.isEnabled(Lint.LintCategory.TRY)) { + for (JCVariableDecl resVar : resourceVarDecls) { + if (unrefdResources.includes(resVar.sym)) { + log.warning(Lint.LintCategory.TRY, resVar.pos(), + "try.resource.not.referenced", resVar.sym); + unrefdResources.remove(resVar.sym); + } + } + } - public void visitSwitch(JCSwitch tree) { - ListBuffer prevPendingExits = pendingExits; - pendingExits = new ListBuffer(); - int nextadrPrev = nextadr; - scanExpr(tree.selector); - Bits initsSwitch = inits; - Bits uninitsSwitch = uninits.dup(); - boolean hasDefault = false; - for (List l = tree.cases; l.nonEmpty(); l = l.tail) { - alive = true; - inits = initsSwitch.dup(); - uninits = uninits.andSet(uninitsSwitch); - JCCase c = l.head; - if (c.pat == null) - hasDefault = true; - else - scanExpr(c.pat); - scanStats(c.stats); - addVars(c.stats, initsSwitch, uninitsSwitch); - // Warn about fall-through if lint switch fallthrough enabled. - if (!loopPassTwo && - alive && - lint.isEnabled(Lint.LintCategory.FALLTHROUGH) && - c.stats.nonEmpty() && l.tail.nonEmpty()) - log.warning(Lint.LintCategory.FALLTHROUGH, - l.tail.head.pos(), - "possible.fall-through.into.case"); + for (List l = tree.catchers; l.nonEmpty(); l = l.tail) { + JCVariableDecl param = l.head.param; + inits = initsTry.dup(); + uninits = uninitsTry.dup(); + scan(param); + inits.incl(param.sym.adr); + uninits.excl(param.sym.adr); + scan(l.head.body); + initsEnd.andSet(inits); + uninitsEnd.andSet(uninits); + nextadr = nextadrCatch; + } + if (tree.finalizer != null) { + inits = initsTry.dup(); + uninits = uninitsTry.dup(); + ListBuffer exits = pendingExits; + pendingExits = prevPendingExits; + scan(tree.finalizer); + if (!tree.finallyCanCompleteNormally) { + // discard exits and exceptions from try and finally + } else { + uninits.andSet(uninitsEnd); + // FIX: this doesn't preserve source order of exits in catch + // versus finally! + while (exits.nonEmpty()) { + AssignPendingExit exit = exits.next(); + if (exit.exit_inits != null) { + exit.exit_inits.orSet(inits); + exit.exit_uninits.andSet(uninits); + } + pendingExits.append(exit); + } + inits.orSet(initsEnd); + } + } else { + inits = initsEnd; + uninits = uninitsEnd; + ListBuffer exits = pendingExits; + pendingExits = prevPendingExits; + while (exits.nonEmpty()) pendingExits.append(exits.next()); + } + uninitsTry.andSet(uninitsTryPrev).andSet(uninits); } - if (!hasDefault) { - inits.andSet(initsSwitch); - alive = true; - } - alive |= resolveBreaks(tree, prevPendingExits); - nextadr = nextadrPrev; - } - // where - /** Add any variables defined in stats to inits and uninits. */ - private static void addVars(List stats, Bits inits, - Bits uninits) { - for (;stats.nonEmpty(); stats = stats.tail) { - JCTree stat = stats.head; - if (stat.hasTag(VARDEF)) { - int adr = ((JCVariableDecl) stat).sym.adr; - inits.excl(adr); - uninits.incl(adr); - } + + public void visitConditional(JCConditional tree) { + scanCond(tree.cond); + Bits initsBeforeElse = initsWhenFalse; + Bits uninitsBeforeElse = uninitsWhenFalse; + inits = initsWhenTrue; + uninits = uninitsWhenTrue; + if (tree.truepart.type.tag == BOOLEAN && + tree.falsepart.type.tag == BOOLEAN) { + // if b and c are boolean valued, then + // v is (un)assigned after a?b:c when true iff + // v is (un)assigned after b when true and + // v is (un)assigned after c when true + scanCond(tree.truepart); + Bits initsAfterThenWhenTrue = initsWhenTrue.dup(); + Bits initsAfterThenWhenFalse = initsWhenFalse.dup(); + Bits uninitsAfterThenWhenTrue = uninitsWhenTrue.dup(); + Bits uninitsAfterThenWhenFalse = uninitsWhenFalse.dup(); + inits = initsBeforeElse; + uninits = uninitsBeforeElse; + scanCond(tree.falsepart); + initsWhenTrue.andSet(initsAfterThenWhenTrue); + initsWhenFalse.andSet(initsAfterThenWhenFalse); + uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue); + uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse); + } else { + scanExpr(tree.truepart); + Bits initsAfterThen = inits.dup(); + Bits uninitsAfterThen = uninits.dup(); + inits = initsBeforeElse; + uninits = uninitsBeforeElse; + scanExpr(tree.falsepart); + inits.andSet(initsAfterThen); + uninits.andSet(uninitsAfterThen); } } - public void visitTry(JCTry tree) { - List caughtPrev = caught; - List thrownPrev = thrown; - thrown = List.nil(); - for (List l = tree.catchers; l.nonEmpty(); l = l.tail) { - List subClauses = TreeInfo.isMultiCatch(l.head) ? - ((JCTypeUnion)l.head.param.vartype).alternatives : - List.of(l.head.param.vartype); - for (JCExpression ct : subClauses) { - caught = chk.incl(ct.type, caught); - } - } - ListBuffer resourceVarDecls = ListBuffer.lb(); - Bits uninitsTryPrev = uninitsTry; - ListBuffer prevPendingExits = pendingExits; - pendingExits = new ListBuffer(); - Bits initsTry = inits.dup(); - uninitsTry = uninits.dup(); - for (JCTree resource : tree.resources) { - if (resource instanceof JCVariableDecl) { - JCVariableDecl vdecl = (JCVariableDecl) resource; - visitVarDef(vdecl); - unrefdResources.enter(vdecl.sym); - resourceVarDecls.append(vdecl); - } else if (resource instanceof JCExpression) { - scanExpr((JCExpression) resource); + public void visitIf(JCIf tree) { + scanCond(tree.cond); + Bits initsBeforeElse = initsWhenFalse; + Bits uninitsBeforeElse = uninitsWhenFalse; + inits = initsWhenTrue; + uninits = uninitsWhenTrue; + scan(tree.thenpart); + if (tree.elsepart != null) { + Bits initsAfterThen = inits.dup(); + Bits uninitsAfterThen = uninits.dup(); + inits = initsBeforeElse; + uninits = uninitsBeforeElse; + scan(tree.elsepart); + inits.andSet(initsAfterThen); + uninits.andSet(uninitsAfterThen); } else { - throw new AssertionError(tree); // parser error - } - } - for (JCTree resource : tree.resources) { - List closeableSupertypes = resource.type.isCompound() ? - types.interfaces(resource.type).prepend(types.supertype(resource.type)) : - List.of(resource.type); - for (Type sup : closeableSupertypes) { - if (types.asSuper(sup, syms.autoCloseableType.tsym) != null) { - Symbol closeMethod = rs.resolveQualifiedMethod(tree, - attrEnv, - sup, - names.close, - List.nil(), - List.nil()); - if (closeMethod.kind == MTH) { - for (Type t : ((MethodSymbol)closeMethod).getThrownTypes()) { - markThrown(resource, t); - } - } - } - } - } - scanStat(tree.body); - List thrownInTry = allowImprovedCatchAnalysis ? - chk.union(thrown, List.of(syms.runtimeExceptionType, syms.errorType)) : - thrown; - thrown = thrownPrev; - caught = caughtPrev; - boolean aliveEnd = alive; - uninitsTry.andSet(uninits); - Bits initsEnd = inits; - Bits uninitsEnd = uninits; - int nextadrCatch = nextadr; - - if (!resourceVarDecls.isEmpty() && - lint.isEnabled(Lint.LintCategory.TRY)) { - for (JCVariableDecl resVar : resourceVarDecls) { - if (unrefdResources.includes(resVar.sym)) { - log.warning(Lint.LintCategory.TRY, resVar.pos(), - "try.resource.not.referenced", resVar.sym); - unrefdResources.remove(resVar.sym); - } + inits.andSet(initsBeforeElse); + uninits.andSet(uninitsBeforeElse); } } - List caughtInTry = List.nil(); - for (List l = tree.catchers; l.nonEmpty(); l = l.tail) { - alive = true; - JCVariableDecl param = l.head.param; - List subClauses = TreeInfo.isMultiCatch(l.head) ? - ((JCTypeUnion)l.head.param.vartype).alternatives : - List.of(l.head.param.vartype); - List ctypes = List.nil(); - List rethrownTypes = chk.diff(thrownInTry, caughtInTry); - for (JCExpression ct : subClauses) { - Type exc = ct.type; - if (exc != syms.unknownType) { - ctypes = ctypes.append(exc); - if (types.isSameType(exc, syms.objectType)) - continue; - checkCaughtType(l.head.pos(), exc, thrownInTry, caughtInTry); - caughtInTry = chk.incl(exc, caughtInTry); - } + public void visitBreak(JCBreak tree) { + recordExit(tree, new AssignPendingExit(tree, inits, uninits)); + } + + public void visitContinue(JCContinue tree) { + recordExit(tree, new AssignPendingExit(tree, inits, uninits)); + } + + public void visitReturn(JCReturn tree) { + scanExpr(tree.expr); + // if not initial constructor, should markDead instead of recordExit + recordExit(tree, new AssignPendingExit(tree, inits, uninits)); + } + + public void visitThrow(JCThrow tree) { + scanExpr(tree.expr); + markDead(); + } + + public void visitApply(JCMethodInvocation tree) { + scanExpr(tree.meth); + scanExprs(tree.args); + } + + public void visitNewClass(JCNewClass tree) { + scanExpr(tree.encl); + scanExprs(tree.args); + scan(tree.def); + } + + public void visitNewArray(JCNewArray tree) { + scanExprs(tree.dims); + scanExprs(tree.elems); + } + + public void visitAssert(JCAssert tree) { + Bits initsExit = inits.dup(); + Bits uninitsExit = uninits.dup(); + scanCond(tree.cond); + uninitsExit.andSet(uninitsWhenTrue); + if (tree.detail != null) { + inits = initsWhenFalse; + uninits = uninitsWhenFalse; + scanExpr(tree.detail); } - inits = initsTry.dup(); - uninits = uninitsTry.dup(); - scan(param); - inits.incl(param.sym.adr); - uninits.excl(param.sym.adr); - preciseRethrowTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes)); - scanStat(l.head.body); - initsEnd.andSet(inits); - uninitsEnd.andSet(uninits); - nextadr = nextadrCatch; - preciseRethrowTypes.remove(param.sym); - aliveEnd |= alive; + inits = initsExit; + uninits = uninitsExit; + } + + public void visitAssign(JCAssign tree) { + JCTree lhs = TreeInfo.skipParens(tree.lhs); + if (!(lhs instanceof JCIdent)) scanExpr(lhs); + scanExpr(tree.rhs); + letInit(lhs); + } + + public void visitAssignop(JCAssignOp tree) { + scanExpr(tree.lhs); + scanExpr(tree.rhs); + letInit(tree.lhs); + } + + public void visitUnary(JCUnary tree) { + switch (tree.getTag()) { + case NOT: + scanCond(tree.arg); + Bits t = initsWhenFalse; + initsWhenFalse = initsWhenTrue; + initsWhenTrue = t; + t = uninitsWhenFalse; + uninitsWhenFalse = uninitsWhenTrue; + uninitsWhenTrue = t; + break; + case PREINC: case POSTINC: + case PREDEC: case POSTDEC: + scanExpr(tree.arg); + letInit(tree.arg); + break; + default: + scanExpr(tree.arg); + } } - if (tree.finalizer != null) { - List savedThrown = thrown; - thrown = List.nil(); - inits = initsTry.dup(); - uninits = uninitsTry.dup(); - ListBuffer exits = pendingExits; - pendingExits = prevPendingExits; - alive = true; - scanStat(tree.finalizer); - if (!alive) { - // discard exits and exceptions from try and finally - thrown = chk.union(thrown, thrownPrev); - if (!loopPassTwo && - lint.isEnabled(Lint.LintCategory.FINALLY)) { - log.warning(Lint.LintCategory.FINALLY, - TreeInfo.diagEndPos(tree.finalizer), - "finally.cannot.complete"); - } - } else { - thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry)); - thrown = chk.union(thrown, savedThrown); - uninits.andSet(uninitsEnd); - // FIX: this doesn't preserve source order of exits in catch - // versus finally! - while (exits.nonEmpty()) { - PendingExit exit = exits.next(); - if (exit.inits != null) { - exit.inits.orSet(inits); - exit.uninits.andSet(uninits); - } - pendingExits.append(exit); - } - inits.orSet(initsEnd); - alive = aliveEnd; + + public void visitBinary(JCBinary tree) { + switch (tree.getTag()) { + case AND: + scanCond(tree.lhs); + Bits initsWhenFalseLeft = initsWhenFalse; + Bits uninitsWhenFalseLeft = uninitsWhenFalse; + inits = initsWhenTrue; + uninits = uninitsWhenTrue; + scanCond(tree.rhs); + initsWhenFalse.andSet(initsWhenFalseLeft); + uninitsWhenFalse.andSet(uninitsWhenFalseLeft); + break; + case OR: + scanCond(tree.lhs); + Bits initsWhenTrueLeft = initsWhenTrue; + Bits uninitsWhenTrueLeft = uninitsWhenTrue; + inits = initsWhenFalse; + uninits = uninitsWhenFalse; + scanCond(tree.rhs); + initsWhenTrue.andSet(initsWhenTrueLeft); + uninitsWhenTrue.andSet(uninitsWhenTrueLeft); + break; + default: + scanExpr(tree.lhs); + scanExpr(tree.rhs); + } + } + + public void visitIdent(JCIdent tree) { + if (tree.sym.kind == VAR) { + checkInit(tree.pos(), (VarSymbol)tree.sym); + referenced(tree.sym); } - } else { - thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry)); - inits = initsEnd; - uninits = uninitsEnd; - alive = aliveEnd; - ListBuffer exits = pendingExits; - pendingExits = prevPendingExits; - while (exits.nonEmpty()) pendingExits.append(exits.next()); + } + + void referenced(Symbol sym) { + unrefdResources.remove(sym); } - uninitsTry.andSet(uninitsTryPrev).andSet(uninits); - } + + public void visitTopLevel(JCCompilationUnit tree) { + // Do nothing for TopLevel since each class is visited individually + } + + /************************************************************************** + * main method + *************************************************************************/ - void checkCaughtType(DiagnosticPosition pos, Type exc, List thrownInTry, List caughtInTry) { - if (chk.subset(exc, caughtInTry)) { - log.error(pos, "except.already.caught", exc); - } else if (!chk.isUnchecked(pos, exc) && - !isExceptionOrThrowable(exc) && - !chk.intersects(exc, thrownInTry)) { - log.error(pos, "except.never.thrown.in.try", exc); - } else if (allowImprovedCatchAnalysis) { - List catchableThrownTypes = chk.intersect(List.of(exc), thrownInTry); - // 'catchableThrownTypes' cannnot possibly be empty - if 'exc' was an - // unchecked exception, the result list would not be empty, as the augmented - // thrown set includes { RuntimeException, Error }; if 'exc' was a checked - // exception, that would have been covered in the branch above - if (chk.diff(catchableThrownTypes, caughtInTry).isEmpty() && - !isExceptionOrThrowable(exc)) { - String key = catchableThrownTypes.length() == 1 ? - "unreachable.catch" : - "unreachable.catch.1"; - log.warning(pos, key, catchableThrownTypes); + /** Perform definite assignment/unassignment analysis on a tree. + */ + public void analyzeTree(Env env, TreeMaker make) { + try { + attrEnv = env; + JCTree tree = env.tree; + Flow.this.make = make; + inits = new Bits(); + uninits = new Bits(); + uninitsTry = new Bits(); + initsWhenTrue = initsWhenFalse = + uninitsWhenTrue = uninitsWhenFalse = null; + if (vars == null) + vars = new VarSymbol[32]; + else + for (int i=0; i(); + this.classDef = null; + unrefdResources = new Scope(env.enclClass.sym); + scan(tree); + } finally { + // note that recursive invocations of this method fail hard + inits = uninits = uninitsTry = null; + initsWhenTrue = initsWhenFalse = + uninitsWhenTrue = uninitsWhenFalse = null; + if (vars != null) for (int i=0; i l = tree.meth.type.getThrownTypes(); l.nonEmpty(); l = l.tail) - markThrown(tree, l.head); - } - - public void visitNewClass(JCNewClass tree) { - scanExpr(tree.encl); - scanExprs(tree.args); - // scan(tree.def); - for (List l = tree.constructorType.getThrownTypes(); - l.nonEmpty(); - l = l.tail) { - markThrown(tree, l.head); - } - List caughtPrev = caught; - try { - // If the new class expression defines an anonymous class, - // analysis of the anonymous constructor may encounter thrown - // types which are unsubstituted type variables. - // However, since the constructor's actual thrown types have - // already been marked as thrown, it is safe to simply include - // each of the constructor's formal thrown types in the set of - // 'caught/declared to be thrown' types, for the duration of - // the class def analysis. - if (tree.def != null) - for (List l = tree.constructor.type.getThrownTypes(); - l.nonEmpty(); - l = l.tail) { - caught = chk.incl(l.head, caught); - } - scan(tree.def); - } - finally { - caught = caughtPrev; - } - } - - public void visitNewArray(JCNewArray tree) { - scanExprs(tree.dims); - scanExprs(tree.elems); - } - - public void visitAssert(JCAssert tree) { - Bits initsExit = inits.dup(); - Bits uninitsExit = uninits.dup(); - scanCond(tree.cond); - uninitsExit.andSet(uninitsWhenTrue); - if (tree.detail != null) { - inits = initsWhenFalse; - uninits = uninitsWhenFalse; - scanExpr(tree.detail); - } - inits = initsExit; - uninits = uninitsExit; - } - - public void visitAssign(JCAssign tree) { - JCTree lhs = TreeInfo.skipParens(tree.lhs); - if (!(lhs instanceof JCIdent)) scanExpr(lhs); - scanExpr(tree.rhs); - letInit(lhs); - } - - public void visitAssignop(JCAssignOp tree) { - scanExpr(tree.lhs); - scanExpr(tree.rhs); - letInit(tree.lhs); - } - - public void visitUnary(JCUnary tree) { - switch (tree.getTag()) { - case NOT: - scanCond(tree.arg); - Bits t = initsWhenFalse; - initsWhenFalse = initsWhenTrue; - initsWhenTrue = t; - t = uninitsWhenFalse; - uninitsWhenFalse = uninitsWhenTrue; - uninitsWhenTrue = t; - break; - case PREINC: case POSTINC: - case PREDEC: case POSTDEC: - scanExpr(tree.arg); - letInit(tree.arg); - break; - default: - scanExpr(tree.arg); - } - } - - public void visitBinary(JCBinary tree) { - switch (tree.getTag()) { - case AND: - scanCond(tree.lhs); - Bits initsWhenFalseLeft = initsWhenFalse; - Bits uninitsWhenFalseLeft = uninitsWhenFalse; - inits = initsWhenTrue; - uninits = uninitsWhenTrue; - scanCond(tree.rhs); - initsWhenFalse.andSet(initsWhenFalseLeft); - uninitsWhenFalse.andSet(uninitsWhenFalseLeft); - break; - case OR: - scanCond(tree.lhs); - Bits initsWhenTrueLeft = initsWhenTrue; - Bits uninitsWhenTrueLeft = uninitsWhenTrue; - inits = initsWhenFalse; - uninits = uninitsWhenFalse; - scanCond(tree.rhs); - initsWhenTrue.andSet(initsWhenTrueLeft); - uninitsWhenTrue.andSet(uninitsWhenTrueLeft); - break; - default: - scanExpr(tree.lhs); - scanExpr(tree.rhs); - } - } - - public void visitIdent(JCIdent tree) { - if (tree.sym.kind == VAR) { - checkInit(tree.pos(), (VarSymbol)tree.sym); - referenced(tree.sym); - } - } - - void referenced(Symbol sym) { - unrefdResources.remove(sym); - } - - public void visitTypeCast(JCTypeCast tree) { - super.visitTypeCast(tree); - if (!tree.type.isErroneous() - && lint.isEnabled(Lint.LintCategory.CAST) - && types.isSameType(tree.expr.type, tree.clazz.type) - && !is292targetTypeCast(tree)) { - log.warning(Lint.LintCategory.CAST, - tree.pos(), "redundant.cast", tree.expr.type); - } - } - //where - private boolean is292targetTypeCast(JCTypeCast tree) { - boolean is292targetTypeCast = false; - JCExpression expr = TreeInfo.skipParens(tree.expr); - if (expr.hasTag(APPLY)) { - JCMethodInvocation apply = (JCMethodInvocation)expr; - Symbol sym = TreeInfo.symbol(apply.meth); - is292targetTypeCast = sym != null && - sym.kind == MTH && - (sym.flags() & POLYMORPHIC_SIGNATURE) != 0; - } - return is292targetTypeCast; - } - - public void visitTopLevel(JCCompilationUnit tree) { - // Do nothing for TopLevel since each class is visited individually - } - -/************************************************************************** - * main method - *************************************************************************/ - - /** Perform definite assignment/unassignment analysis on a tree. - */ - public void analyzeTree(Env env, TreeMaker make) { - try { - attrEnv = env; - JCTree tree = env.tree; - this.make = make; - inits = new Bits(); - uninits = new Bits(); - uninitsTry = new Bits(); - initsWhenTrue = initsWhenFalse = - uninitsWhenTrue = uninitsWhenFalse = null; - if (vars == null) - vars = new VarSymbol[32]; - else - for (int i=0; i(); - preciseRethrowTypes = new HashMap>(); - alive = true; - this.thrown = this.caught = null; - this.classDef = null; - unrefdResources = new Scope(env.enclClass.sym); - scan(tree); - } finally { - // note that recursive invocations of this method fail hard - inits = uninits = uninitsTry = null; - initsWhenTrue = initsWhenFalse = - uninitsWhenTrue = uninitsWhenFalse = null; - if (vars != null) for (int i=0; i instantiateAsUninferredVars(List undetvars, List tvars) { @@ -603,8 +603,7 @@ * method signature. The target return type is computed from the immediately * enclosing scope surrounding the polymorphic-signature call. */ - Type instantiatePolymorphicSignatureInstance(Env env, Type site, - Name name, + Type instantiatePolymorphicSignatureInstance(Env env, MethodSymbol spMethod, // sig. poly. method or null if none List argtypes) { final Type restype; diff -r 61eccc72f402 -r 122a0aede750 langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Wed Jul 05 18:07:54 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, 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 @@ -781,20 +781,6 @@ && s.owner.kind != MTH && types.isSameType(c.type, syms.deprecatedType)) s.flags_field |= Flags.DEPRECATED; - // Internally to java.lang.invoke, a @PolymorphicSignature annotation - // acts like a classfile attribute. - if (!c.type.isErroneous() && - types.isSameType(c.type, syms.polymorphicSignatureType)) { - if (!target.hasMethodHandles()) { - // Somebody is compiling JDK7 source code to a JDK6 target. - // Make it an error, since it is unlikely but important. - log.error(env.tree.pos(), - "wrong.target.for.polymorphic.signature.definition", - target.name); - } - // Pull the flag through for better diagnostics, even on a bad target. - s.flags_field |= Flags.POLYMORPHIC_SIGNATURE; - } if (!annotated.add(a.type.tsym)) log.error(a.pos, "duplicate.annotation"); } diff -r 61eccc72f402 -r 122a0aede750 langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Jul 05 18:07:54 2017 +0200 @@ -29,6 +29,8 @@ import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.Symbol.*; +import com.sun.tools.javac.comp.Attr.ResultInfo; +import com.sun.tools.javac.comp.Check.CheckContext; import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate; import com.sun.tools.javac.jvm.*; import com.sun.tools.javac.tree.*; @@ -70,6 +72,7 @@ Names names; Log log; Symtab syms; + Attr attr; Check chk; Infer infer; ClassReader reader; @@ -101,6 +104,7 @@ names = Names.instance(context); log = Log.instance(context); + attr = Attr.instance(context); chk = Check.instance(context); infer = Infer.instance(context); reader = ClassReader.instance(context); @@ -395,7 +399,6 @@ else { Symbol s2 = ((MethodSymbol)sym).implementation(site.tsym, types, true); return (s2 == null || s2 == sym || sym.owner == s2.owner || - s2.isPolymorphicSignatureGeneric() || !types.isSubSignature(types.memberType(site, s2), types.memberType(site, sym))); } } @@ -445,7 +448,6 @@ boolean useVarargs, Warner warn) throws Infer.InferenceException { - boolean polymorphicSignature = m.isPolymorphicSignatureGeneric() && allowMethodHandles; if (useVarargs && (m.flags() & VARARGS) == 0) throw inapplicableMethodException.setMessage(); Type mt = types.memberType(site, m); @@ -486,8 +488,7 @@ } // find out whether we need to go the slow route via infer - boolean instNeeded = tvars.tail != null || /*inlined: tvars.nonEmpty()*/ - polymorphicSignature; + boolean instNeeded = tvars.tail != null; /*inlined: tvars.nonEmpty()*/ for (List l = argtypes; l.tail != null/*inlined: l.nonEmpty()*/ && !instNeeded; l = l.tail) { @@ -495,9 +496,7 @@ } if (instNeeded) - return polymorphicSignature ? - infer.instantiatePolymorphicSignatureInstance(env, site, m.name, (MethodSymbol)m, argtypes) : - infer.instantiateMethod(env, + return infer.instantiateMethod(env, tvars, (MethodType)mt, m, @@ -627,15 +626,8 @@ } while (argtypes.nonEmpty() && formals.head != varargsFormal) { - Type undetFormal = infer.asUndetType(formals.head, undetvars); - Type capturedActual = types.capture(argtypes.head); - boolean works = allowBoxing ? - types.isConvertible(capturedActual, undetFormal, warn) : - types.isSubtypeUnchecked(capturedActual, undetFormal, warn); - if (!works) { - throw handler.argumentMismatch(false, argtypes.head, formals.head); - } - checkedArgs.append(capturedActual); + ResultInfo resultInfo = methodCheckResult(formals.head, allowBoxing, false, undetvars, handler, warn); + checkedArgs.append(resultInfo.check(env.tree.pos(), argtypes.head)); argtypes = argtypes.tail; formals = formals.tail; } @@ -648,13 +640,9 @@ //note: if applicability check is triggered by most specific test, //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5) Type elt = types.elemtype(varargsFormal); - Type eltUndet = infer.asUndetType(elt, undetvars); while (argtypes.nonEmpty()) { - Type capturedActual = types.capture(argtypes.head); - if (!types.isConvertible(capturedActual, eltUndet, warn)) { - throw handler.argumentMismatch(true, argtypes.head, elt); - } - checkedArgs.append(capturedActual); + ResultInfo resultInfo = methodCheckResult(elt, allowBoxing, true, undetvars, handler, warn); + checkedArgs.append(resultInfo.check(env.tree.pos(), argtypes.head)); argtypes = argtypes.tail; } //check varargs element type accessibility @@ -665,39 +653,116 @@ } return checkedArgs.toList(); } - // where - public static class InapplicableMethodException extends RuntimeException { - private static final long serialVersionUID = 0; + + /** + * Check context to be used during method applicability checks. A method check + * context might contain inference variables. + */ + abstract class MethodCheckContext implements CheckContext { + + MethodCheckHandler handler; + boolean useVarargs; + List undetvars; + Warner rsWarner; - JCDiagnostic diagnostic; - JCDiagnostic.Factory diags; + public MethodCheckContext(MethodCheckHandler handler, boolean useVarargs, List undetvars, Warner rsWarner) { + this.handler = handler; + this.useVarargs = useVarargs; + this.undetvars = undetvars; + this.rsWarner = rsWarner; + } + + public void report(DiagnosticPosition pos, Type found, Type req, JCDiagnostic details) { + throw handler.argumentMismatch(useVarargs, found, req); + } + + public Type rawInstantiatePoly(ForAll found, Type req, Warner warn) { + throw new AssertionError("ForAll in argument position"); + } + + public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { + return rsWarner; + } + } - InapplicableMethodException(JCDiagnostic.Factory diags) { - this.diagnostic = null; - this.diags = diags; - } - InapplicableMethodException setMessage() { - this.diagnostic = null; - return this; + /** + * Subclass of method check context class that implements strict method conversion. + * Strict method conversion checks compatibility between types using subtyping tests. + */ + class StrictMethodContext extends MethodCheckContext { + + public StrictMethodContext(MethodCheckHandler handler, boolean useVarargs, List undetvars, Warner rsWarner) { + super(handler, useVarargs, undetvars, rsWarner); + } + + public boolean compatible(Type found, Type req, Warner warn) { + return types.isSubtypeUnchecked(found, infer.asUndetType(req, undetvars), warn); + } + } + + /** + * Subclass of method check context class that implements loose method conversion. + * Loose method conversion checks compatibility between types using method conversion tests. + */ + class LooseMethodContext extends MethodCheckContext { + + public LooseMethodContext(MethodCheckHandler handler, boolean useVarargs, List undetvars, Warner rsWarner) { + super(handler, useVarargs, undetvars, rsWarner); + } + + public boolean compatible(Type found, Type req, Warner warn) { + return types.isConvertible(found, infer.asUndetType(req, undetvars), warn); + } + } + + /** + * Create a method check context to be used during method applicability check + */ + ResultInfo methodCheckResult(Type to, boolean allowBoxing, boolean useVarargs, + List undetvars, MethodCheckHandler methodHandler, Warner rsWarner) { + MethodCheckContext checkContext = allowBoxing ? + new LooseMethodContext(methodHandler, useVarargs, undetvars, rsWarner) : + new StrictMethodContext(methodHandler, useVarargs, undetvars, rsWarner); + return attr.new ResultInfo(VAL, to, checkContext) { + @Override + protected Type check(DiagnosticPosition pos, Type found) { + return super.check(pos, chk.checkNonVoid(pos, types.capture(types.upperBound(found)))); } - InapplicableMethodException setMessage(String key) { - this.diagnostic = key != null ? diags.fragment(key) : null; - return this; - } - InapplicableMethodException setMessage(String key, Object... args) { - this.diagnostic = key != null ? diags.fragment(key, args) : null; - return this; - } - InapplicableMethodException setMessage(JCDiagnostic diag) { - this.diagnostic = diag; - return this; - } + }; + } + + public static class InapplicableMethodException extends RuntimeException { + private static final long serialVersionUID = 0; + + JCDiagnostic diagnostic; + JCDiagnostic.Factory diags; - public JCDiagnostic getDiagnostic() { - return diagnostic; - } + InapplicableMethodException(JCDiagnostic.Factory diags) { + this.diagnostic = null; + this.diags = diags; + } + InapplicableMethodException setMessage() { + this.diagnostic = null; + return this; + } + InapplicableMethodException setMessage(String key) { + this.diagnostic = key != null ? diags.fragment(key) : null; + return this; } - private final InapplicableMethodException inapplicableMethodException; + InapplicableMethodException setMessage(String key, Object... args) { + this.diagnostic = key != null ? diags.fragment(key, args) : null; + return this; + } + InapplicableMethodException setMessage(JCDiagnostic diag) { + this.diagnostic = diag; + return this; + } + + public JCDiagnostic getDiagnostic() { + return diagnostic; + } + } + private final InapplicableMethodException inapplicableMethodException; /* *************************************************************************** * Symbol lookup @@ -1670,25 +1735,18 @@ steps = steps.tail; } if (sym.kind >= AMBIGUOUS) { - if (site.tsym.isPolymorphicSignatureGeneric()) { - //polymorphic receiver - synthesize new method symbol + //if nothing is found return the 'first' error + MethodResolutionPhase errPhase = + currentResolutionContext.firstErroneousResolutionPhase(); + sym = access(currentResolutionContext.resolutionCache.get(errPhase), + pos, location, site, name, true, argtypes, typeargtypes); + env.info.varArgs = errPhase.isVarargsRequired; + } else if (allowMethodHandles) { + MethodSymbol msym = (MethodSymbol)sym; + if (msym.isSignaturePolymorphic(types)) { env.info.varArgs = false; - sym = findPolymorphicSignatureInstance(env, - site, name, null, argtypes); + return findPolymorphicSignatureInstance(env, sym, argtypes); } - else { - //if nothing is found return the 'first' error - MethodResolutionPhase errPhase = - currentResolutionContext.firstErroneousResolutionPhase(); - sym = access(currentResolutionContext.resolutionCache.get(errPhase), - pos, location, site, name, true, argtypes, typeargtypes); - env.info.varArgs = errPhase.isVarargsRequired; - } - } else if (allowMethodHandles && sym.isPolymorphicSignatureGeneric()) { - //non-instantiated polymorphic signature - synthesize new method symbol - env.info.varArgs = false; - sym = findPolymorphicSignatureInstance(env, - site, name, (MethodSymbol)sym, argtypes); } return sym; } @@ -1701,40 +1759,25 @@ * Searches in a side table, not the main scope of the site. * This emulates the lookup process required by JSR 292 in JVM. * @param env Attribution environment - * @param site The original type from where the selection takes place. - * @param name The method's name. - * @param spMethod A template for the implicit method, or null. - * @param argtypes The required argument types. - * @param typeargtypes The required type arguments. + * @param spMethod signature polymorphic method - i.e. MH.invokeExact + * @param argtypes The required argument types */ - Symbol findPolymorphicSignatureInstance(Env env, Type site, - Name name, - MethodSymbol spMethod, // sig. poly. method or null if none + Symbol findPolymorphicSignatureInstance(Env env, + Symbol spMethod, List argtypes) { Type mtype = infer.instantiatePolymorphicSignatureInstance(env, - site, name, spMethod, argtypes); - long flags = ABSTRACT | HYPOTHETICAL | POLYMORPHIC_SIGNATURE | - (spMethod != null ? - spMethod.flags() & Flags.AccessFlags : - Flags.PUBLIC | Flags.STATIC); - Symbol m = null; - for (Scope.Entry e = polymorphicSignatureScope.lookup(name); - e.scope != null; - e = e.next()) { - Symbol sym = e.sym; - if (types.isSameType(mtype, sym.type) && - (sym.flags() & Flags.STATIC) == (flags & Flags.STATIC) && - types.isSameType(sym.owner.type, site)) { - m = sym; - break; + (MethodSymbol)spMethod, argtypes); + for (Symbol sym : polymorphicSignatureScope.getElementsByName(spMethod.name)) { + if (types.isSameType(mtype, sym.type)) { + return sym; } } - if (m == null) { - // create the desired method - m = new MethodSymbol(flags, name, mtype, site.tsym); - polymorphicSignatureScope.enter(m); - } - return m; + + // create the desired method + long flags = ABSTRACT | HYPOTHETICAL | spMethod.flags() & Flags.AccessFlags; + Symbol msym = new MethodSymbol(flags, spMethod.name, mtype, spMethod.owner); + polymorphicSignatureScope.enter(msym); + return msym; } /** Resolve a qualified method identifier, throw a fatal error if not diff -r 61eccc72f402 -r 122a0aede750 langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Wed Jul 05 18:07:54 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, 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 @@ -1320,10 +1320,6 @@ sym.flags_field |= PROPRIETARY; else proxies.append(proxy); - if (majorVersion >= V51.major && - proxy.type.tsym == syms.polymorphicSignatureType.tsym) { - sym.flags_field |= POLYMORPHIC_SIGNATURE; - } } annotate.later(new AnnotationCompleter(sym, proxies.toList())); } diff -r 61eccc72f402 -r 122a0aede750 langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Wed Jul 05 18:07:54 2017 +0200 @@ -983,12 +983,13 @@ t = lambdaExpressionOrStatement(variableDeclaratorId(mods, t), pos); break; } - } else { - Assert.check((mode & EXPR) != 0); + } else if ((mode & EXPR) != 0) { mode = EXPR; JCExpression e = term2Rest(t1, TreeInfo.shiftPrec); t = F.at(pos1).Binary(op, t, e); t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec))); + } else { + accept(GT); } } else if ((mode & TYPE) != 0 && (token.kind == IDENTIFIER || token.kind == ELLIPSIS)) { diff -r 61eccc72f402 -r 122a0aede750 langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Jul 05 18:07:54 2017 +0200 @@ -134,12 +134,6 @@ compiler.err.array.req.but.found=\ array required, but {0} found -compiler.err.assignment.from.super-bound=\ - assigning from wildcard {0} - -compiler.err.assignment.to.extends-bound=\ - assigning to wildcard {0} - compiler.err.attribute.value.must.be.constant=\ attribute value must be constant @@ -223,9 +217,6 @@ compiler.err.no.superclass=\ {0} has no superclass -compiler.err.wrong.target.for.polymorphic.signature.definition=\ - MethodHandle API building requires -target 7 runtimes or better; current is -target {0} - # 0: symbol, 1: type, 2: symbol, 3: type, 4: unused compiler.err.concrete.inheritance.conflict=\ methods {0} from {1} and {2} from {3} are inherited with the same signature @@ -779,25 +770,23 @@ compiler.err.undef.label=\ undefined label: {0} -compiler.err.undetermined.type=\ - cannot infer type arguments for {0} - -# 0: type, 1: message segment -compiler.err.undetermined.type.1=\ - cannot infer type arguments for {0};\n\ +# 0: list of type, 1: message segment +compiler.misc.invalid.inferred.types=\ + invalid inferred types for {0}\n\ reason: {1} -# 0: list of type, 1: message segment -compiler.err.invalid.inferred.types=\ - invalid inferred types for {0}; {1} - # 0: message segment, 1: unused compiler.err.cant.apply.diamond=\ cannot infer type arguments for {0} # 0: message segment or type, 1: message segment compiler.err.cant.apply.diamond.1=\ - cannot infer type arguments for {0};\n\ + cannot infer type arguments for {0}\n\ + reason: {1} + +# 0: message segment or type, 1: message segment +compiler.misc.cant.apply.diamond.1=\ + cannot infer type arguments for {0}\n\ reason: {1} compiler.err.unreachable.stmt=\ @@ -1503,11 +1492,15 @@ ##### -# 0: message segment, 1: type, 2: type +# 0: type, 1: type compiler.err.prob.found.req=\ - {0}\n\ - required: {2}\n\ - found: {1} + incompatible types\n\ + required: {1}\n\ + found: {0} + +# 0: message segment +compiler.err.prob.found.req.1=\ + incompatible types: {0} # 0: message segment, 1: type, 2: type compiler.warn.prob.found.req=\ @@ -1515,22 +1508,9 @@ required: {2}\n\ found: {1} -compiler.err.prob.found.req.1=\ - {0} {3}\n\ - required: {2}\n\ - found: {1} - -## The following are all possible strings for the first argument ({0}) of the -## above strings. -compiler.misc.incompatible.types=\ - incompatible types - -# 0: message segment -compiler.misc.incompatible.types.1=\ - incompatible types; {0} - +# 0: type, 1: type compiler.misc.inconvertible.types=\ - inconvertible types + {0} cannot be converted to {1} compiler.misc.possible.loss.of.precision=\ possible loss of precision @@ -1545,19 +1525,15 @@ compiler.misc.unchecked.cast.to.type=\ unchecked cast -compiler.misc.assignment.from.super-bound=\ - assignment from super-bound type {0} - -compiler.misc.assignment.to.extends-bound=\ - assignment to extends-bound type {0} - # compiler.err.star.expected=\ # ''*'' expected # compiler.err.no.elem.type=\ # \[\*\] cannot have a type +# 0: type compiler.misc.try.not.applicable.to.type=\ - try-with-resources not applicable to variable type + try-with-resources not applicable to variable type {0}\n\ + (expected a variable of type java.lang.AutoCloseable) ##### @@ -1592,8 +1568,11 @@ ## The following are all possible strings for the last argument of all those ## diagnostics whose key ends in ".1" + +# 0: type, 1: message segment compiler.misc.undetermined.type=\ - undetermined type + cannot infer type arguments for {0}\n\ + reason: {1} compiler.misc.type.variable.has.undetermined.type=\ type variable {0} has undetermined type diff -r 61eccc72f402 -r 122a0aede750 langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java --- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java Wed Jul 05 18:07:54 2017 +0200 @@ -1083,6 +1083,7 @@ public List catchers; public JCBlock finalizer; public List resources; + public boolean finallyCanCompleteNormally; protected JCTry(List resources, JCBlock body, List catchers, diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/6979683/TestCast6979683_BAD34.java.errlog --- a/langtools/test/tools/javac/6979683/TestCast6979683_BAD34.java.errlog Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/6979683/TestCast6979683_BAD34.java.errlog Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -TestCast6979683_BAD34.java:34:49: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.Number, boolean +TestCast6979683_BAD34.java:34:49: compiler.err.prob.found.req: java.lang.Number, boolean 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/6979683/TestCast6979683_BAD35.java.errlog --- a/langtools/test/tools/javac/6979683/TestCast6979683_BAD35.java.errlog Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/6979683/TestCast6979683_BAD35.java.errlog Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -TestCast6979683_BAD35.java:35:45: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.Number, int +TestCast6979683_BAD35.java:35:45: compiler.err.prob.found.req: java.lang.Number, int 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/6979683/TestCast6979683_BAD36.java.errlog --- a/langtools/test/tools/javac/6979683/TestCast6979683_BAD36.java.errlog Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/6979683/TestCast6979683_BAD36.java.errlog Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -TestCast6979683_BAD36.java:36:58: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.Comparable, int +TestCast6979683_BAD36.java:36:58: compiler.err.prob.found.req: java.lang.Comparable, int 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/6979683/TestCast6979683_BAD37.java.errlog --- a/langtools/test/tools/javac/6979683/TestCast6979683_BAD37.java.errlog Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/6979683/TestCast6979683_BAD37.java.errlog Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -TestCast6979683_BAD37.java:37:61: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), java.lang.Comparable, int +TestCast6979683_BAD37.java:37:61: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: java.lang.Comparable, int) 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/6979683/TestCast6979683_BAD38.java.errlog --- a/langtools/test/tools/javac/6979683/TestCast6979683_BAD38.java.errlog Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/6979683/TestCast6979683_BAD38.java.errlog Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -TestCast6979683_BAD38.java:38:62: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.Comparable, float +TestCast6979683_BAD38.java:38:62: compiler.err.prob.found.req: java.lang.Comparable, float 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/6979683/TestCast6979683_BAD39.java.errlog --- a/langtools/test/tools/javac/6979683/TestCast6979683_BAD39.java.errlog Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/6979683/TestCast6979683_BAD39.java.errlog Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -TestCast6979683_BAD39.java:39:53: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), java.lang.Number, char +TestCast6979683_BAD39.java:39:53: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: java.lang.Number, char) 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/Diagnostics/6722234/T6722234d_1.out --- a/langtools/test/tools/javac/Diagnostics/6722234/T6722234d_1.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/Diagnostics/6722234/T6722234d_1.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,3 +1,3 @@ -T6722234d.java:18:20: compiler.err.prob.found.req: (compiler.misc.incompatible.types), compiler.misc.intersection.type: 1, T6722234d.A +T6722234d.java:18:20: compiler.err.prob.found.req: compiler.misc.intersection.type: 1, T6722234d.A - compiler.misc.where.description.intersection: compiler.misc.intersection.type: 1,{(compiler.misc.where.intersection: compiler.misc.intersection.type: 1, java.lang.Object,T6722234d.I1,T6722234d.I2)} 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/Diagnostics/6722234/T6722234d_2.out --- a/langtools/test/tools/javac/Diagnostics/6722234/T6722234d_2.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/Diagnostics/6722234/T6722234d_2.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,3 +1,3 @@ -T6722234d.java:18:20: compiler.err.prob.found.req: (compiler.misc.incompatible.types), compiler.misc.intersection.type: 1, T6722234d.A +T6722234d.java:18:20: compiler.err.prob.found.req: compiler.misc.intersection.type: 1, T6722234d.A - compiler.misc.where.description.intersection: compiler.misc.intersection.type: 1,{(compiler.misc.where.intersection: compiler.misc.intersection.type: 1, Object,I1,I2)} 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/OverrideChecks/6400189/T6400189a.out --- a/langtools/test/tools/javac/OverrideChecks/6400189/T6400189a.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/OverrideChecks/6400189/T6400189a.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,4 +1,4 @@ T6400189a.java:14:35: compiler.warn.unchecked.call.mbr.of.raw.type: getAnnotation(java.lang.Class), java.lang.reflect.Constructor -T6400189a.java:14:35: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.annotation.Annotation, java.lang.annotation.Documented +T6400189a.java:14:35: compiler.err.prob.found.req: java.lang.annotation.Annotation, java.lang.annotation.Documented 1 error 1 warning diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/OverrideChecks/6400189/T6400189b.out --- a/langtools/test/tools/javac/OverrideChecks/6400189/T6400189b.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/OverrideChecks/6400189/T6400189b.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,4 +1,4 @@ T6400189b.java:24:24: compiler.warn.unchecked.call.mbr.of.raw.type: m(T6400189b), T6400189b.B -T6400189b.java:24:24: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.Object, java.lang.Integer +T6400189b.java:24:24: compiler.err.prob.found.req: java.lang.Object, java.lang.Integer 1 error 1 warning diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/StringsInSwitch/BadlyTypedLabel1.out --- a/langtools/test/tools/javac/StringsInSwitch/BadlyTypedLabel1.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/StringsInSwitch/BadlyTypedLabel1.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -BadlyTypedLabel1.java:13:14: compiler.err.prob.found.req: (compiler.misc.incompatible.types), int, java.lang.String +BadlyTypedLabel1.java:13:14: compiler.err.prob.found.req: int, java.lang.String 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/StringsInSwitch/BadlyTypedLabel2.out --- a/langtools/test/tools/javac/StringsInSwitch/BadlyTypedLabel2.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/StringsInSwitch/BadlyTypedLabel2.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -BadlyTypedLabel2.java:15:14: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.math.RoundingMode, java.lang.String +BadlyTypedLabel2.java:15:14: compiler.err.prob.found.req: java.math.RoundingMode, java.lang.String 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/T6326754.out --- a/langtools/test/tools/javac/T6326754.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/T6326754.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,6 +1,6 @@ T6326754.java:44:12: compiler.err.name.clash.same.erasure: TestConstructor(T), TestConstructor(K) T6326754.java:52:17: compiler.err.name.clash.same.erasure: setT(K), setT(T) -T6326754.java:64:18: compiler.err.prob.found.req: (compiler.misc.incompatible.types), T, T +T6326754.java:64:18: compiler.err.prob.found.req: T, T T6326754.java:70:11: compiler.err.cant.apply.symbol.1: kindname.method, setT, java.lang.Object, compiler.misc.no.args, kindname.class, TestC, (compiler.misc.arg.length.mismatch) - compiler.note.unchecked.filename: T6326754.java - compiler.note.unchecked.recompile diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/TryWithResources/TwrOnNonResource.out --- a/langtools/test/tools/javac/TryWithResources/TwrOnNonResource.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/TryWithResources/TwrOnNonResource.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,4 +1,4 @@ -TwrOnNonResource.java:12:30: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable -TwrOnNonResource.java:15:30: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable -TwrOnNonResource.java:18:30: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable +TwrOnNonResource.java:12:30: compiler.err.prob.found.req.1: (compiler.misc.try.not.applicable.to.type: TwrOnNonResource) +TwrOnNonResource.java:15:30: compiler.err.prob.found.req.1: (compiler.misc.try.not.applicable.to.type: TwrOnNonResource) +TwrOnNonResource.java:18:30: compiler.err.prob.found.req.1: (compiler.misc.try.not.applicable.to.type: TwrOnNonResource) 3 errors diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/cast/6270087/T6270087neg.out --- a/langtools/test/tools/javac/cast/6270087/T6270087neg.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/cast/6270087/T6270087neg.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -T6270087neg.java:36:29: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6270087neg.Foo, T6270087neg.Foo +T6270087neg.java:36:29: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: T6270087neg.Foo, T6270087neg.Foo) 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/cast/6557182/T6557182.out --- a/langtools/test/tools/javac/cast/6557182/T6557182.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/cast/6557182/T6557182.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,4 +1,4 @@ -T6557182.java:12:56: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T, java.lang.Comparable +T6557182.java:12:56: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: T, java.lang.Comparable) T6557182.java:16:56: compiler.warn.prob.found.req: (compiler.misc.unchecked.cast.to.type), T, java.lang.Comparable 1 error 1 warning diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/cast/6665356/T6665356.out --- a/langtools/test/tools/javac/cast/6665356/T6665356.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/cast/6665356/T6665356.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,8 +1,8 @@ -T6665356.java:31:55: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner -T6665356.java:35:58: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner -T6665356.java:39:65: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner -T6665356.java:43:57: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner -T6665356.java:47:60: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner -T6665356.java:51:55: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner -T6665356.java:55:58: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner +T6665356.java:31:55: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: T6665356.Outer.Inner, T6665356.Outer.Inner) +T6665356.java:35:58: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: T6665356.Outer.Inner, T6665356.Outer.Inner) +T6665356.java:39:65: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: T6665356.Outer.Inner, T6665356.Outer.Inner) +T6665356.java:43:57: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: T6665356.Outer.Inner, T6665356.Outer.Inner) +T6665356.java:47:60: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: T6665356.Outer.Inner, T6665356.Outer.Inner) +T6665356.java:51:55: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: T6665356.Outer.Inner, T6665356.Outer.Inner) +T6665356.java:55:58: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: T6665356.Outer.Inner, T6665356.Outer.Inner) 7 errors diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/cast/6795580/T6795580.out --- a/langtools/test/tools/javac/cast/6795580/T6795580.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/cast/6795580/T6795580.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,8 +1,8 @@ -T6795580.java:31:57: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6795580.Outer.Inner[], T6795580.Outer.Inner[] -T6795580.java:35:60: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6795580.Outer.Inner[], T6795580.Outer.Inner[] -T6795580.java:39:67: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6795580.Outer.Inner[], T6795580.Outer.Inner[] -T6795580.java:43:59: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6795580.Outer.Inner[], T6795580.Outer.Inner[] -T6795580.java:47:62: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6795580.Outer.Inner[], T6795580.Outer.Inner[] -T6795580.java:51:57: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6795580.Outer.Inner[], T6795580.Outer.Inner[] -T6795580.java:55:60: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6795580.Outer.Inner[], T6795580.Outer.Inner[] +T6795580.java:31:57: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: T6795580.Outer.Inner[], T6795580.Outer.Inner[]) +T6795580.java:35:60: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: T6795580.Outer.Inner[], T6795580.Outer.Inner[]) +T6795580.java:39:67: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: T6795580.Outer.Inner[], T6795580.Outer.Inner[]) +T6795580.java:43:59: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: T6795580.Outer.Inner[], T6795580.Outer.Inner[]) +T6795580.java:47:62: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: T6795580.Outer.Inner[], T6795580.Outer.Inner[]) +T6795580.java:51:57: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: T6795580.Outer.Inner[], T6795580.Outer.Inner[]) +T6795580.java:55:60: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: T6795580.Outer.Inner[], T6795580.Outer.Inner[]) 7 errors diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/cast/6932571/T6932571neg.out --- a/langtools/test/tools/javac/cast/6932571/T6932571neg.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/cast/6932571/T6932571neg.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -T6932571neg.java:39:19: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6932571neg.S, G +T6932571neg.java:39:19: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: T6932571neg.S, G) 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/cast/7005095/T7005095neg.out --- a/langtools/test/tools/javac/cast/7005095/T7005095neg.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/cast/7005095/T7005095neg.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -T7005095neg.java:13:25: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T7005095pos.FooImpl, T7005095pos.Foo +T7005095neg.java:13:25: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: T7005095pos.FooImpl, T7005095pos.Foo) 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/cast/7005671/T7005671.out --- a/langtools/test/tools/javac/cast/7005671/T7005671.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/cast/7005671/T7005671.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,17 +1,17 @@ -T7005671.java:12:26: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), byte[], X[] -T7005671.java:13:26: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), short[], X[] -T7005671.java:14:26: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), int[], X[] -T7005671.java:15:26: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), long[], X[] -T7005671.java:16:26: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), float[], X[] -T7005671.java:17:26: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), double[], X[] -T7005671.java:18:26: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), char[], X[] -T7005671.java:19:26: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), boolean[], X[] -T7005671.java:23:29: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), X[], byte[] -T7005671.java:24:30: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), X[], short[] -T7005671.java:25:28: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), X[], int[] -T7005671.java:26:29: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), X[], long[] -T7005671.java:27:30: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), X[], float[] -T7005671.java:28:31: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), X[], double[] -T7005671.java:29:29: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), X[], char[] -T7005671.java:30:32: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), X[], boolean[] +T7005671.java:12:26: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: byte[], X[]) +T7005671.java:13:26: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: short[], X[]) +T7005671.java:14:26: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: int[], X[]) +T7005671.java:15:26: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: long[], X[]) +T7005671.java:16:26: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: float[], X[]) +T7005671.java:17:26: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: double[], X[]) +T7005671.java:18:26: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: char[], X[]) +T7005671.java:19:26: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: boolean[], X[]) +T7005671.java:23:29: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: X[], byte[]) +T7005671.java:24:30: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: X[], short[]) +T7005671.java:25:28: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: X[], int[]) +T7005671.java:26:29: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: X[], long[]) +T7005671.java:27:30: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: X[], float[]) +T7005671.java:28:31: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: X[], double[]) +T7005671.java:29:29: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: X[], char[]) +T7005671.java:30:32: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: X[], boolean[]) 16 errors diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/diags/examples.not-yet.txt --- a/langtools/test/tools/javac/diags/examples.not-yet.txt Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/diags/examples.not-yet.txt Wed Jul 05 18:07:54 2017 +0200 @@ -1,8 +1,6 @@ compiler.err.already.annotated # internal compiler error? compiler.err.already.defined.this.unit # seems to be masked by compiler.err.duplicate.class compiler.err.annotation.value.not.allowable.type # cannot happen: precluded by complete type-specific tests -compiler.err.assignment.from.super-bound # DEAD -compiler.err.assignment.to.extends-bound # DEAD compiler.err.cant.apply.symbol compiler.err.cant.read.file # (apt.JavaCompiler?) compiler.err.cant.select.static.class.from.param.type @@ -24,7 +22,6 @@ compiler.err.no.encl.instance.of.type.in.scope # cannot occur; always followed by assert false; compiler.err.no.match.entry # UNUSED? compiler.err.not.annotation.type # cannot occur given preceding checkType -compiler.err.prob.found.req.1 # Check: DEAD, in unused method compiler.err.proc.bad.config.file # JavacProcessingEnvironment compiler.err.proc.cant.access # completion failure compiler.err.proc.cant.access.1 # completion failure, no stack trace @@ -38,12 +35,8 @@ compiler.err.stack.sim.error compiler.err.type.var.more.than.once # UNUSED compiler.err.type.var.more.than.once.in.result # UNUSED -compiler.err.undetermined.type compiler.err.unexpected.type compiler.err.unsupported.cross.fp.lit # Scanner: host system dependent -compiler.err.wrong.target.for.polymorphic.signature.definition # Transitional 292 -compiler.misc.assignment.from.super-bound -compiler.misc.assignment.to.extends-bound compiler.misc.bad.class.file.header # bad class file compiler.misc.bad.class.signature # bad class file compiler.misc.bad.const.pool.tag # bad class file @@ -88,7 +81,6 @@ compiler.misc.type.variable.has.undetermined.type compiler.misc.unable.to.access.file # ClassFile compiler.misc.undecl.type.var # ClassReader -compiler.misc.undetermined.type compiler.misc.unicode.str.not.supported # ClassReader compiler.misc.verbose.retro # UNUSED compiler.misc.verbose.retro.with # UNUSED diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/diags/examples/CantApplyDiamond1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/diags/examples/CantApplyDiamond1.java Wed Jul 05 18:07:54 2017 +0200 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2012, 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.prob.found.req.1 +// key: compiler.misc.cant.apply.diamond.1 +// key: compiler.misc.infer.no.conforming.instance.exists +// key: compiler.misc.diamond + +class CantApplyDiamond1 { + + CantApplyDiamond1(CantApplyDiamond1 lz) { } + + void test(CantApplyDiamond1 li) { + CantApplyDiamond1 ls = new CantApplyDiamond1<>(li); + } +} diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/diags/examples/IncompatibleTypes1.java --- a/langtools/test/tools/javac/diags/examples/IncompatibleTypes1.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/diags/examples/IncompatibleTypes1.java Wed Jul 05 18:07:54 2017 +0200 @@ -21,9 +21,8 @@ * questions. */ -// key: compiler.misc.incompatible.types.1 // key: compiler.misc.infer.no.conforming.instance.exists -// key: compiler.err.prob.found.req +// key: compiler.err.prob.found.req.1 class IncompatibleTypes1 { IncompatibleTypes1 m() { diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/diags/examples/InconvertibleTypes.java --- a/langtools/test/tools/javac/diags/examples/InconvertibleTypes.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/diags/examples/InconvertibleTypes.java Wed Jul 05 18:07:54 2017 +0200 @@ -22,7 +22,7 @@ */ // key: compiler.misc.inconvertible.types -// key: compiler.err.prob.found.req +// key: compiler.err.prob.found.req.1 class InconvertibleTypes { class Outer { diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/diags/examples/InvalidInferredTypes.java --- a/langtools/test/tools/javac/diags/examples/InvalidInferredTypes.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/diags/examples/InvalidInferredTypes.java Wed Jul 05 18:07:54 2017 +0200 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.invalid.inferred.types +// key: compiler.err.prob.found.req.1 +// key: compiler.misc.invalid.inferred.types // key: compiler.misc.inferred.do.not.conform.to.bounds import java.util.*; diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/diags/examples/PossibleLossPrecision.java --- a/langtools/test/tools/javac/diags/examples/PossibleLossPrecision.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/diags/examples/PossibleLossPrecision.java Wed Jul 05 18:07:54 2017 +0200 @@ -22,7 +22,7 @@ */ // key: compiler.misc.possible.loss.of.precision -// key: compiler.err.prob.found.req +// key: compiler.err.prob.found.req.1 class PossibleLossPrecision { long l; diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/diags/examples/ResourceNotApplicableToType.java --- a/langtools/test/tools/javac/diags/examples/ResourceNotApplicableToType.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/diags/examples/ResourceNotApplicableToType.java Wed Jul 05 18:07:54 2017 +0200 @@ -22,7 +22,7 @@ */ // key: compiler.misc.try.not.applicable.to.type -// key: compiler.err.prob.found.req +// key: compiler.err.prob.found.req.1 class ResourceNotApplicableToType { void m() { diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/diags/examples/UndeterminedType1.java --- a/langtools/test/tools/javac/diags/examples/UndeterminedType1.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/diags/examples/UndeterminedType1.java Wed Jul 05 18:07:54 2017 +0200 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.undetermined.type.1 +// key: compiler.err.prob.found.req.1 +// key: compiler.misc.undetermined.type // key: compiler.misc.no.unique.maximal.instance.exists class UndeterminedType1 { diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/diags/examples/WhereIntersection.java --- a/langtools/test/tools/javac/diags/examples/WhereIntersection.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/diags/examples/WhereIntersection.java Wed Jul 05 18:07:54 2017 +0200 @@ -24,7 +24,6 @@ // key: compiler.misc.where.intersection // key: compiler.misc.where.description.intersection // key: compiler.misc.intersection.type -// key: compiler.misc.incompatible.types // key: compiler.err.prob.found.req // options: -XDdiags=where // run: simple diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/generics/6207386/T6207386.out --- a/langtools/test/tools/javac/generics/6207386/T6207386.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/generics/6207386/T6207386.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -T6207386.java:13:30: compiler.err.prob.found.req: (compiler.misc.incompatible.types), X, T6207386.F +T6207386.java:13:30: compiler.err.prob.found.req: X, T6207386.F 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/generics/diamond/neg/Neg05.out --- a/langtools/test/tools/javac/generics/diamond/neg/Neg05.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/generics/diamond/neg/Neg05.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,19 +1,19 @@ Neg05.java:19:48: compiler.err.improperly.formed.type.inner.raw.param -Neg05.java:19:35: compiler.err.prob.found.req: (compiler.misc.incompatible.types), Neg05.Foo, Neg05.Foo +Neg05.java:19:35: compiler.err.prob.found.req: Neg05.Foo, Neg05.Foo Neg05.java:20:58: compiler.err.improperly.formed.type.inner.raw.param -Neg05.java:20:45: compiler.err.prob.found.req: (compiler.misc.incompatible.types), Neg05.Foo, Neg05.Foo +Neg05.java:20:45: compiler.err.prob.found.req: Neg05.Foo, Neg05.Foo Neg05.java:21:43: compiler.err.improperly.formed.type.inner.raw.param -Neg05.java:21:30: compiler.err.prob.found.req: (compiler.misc.incompatible.types), Neg05.Foo, Neg05.Foo +Neg05.java:21:30: compiler.err.prob.found.req: Neg05.Foo, Neg05.Foo Neg05.java:22:56: compiler.err.improperly.formed.type.inner.raw.param -Neg05.java:22:43: compiler.err.prob.found.req: (compiler.misc.incompatible.types), Neg05.Foo, Neg05.Foo +Neg05.java:22:43: compiler.err.prob.found.req: Neg05.Foo, Neg05.Foo Neg05.java:24:48: compiler.err.improperly.formed.type.inner.raw.param -Neg05.java:24:35: compiler.err.prob.found.req: (compiler.misc.incompatible.types), Neg05.Foo, Neg05.Foo +Neg05.java:24:35: compiler.err.prob.found.req: Neg05.Foo, Neg05.Foo Neg05.java:25:58: compiler.err.improperly.formed.type.inner.raw.param -Neg05.java:25:45: compiler.err.prob.found.req: (compiler.misc.incompatible.types), Neg05.Foo, Neg05.Foo +Neg05.java:25:45: compiler.err.prob.found.req: Neg05.Foo, Neg05.Foo Neg05.java:26:43: compiler.err.improperly.formed.type.inner.raw.param -Neg05.java:26:30: compiler.err.prob.found.req: (compiler.misc.incompatible.types), Neg05.Foo, Neg05.Foo +Neg05.java:26:30: compiler.err.prob.found.req: Neg05.Foo, Neg05.Foo Neg05.java:27:56: compiler.err.improperly.formed.type.inner.raw.param -Neg05.java:27:43: compiler.err.prob.found.req: (compiler.misc.incompatible.types), Neg05.Foo, Neg05.Foo +Neg05.java:27:43: compiler.err.prob.found.req: Neg05.Foo, Neg05.Foo Neg05.java:31:37: compiler.err.improperly.formed.type.inner.raw.param Neg05.java:32:47: compiler.err.improperly.formed.type.inner.raw.param Neg05.java:33:32: compiler.err.improperly.formed.type.inner.raw.param diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/generics/diamond/neg/Neg06.out --- a/langtools/test/tools/javac/generics/diamond/neg/Neg06.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/generics/diamond/neg/Neg06.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -Neg06.java:16:37: compiler.err.cant.apply.diamond.1: (compiler.misc.diamond: Neg06.CFoo), (compiler.misc.infer.no.conforming.instance.exists: X, Neg06.CFoo, Neg06.CSuperFoo) +Neg06.java:16:37: compiler.err.prob.found.req.1: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg06.CFoo), (compiler.misc.infer.no.conforming.instance.exists: X, Neg06.CFoo, Neg06.CSuperFoo)) 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/generics/diamond/neg/Neg10.out --- a/langtools/test/tools/javac/generics/diamond/neg/Neg10.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/generics/diamond/neg/Neg10.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -Neg10.java:16:22: compiler.err.prob.found.req: (compiler.misc.incompatible.types), Neg10.Foo, Neg10.Foo +Neg10.java:16:22: compiler.err.prob.found.req: Neg10.Foo, Neg10.Foo 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/generics/inference/6315770/T6315770.out --- a/langtools/test/tools/javac/generics/inference/6315770/T6315770.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/generics/inference/6315770/T6315770.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,3 +1,3 @@ -T6315770.java:16:42: compiler.err.undetermined.type.1: T6315770, (compiler.misc.no.unique.maximal.instance.exists: T, java.lang.String,java.lang.Integer,java.lang.Runnable) -T6315770.java:17:40: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.no.conforming.instance.exists: T, T6315770, T6315770)), T6315770, T6315770 +T6315770.java:16:42: compiler.err.prob.found.req.1: (compiler.misc.undetermined.type: T6315770, (compiler.misc.no.unique.maximal.instance.exists: T, java.lang.String,java.lang.Integer,java.lang.Runnable)) +T6315770.java:17:40: compiler.err.prob.found.req.1: (compiler.misc.infer.no.conforming.instance.exists: T, T6315770, T6315770) 2 errors diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/generics/inference/6638712/T6638712b.out --- a/langtools/test/tools/javac/generics/inference/6638712/T6638712b.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/generics/inference/6638712/T6638712b.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -T6638712b.java:14:21: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.no.conforming.instance.exists: T, T, java.lang.String)), T, java.lang.String +T6638712b.java:14:21: compiler.err.prob.found.req.1: (compiler.misc.infer.no.conforming.instance.exists: T, T, java.lang.String) 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/generics/inference/6638712/T6638712e.out --- a/langtools/test/tools/javac/generics/inference/6638712/T6638712e.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/generics/inference/6638712/T6638712e.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -T6638712e.java:17:27: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.no.conforming.instance.exists: X, T6638712e.Foo, T6638712e.Foo)), T6638712e.Foo, T6638712e.Foo +T6638712e.java:17:27: compiler.err.prob.found.req.1: (compiler.misc.infer.no.conforming.instance.exists: X, T6638712e.Foo, T6638712e.Foo) 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/generics/inference/6650759/T6650759m.out --- a/langtools/test/tools/javac/generics/inference/6650759/T6650759m.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/generics/inference/6650759/T6650759m.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -T6650759m.java:43:36: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.util.List, java.util.List +T6650759m.java:43:36: compiler.err.prob.found.req: java.util.List, java.util.List 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/generics/rawOverride/7062745/T7062745neg.out --- a/langtools/test/tools/javac/generics/rawOverride/7062745/T7062745neg.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/generics/rawOverride/7062745/T7062745neg.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -T7062745neg.java:16:36: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.Object, java.lang.Number +T7062745neg.java:16:36: compiler.err.prob.found.req: java.lang.Object, java.lang.Number 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/generics/wildcards/6886247/T6886247_2.out --- a/langtools/test/tools/javac/generics/wildcards/6886247/T6886247_2.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/generics/wildcards/6886247/T6886247_2.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -T6886247_2.java:35:28: compiler.err.prob.found.req: (compiler.misc.incompatible.types), compiler.misc.type.captureof: 1, ?, E +T6886247_2.java:35:28: compiler.err.prob.found.req: compiler.misc.type.captureof: 1, ?, E 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/multicatch/Neg06.out --- a/langtools/test/tools/javac/multicatch/Neg06.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/multicatch/Neg06.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,3 +1,3 @@ -Neg06.java:14:16: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.String, java.lang.Throwable -Neg06.java:14:25: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.Integer, java.lang.Throwable +Neg06.java:14:16: compiler.err.prob.found.req: java.lang.String, java.lang.Throwable +Neg06.java:14:25: compiler.err.prob.found.req: java.lang.Integer, java.lang.Throwable 2 errors diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/multicatch/Neg07.out --- a/langtools/test/tools/javac/multicatch/Neg07.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/multicatch/Neg07.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -Neg07.java:14:56: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.Class, java.lang.Class +Neg07.java:14:56: compiler.err.prob.found.req: java.lang.Class, java.lang.Class 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/parser/7157165/T7157165.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/parser/7157165/T7157165.java Wed Jul 05 18:07:54 2017 +0200 @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7157165 + * + * @summary Regression: code with disjunctive type crashes javac + * @compile/fail/ref=T7157165.out -XDrawDiagnostics T7157165.java + * + */ + +class T7157165 { + Foo foo1 = null; +} diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/parser/7157165/T7157165.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/parser/7157165/T7157165.out Wed Jul 05 18:07:54 2017 +0200 @@ -0,0 +1,4 @@ +T7157165.java:11:20: compiler.err.expected: > +T7157165.java:11:21: compiler.err.expected: ';' +T7157165.java:11:22: compiler.err.illegal.start.of.type +3 errors diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/processing/TestWarnErrorCount.java --- a/langtools/test/tools/javac/processing/TestWarnErrorCount.java Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/processing/TestWarnErrorCount.java Wed Jul 05 18:07:54 2017 +0200 @@ -327,7 +327,7 @@ Writer out = fo.openWriter(); try { out.write("class " + name + " {\n" - + (warn ? " int i = (int) 0;\n" : "") + + (warn ? " void m() throws Exception { try (AutoCloseable ac = null) { } }" : "") + (error ? " ERROR\n" : "") + "}\n"); } finally { diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/types/CastObjectToPrimitiveTest.out --- a/langtools/test/tools/javac/types/CastObjectToPrimitiveTest.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/types/CastObjectToPrimitiveTest.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,2 +1,2 @@ -CastObjectToPrimitiveTest.java:36:23: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), java.lang.Object, int +CastObjectToPrimitiveTest.java:36:23: compiler.err.prob.found.req.1: (compiler.misc.inconvertible.types: java.lang.Object, int) 1 error diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/varargs/6313164/T6313164.out --- a/langtools/test/tools/javac/varargs/6313164/T6313164.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/varargs/6313164/T6313164.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,6 +1,6 @@ T6313164.java:12:8: compiler.err.cant.apply.symbol.1: kindname.method, foo1, p1.A[], p1.B,p1.B, kindname.class, p1.B, (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164) -T6313164.java:14:13: compiler.err.invalid.inferred.types: X, (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164) -T6313164.java:15:13: compiler.err.invalid.inferred.types: X, (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164) +T6313164.java:14:13: compiler.err.prob.found.req.1: (compiler.misc.invalid.inferred.types: X, (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)) +T6313164.java:15:13: compiler.err.prob.found.req.1: (compiler.misc.invalid.inferred.types: X, (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)) - compiler.note.unchecked.filename: B.java - compiler.note.unchecked.recompile 3 errors diff -r 61eccc72f402 -r 122a0aede750 langtools/test/tools/javac/varargs/7097436/T7097436.out --- a/langtools/test/tools/javac/varargs/7097436/T7097436.out Wed Jul 05 18:07:49 2017 +0200 +++ b/langtools/test/tools/javac/varargs/7097436/T7097436.out Wed Jul 05 18:07:54 2017 +0200 @@ -1,6 +1,6 @@ T7097436.java:13:20: compiler.warn.varargs.unsafe.use.varargs.param: ls T7097436.java:14:25: compiler.warn.varargs.unsafe.use.varargs.param: ls -T7097436.java:15:20: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.util.List[], java.lang.String -T7097436.java:16:26: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.util.List[], java.lang.Integer[] +T7097436.java:15:20: compiler.err.prob.found.req: java.util.List[], java.lang.String +T7097436.java:16:26: compiler.err.prob.found.req: java.util.List[], java.lang.Integer[] 2 errors 2 warnings