7160084: javac fails to compile an apparently valid class/interface combination
Summary: javac generates wrong syntetized trees for nested enum constants
Reviewed-by: dlsmith, jjg
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu May 31 17:42:14 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu May 31 17:44:04 2012 +0100
@@ -702,6 +702,13 @@
return t;
}
+ Type attribIdentAsEnumType(Env<AttrContext> env, JCIdent id) {
+ Assert.check((env.enclClass.sym.flags() & ENUM) != 0);
+ id.type = env.info.scope.owner.type;
+ id.sym = env.info.scope.owner;
+ return id.type;
+ }
+
public void visitClassDef(JCClassDecl tree) {
// Local classes have not been entered yet, so we need to do it now:
if ((env.info.scope.owner.kind & (VAR | MTH)) != 0)
@@ -1657,7 +1664,10 @@
// Attribute clazz expression and store
// symbol + type back into the attributed tree.
- Type clazztype = attribType(clazz, env);
+ Type clazztype = TreeInfo.isEnumInit(env.tree) ?
+ attribIdentAsEnumType(env, (JCIdent)clazz) :
+ attribType(clazz, env);
+
clazztype = chk.checkDiamond(tree, clazztype);
chk.validate(clazz, localEnv);
if (tree.encl != null) {
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Thu May 31 17:42:14 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Thu May 31 17:44:04 2012 +0100
@@ -620,7 +620,11 @@
DeferredLintHandler prevLintHandler =
chk.setDeferredLintHandler(deferredLintHandler.setPos(tree.pos()));
try {
- attr.attribType(tree.vartype, localEnv);
+ if (TreeInfo.isEnumInit(tree)) {
+ attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype);
+ } else {
+ attr.attribType(tree.vartype, localEnv);
+ }
} finally {
chk.setDeferredLintHandler(prevLintHandler);
}
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Thu May 31 17:42:14 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Thu May 31 17:44:04 2012 +0100
@@ -237,6 +237,15 @@
}
}
+ public static boolean isEnumInit(JCTree tree) {
+ switch (tree.getTag()) {
+ case VARDEF:
+ return (((JCVariableDecl)tree).mods.flags & ENUM) != 0;
+ default:
+ return false;
+ }
+ }
+
/**
* Return true if the AST corresponds to a static select of the kind A.B
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/enum/7160084/T7160084a.java Thu May 31 17:44:04 2012 +0100
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 7160084
+ * @summary javac fails to compile an apparently valid class/interface combination
+ */
+public class T7160084a {
+
+ static int assertionCount = 0;
+
+ static void assertTrue(boolean cond) {
+ assertionCount++;
+ if (!cond) {
+ throw new AssertionError();
+ }
+ }
+
+ interface Intf {
+ enum MyEnumA {
+ AA(""),
+ UNUSED("");
+
+ private MyEnumA(String s) { }
+ }
+ }
+
+ enum MyEnumA implements Intf {
+ AA("");
+
+ private MyEnumA(String s) { }
+ }
+
+ public static void main(String... args) {
+ assertTrue(MyEnumA.values().length == 1);
+ assertTrue(Intf.MyEnumA.values().length == 2);
+ assertTrue(assertionCount == 2);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/enum/7160084/T7160084b.java Thu May 31 17:44:04 2012 +0100
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 7160084
+ * @summary javac fails to compile an apparently valid class/interface combination
+ */
+public class T7160084b {
+
+ static int assertionCount = 0;
+
+ static void assertTrue(boolean cond) {
+ assertionCount++;
+ if (!cond) {
+ throw new AssertionError();
+ }
+ }
+
+ interface Extras {
+ static class Enums {
+ static class Component {
+ Component() { throw new RuntimeException("oops!"); }
+ }
+ }
+ }
+
+ interface Test {
+ public class Enums {
+ interface Widget {
+ enum Component { X, Y };
+ }
+
+ enum Component implements Widget, Extras {
+ Z;
+ };
+
+ public static void test() {
+ assertTrue(Component.values().length == 1);
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ Test.Enums.test();
+ assertTrue(assertionCount == 1);
+ }
+}