提交 e0ea14d0 编写于 作者: V vromero

7199823: javac generates inner class that can't be verified

Reviewed-by: jjg, mcimadamore
上级 f1f305f0
...@@ -570,10 +570,19 @@ public class Lower extends TreeTranslator { ...@@ -570,10 +570,19 @@ public class Lower extends TreeTranslator {
* @param flags The class symbol's flags * @param flags The class symbol's flags
* @param owner The class symbol's owner * @param owner The class symbol's owner
*/ */
ClassSymbol makeEmptyClass(long flags, ClassSymbol owner) { JCClassDecl makeEmptyClass(long flags, ClassSymbol owner) {
return makeEmptyClass(flags, owner, null, true);
}
JCClassDecl makeEmptyClass(long flags, ClassSymbol owner, Name flatname,
boolean addToDefs) {
// Create class symbol. // Create class symbol.
ClassSymbol c = reader.defineClass(names.empty, owner); ClassSymbol c = reader.defineClass(names.empty, owner);
c.flatname = chk.localClassName(c); if (flatname != null) {
c.flatname = flatname;
} else {
c.flatname = chk.localClassName(c);
}
c.sourcefile = owner.sourcefile; c.sourcefile = owner.sourcefile;
c.completer = null; c.completer = null;
c.members_field = new Scope(c); c.members_field = new Scope(c);
...@@ -597,9 +606,8 @@ public class Lower extends TreeTranslator { ...@@ -597,9 +606,8 @@ public class Lower extends TreeTranslator {
cdef.type = c.type; cdef.type = c.type;
// Append class definition tree to owner's definitions. // Append class definition tree to owner's definitions.
odef.defs = odef.defs.prepend(cdef); if (addToDefs) odef.defs = odef.defs.prepend(cdef);
return cdef;
return c;
} }
/************************************************************************** /**************************************************************************
...@@ -706,7 +714,7 @@ public class Lower extends TreeTranslator { ...@@ -706,7 +714,7 @@ public class Lower extends TreeTranslator {
* and synthethise a class (with makeEmptyClass) if one is not available. * and synthethise a class (with makeEmptyClass) if one is not available.
* However, there is a small possibility that an existing class will not * However, there is a small possibility that an existing class will not
* be generated as expected if it is inside a conditional with a constant * be generated as expected if it is inside a conditional with a constant
* expression. If that is found to be the case, create an empty class here. * expression. If that is found to be the case, create an empty class tree here.
*/ */
private void checkAccessConstructorTags() { private void checkAccessConstructorTags() {
for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) { for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
...@@ -714,14 +722,10 @@ public class Lower extends TreeTranslator { ...@@ -714,14 +722,10 @@ public class Lower extends TreeTranslator {
if (isTranslatedClassAvailable(c)) if (isTranslatedClassAvailable(c))
continue; continue;
// Create class definition tree. // Create class definition tree.
JCClassDecl cdef = make.ClassDef( JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC,
make.Modifiers(STATIC | SYNTHETIC), names.empty, c.outermostClass(), c.flatname, false);
List.<JCTypeParameter>nil(), swapAccessConstructorTag(c, cdec.sym);
null, List.<JCExpression>nil(), List.<JCTree>nil()); translated.append(cdec);
cdef.sym = c;
cdef.type = c.type;
// add it to the list of classes to be generated
translated.append(cdef);
} }
} }
// where // where
...@@ -735,6 +739,19 @@ public class Lower extends TreeTranslator { ...@@ -735,6 +739,19 @@ public class Lower extends TreeTranslator {
return false; return false;
} }
void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) {
for (MethodSymbol methodSymbol : accessConstrs.values()) {
Assert.check(methodSymbol.type.hasTag(METHOD));
MethodType oldMethodType =
(MethodType)methodSymbol.type;
if (oldMethodType.argtypes.head.tsym == oldCTag)
methodSymbol.type =
types.createMethodTypeWithParameters(oldMethodType,
oldMethodType.getParameterTypes().tail
.prepend(newCTag.erasure(types)));
}
}
/************************************************************************** /**************************************************************************
* Access methods * Access methods
*************************************************************************/ *************************************************************************/
...@@ -1211,7 +1228,7 @@ public class Lower extends TreeTranslator { ...@@ -1211,7 +1228,7 @@ public class Lower extends TreeTranslator {
"1"); "1");
ClassSymbol ctag = chk.compiled.get(flatname); ClassSymbol ctag = chk.compiled.get(flatname);
if (ctag == null) if (ctag == null)
ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass); ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass).sym;
// keep a record of all tags, to verify that all are generated as required // keep a record of all tags, to verify that all are generated as required
accessConstrTags = accessConstrTags.prepend(ctag); accessConstrTags = accessConstrTags.prepend(ctag);
return ctag; return ctag;
...@@ -1778,7 +1795,7 @@ public class Lower extends TreeTranslator { ...@@ -1778,7 +1795,7 @@ public class Lower extends TreeTranslator {
if (e.sym.kind == TYP && if (e.sym.kind == TYP &&
e.sym.name == names.empty && e.sym.name == names.empty &&
(e.sym.flags() & INTERFACE) == 0) return (ClassSymbol) e.sym; (e.sym.flags() & INTERFACE) == 0) return (ClassSymbol) e.sym;
return makeEmptyClass(STATIC | SYNTHETIC, clazz); return makeEmptyClass(STATIC | SYNTHETIC, clazz).sym;
} }
/** Return symbol for "class$" method. If there is no method definition /** Return symbol for "class$" method. If there is no method definition
......
/*
* Copyright (c) 2012, 2013, 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 7199823
* @summary javac generates inner class that can't be verified
* @run main InnerClassCannotBeVerified
*/
import java.util.Arrays;
import javax.tools.JavaFileObject;
import java.net.URI;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler;
import com.sun.source.util.JavacTask;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.ConstantPoolException;
import java.io.File;
import java.io.IOException;
public class InnerClassCannotBeVerified {
private static final String errorMessage =
"Compile error while compiling the following source:\n";
public static void main(String... args) throws Exception {
new InnerClassCannotBeVerified().run();
}
void run() throws Exception {
JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
JavaSource source = new JavaSource();
JavacTask ct = (JavacTask)comp.getTask(null, null, null,
null, null, Arrays.asList(source));
try {
if (!ct.call()) {
throw new AssertionError(errorMessage +
source.getCharContent(true));
}
} catch (Throwable ex) {
throw new AssertionError(errorMessage +
source.getCharContent(true));
}
check();
}
private void check() throws IOException, ConstantPoolException {
File file = new File("Test$1.class");
ClassFile classFile = ClassFile.read(file);
boolean inheritsFromObject =
classFile.getSuperclassName().equals("java/lang/Object");
boolean implementsNoInterface = classFile.interfaces.length == 0;
boolean noMethods = classFile.methods.length == 0;
if (!(inheritsFromObject &&
implementsNoInterface &&
noMethods)) {
throw new AssertionError("The inner classes reused as " +
"access constructor tag for this code must be empty");
}
}
class JavaSource extends SimpleJavaFileObject {
String internalSource =
"public class Test {\n" +
" private static class Foo {}\n" +
" public static void main(String[] args){ \n" +
" new Foo();\n" +
" if(false) {\n" +
" new Runnable() {\n" +
" @Override\n" +
" public void run() {\n" +
" System.out.println();\n" +
" }\n" +
" }.run();\n" +
" }\n" +
" }\n" +
"}";
public JavaSource() {
super(URI.create("Test.java"), JavaFileObject.Kind.SOURCE);
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return internalSource;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册