Thu, 31 May 2012 17:44:04 +0100
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
1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu May 31 17:42:14 2012 +0100 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu May 31 17:44:04 2012 +0100 1.3 @@ -702,6 +702,13 @@ 1.4 return t; 1.5 } 1.6 1.7 + Type attribIdentAsEnumType(Env<AttrContext> env, JCIdent id) { 1.8 + Assert.check((env.enclClass.sym.flags() & ENUM) != 0); 1.9 + id.type = env.info.scope.owner.type; 1.10 + id.sym = env.info.scope.owner; 1.11 + return id.type; 1.12 + } 1.13 + 1.14 public void visitClassDef(JCClassDecl tree) { 1.15 // Local classes have not been entered yet, so we need to do it now: 1.16 if ((env.info.scope.owner.kind & (VAR | MTH)) != 0) 1.17 @@ -1657,7 +1664,10 @@ 1.18 1.19 // Attribute clazz expression and store 1.20 // symbol + type back into the attributed tree. 1.21 - Type clazztype = attribType(clazz, env); 1.22 + Type clazztype = TreeInfo.isEnumInit(env.tree) ? 1.23 + attribIdentAsEnumType(env, (JCIdent)clazz) : 1.24 + attribType(clazz, env); 1.25 + 1.26 clazztype = chk.checkDiamond(tree, clazztype); 1.27 chk.validate(clazz, localEnv); 1.28 if (tree.encl != null) {
2.1 --- a/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Thu May 31 17:42:14 2012 +0100 2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Thu May 31 17:44:04 2012 +0100 2.3 @@ -620,7 +620,11 @@ 2.4 DeferredLintHandler prevLintHandler = 2.5 chk.setDeferredLintHandler(deferredLintHandler.setPos(tree.pos())); 2.6 try { 2.7 - attr.attribType(tree.vartype, localEnv); 2.8 + if (TreeInfo.isEnumInit(tree)) { 2.9 + attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype); 2.10 + } else { 2.11 + attr.attribType(tree.vartype, localEnv); 2.12 + } 2.13 } finally { 2.14 chk.setDeferredLintHandler(prevLintHandler); 2.15 }
3.1 --- a/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Thu May 31 17:42:14 2012 +0100 3.2 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Thu May 31 17:44:04 2012 +0100 3.3 @@ -237,6 +237,15 @@ 3.4 } 3.5 } 3.6 3.7 + public static boolean isEnumInit(JCTree tree) { 3.8 + switch (tree.getTag()) { 3.9 + case VARDEF: 3.10 + return (((JCVariableDecl)tree).mods.flags & ENUM) != 0; 3.11 + default: 3.12 + return false; 3.13 + } 3.14 + } 3.15 + 3.16 /** 3.17 * Return true if the AST corresponds to a static select of the kind A.B 3.18 */
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/tools/javac/enum/7160084/T7160084a.java Thu May 31 17:44:04 2012 +0100 4.3 @@ -0,0 +1,60 @@ 4.4 +/* 4.5 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 + * 4.8 + * This code is free software; you can redistribute it and/or modify it 4.9 + * under the terms of the GNU General Public License version 2 only, as 4.10 + * published by the Free Software Foundation. 4.11 + * 4.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 4.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.15 + * version 2 for more details (a copy is included in the LICENSE file that 4.16 + * accompanied this code). 4.17 + * 4.18 + * You should have received a copy of the GNU General Public License version 4.19 + * 2 along with this work; if not, write to the Free Software Foundation, 4.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.21 + * 4.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4.23 + * or visit www.oracle.com if you need additional information or have any 4.24 + * questions. 4.25 + */ 4.26 + 4.27 +/* 4.28 + * @test 4.29 + * @bug 7160084 4.30 + * @summary javac fails to compile an apparently valid class/interface combination 4.31 + */ 4.32 +public class T7160084a { 4.33 + 4.34 + static int assertionCount = 0; 4.35 + 4.36 + static void assertTrue(boolean cond) { 4.37 + assertionCount++; 4.38 + if (!cond) { 4.39 + throw new AssertionError(); 4.40 + } 4.41 + } 4.42 + 4.43 + interface Intf { 4.44 + enum MyEnumA { 4.45 + AA(""), 4.46 + UNUSED(""); 4.47 + 4.48 + private MyEnumA(String s) { } 4.49 + } 4.50 + } 4.51 + 4.52 + enum MyEnumA implements Intf { 4.53 + AA(""); 4.54 + 4.55 + private MyEnumA(String s) { } 4.56 + } 4.57 + 4.58 + public static void main(String... args) { 4.59 + assertTrue(MyEnumA.values().length == 1); 4.60 + assertTrue(Intf.MyEnumA.values().length == 2); 4.61 + assertTrue(assertionCount == 2); 4.62 + } 4.63 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/tools/javac/enum/7160084/T7160084b.java Thu May 31 17:44:04 2012 +0100 5.3 @@ -0,0 +1,68 @@ 5.4 +/* 5.5 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.7 + * 5.8 + * This code is free software; you can redistribute it and/or modify it 5.9 + * under the terms of the GNU General Public License version 2 only, as 5.10 + * published by the Free Software Foundation. 5.11 + * 5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 5.15 + * version 2 for more details (a copy is included in the LICENSE file that 5.16 + * accompanied this code). 5.17 + * 5.18 + * You should have received a copy of the GNU General Public License version 5.19 + * 2 along with this work; if not, write to the Free Software Foundation, 5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 5.21 + * 5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 5.23 + * or visit www.oracle.com if you need additional information or have any 5.24 + * questions. 5.25 + */ 5.26 + 5.27 +/* 5.28 + * @test 5.29 + * @bug 7160084 5.30 + * @summary javac fails to compile an apparently valid class/interface combination 5.31 + */ 5.32 +public class T7160084b { 5.33 + 5.34 + static int assertionCount = 0; 5.35 + 5.36 + static void assertTrue(boolean cond) { 5.37 + assertionCount++; 5.38 + if (!cond) { 5.39 + throw new AssertionError(); 5.40 + } 5.41 + } 5.42 + 5.43 + interface Extras { 5.44 + static class Enums { 5.45 + static class Component { 5.46 + Component() { throw new RuntimeException("oops!"); } 5.47 + } 5.48 + } 5.49 + } 5.50 + 5.51 + interface Test { 5.52 + public class Enums { 5.53 + interface Widget { 5.54 + enum Component { X, Y }; 5.55 + } 5.56 + 5.57 + enum Component implements Widget, Extras { 5.58 + Z; 5.59 + }; 5.60 + 5.61 + public static void test() { 5.62 + assertTrue(Component.values().length == 1); 5.63 + } 5.64 + } 5.65 + } 5.66 + 5.67 + public static void main(String[] args) { 5.68 + Test.Enums.test(); 5.69 + assertTrue(assertionCount == 1); 5.70 + } 5.71 +}