提交 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 {
* @param flags The class symbol's flags
* @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.
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.completer = null;
c.members_field = new Scope(c);
......@@ -597,9 +606,8 @@ public class Lower extends TreeTranslator {
cdef.type = c.type;
// Append class definition tree to owner's definitions.
odef.defs = odef.defs.prepend(cdef);
return c;
if (addToDefs) odef.defs = odef.defs.prepend(cdef);
return cdef;
}
/**************************************************************************
......@@ -706,7 +714,7 @@ public class Lower extends TreeTranslator {
* and synthethise a class (with makeEmptyClass) if one is not available.
* 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
* 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() {
for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
......@@ -714,14 +722,10 @@ public class Lower extends TreeTranslator {
if (isTranslatedClassAvailable(c))
continue;
// Create class definition tree.
JCClassDecl cdef = make.ClassDef(
make.Modifiers(STATIC | SYNTHETIC), names.empty,
List.<JCTypeParameter>nil(),
null, List.<JCExpression>nil(), List.<JCTree>nil());
cdef.sym = c;
cdef.type = c.type;
// add it to the list of classes to be generated
translated.append(cdef);
JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC,
c.outermostClass(), c.flatname, false);
swapAccessConstructorTag(c, cdec.sym);
translated.append(cdec);
}
}
// where
......@@ -735,6 +739,19 @@ public class Lower extends TreeTranslator {
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
*************************************************************************/
......@@ -1211,7 +1228,7 @@ public class Lower extends TreeTranslator {
"1");
ClassSymbol ctag = chk.compiled.get(flatname);
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
accessConstrTags = accessConstrTags.prepend(ctag);
return ctag;
......@@ -1778,7 +1795,7 @@ public class Lower extends TreeTranslator {
if (e.sym.kind == TYP &&
e.sym.name == names.empty &&
(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
......
/*
* 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.
先完成此消息的编辑!
想要评论请 注册