8272564: Incorrect attribution of method invocations of Object methods on interfaces
Reviewed-by: jlaskey, mcimadamore, vromero
This commit is contained in:
parent
a914ee7216
commit
a5080effc7
@ -2590,7 +2590,7 @@ public class Attr extends JCTree.Visitor {
|
||||
//where
|
||||
Type adjustMethodReturnType(Symbol msym, Type qualifierType, Name methodName, List<Type> argtypes, Type restype) {
|
||||
if (msym != null &&
|
||||
msym.owner == syms.objectType.tsym &&
|
||||
(msym.owner == syms.objectType.tsym || msym.owner.isInterface()) &&
|
||||
methodName == names.getClass &&
|
||||
argtypes.isEmpty()) {
|
||||
// as a special case, x.getClass() has type Class<? extends |X|>
|
||||
|
@ -469,7 +469,7 @@ public class Resolve {
|
||||
return true;
|
||||
else {
|
||||
Symbol s2 = ((MethodSymbol)sym).implementation(site.tsym, types, true);
|
||||
return (s2 == null || s2 == sym || sym.owner == s2.owner ||
|
||||
return (s2 == null || s2 == sym || sym.owner == s2.owner || (sym.owner.isInterface() && s2.owner == syms.objectType.tsym) ||
|
||||
!types.isSubSignature(types.memberType(site, s2), types.memberType(site, sym)));
|
||||
}
|
||||
}
|
||||
@ -1854,7 +1854,8 @@ public class Resolve {
|
||||
List<Type>[] itypes = (List<Type>[])new List[] { List.<Type>nil(), List.<Type>nil() };
|
||||
|
||||
InterfaceLookupPhase iphase = InterfaceLookupPhase.ABSTRACT_OK;
|
||||
for (TypeSymbol s : superclasses(intype)) {
|
||||
boolean isInterface = site.tsym.isInterface();
|
||||
for (TypeSymbol s : isInterface ? List.of(intype.tsym) : superclasses(intype)) {
|
||||
bestSoFar = findMethodInScope(env, site, name, argtypes, typeargtypes,
|
||||
s.members(), bestSoFar, allowBoxing, useVarargs, true);
|
||||
if (name == names.init) return bestSoFar;
|
||||
@ -1892,6 +1893,19 @@ public class Resolve {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isInterface && bestSoFar.kind.isResolutionError()) {
|
||||
bestSoFar = findMethodInScope(env, site, name, argtypes, typeargtypes,
|
||||
syms.objectType.tsym.members(), bestSoFar, allowBoxing, useVarargs, true);
|
||||
if (bestSoFar.kind.isValid()) {
|
||||
Symbol baseSymbol = bestSoFar;
|
||||
bestSoFar = new MethodSymbol(bestSoFar.flags_field, bestSoFar.name, bestSoFar.type, intype.tsym) {
|
||||
@Override
|
||||
public Symbol baseSymbol() {
|
||||
return baseSymbol;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
return bestSoFar;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8012929 8243074 8266281
|
||||
* @bug 8012929 8243074 8266281 8272564
|
||||
* @summary Trees.getElement should work not only for declaration trees, but also for use-trees
|
||||
* @modules jdk.compiler
|
||||
* @build TestGetElementReference
|
||||
|
@ -37,6 +37,10 @@ public class TestGetElementReferenceData {
|
||||
target(TestGetElementReferenceData :: test/*getElement:METHOD:test.nested.TestGetElementReferenceData.test()*/);
|
||||
Object/*getElement:CLASS:java.lang.Object*/ o = null;
|
||||
if (o/*getElement:LOCAL_VARIABLE:o*/ instanceof String/*getElement:CLASS:java.lang.String*/ str/*getElement:BINDING_VARIABLE:str*/) ;
|
||||
I i = null;
|
||||
i.toString/*getElement:METHOD:test.nested.TestGetElementReferenceData.I.toString()*/();
|
||||
J j = null;
|
||||
j.toString/*getElement:METHOD:test.nested.TestGetElementReferenceData.I.toString()*/();
|
||||
}
|
||||
private static void target(Runnable r) { r.run(); }
|
||||
public static class Base {
|
||||
@ -50,4 +54,8 @@ public class TestGetElementReferenceData {
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface TypeAnnotation {
|
||||
}
|
||||
interface I {
|
||||
public String toString();
|
||||
}
|
||||
interface J extends I {}
|
||||
}
|
||||
|
75
test/langtools/tools/javac/api/TestIsAccessible.java
Normal file
75
test/langtools/tools/javac/api/TestIsAccessible.java
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2015, 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 8272564
|
||||
* @summary Verify accessibility of Object-based methods inherited from super interfaces.
|
||||
* @modules jdk.compiler
|
||||
*/
|
||||
|
||||
import com.sun.source.tree.CompilationUnitTree;
|
||||
import com.sun.source.tree.Scope;
|
||||
import com.sun.source.util.JavacTask;
|
||||
import com.sun.source.util.TreePath;
|
||||
import com.sun.source.util.Trees;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.ToolProvider;
|
||||
|
||||
public class TestIsAccessible {
|
||||
public static void main(String[] args) throws Exception {
|
||||
final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
|
||||
assert tool != null;
|
||||
final JavacTask ct = (JavacTask)tool.getTask(null, null, null, null, null, Arrays.asList(new MyFileObject()));
|
||||
|
||||
CompilationUnitTree cut = ct.parse().iterator().next();
|
||||
TreePath tp = new TreePath(new TreePath(cut), cut.getTypeDecls().get(0));
|
||||
Scope s = Trees.instance(ct).getScope(tp);
|
||||
TypeElement name = ct.getElements().getTypeElement("javax.lang.model.element.Name");
|
||||
Trees trees = Trees.instance(ct);
|
||||
|
||||
if (trees.isAccessible(s, name)) {
|
||||
for (Element member : ct.getElements().getAllMembers(name)) {
|
||||
if (!trees.isAccessible(s, member, (DeclaredType) name.asType())) {
|
||||
throw new IllegalStateException("Inaccessible Name member: " + member);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class MyFileObject extends SimpleJavaFileObject {
|
||||
public MyFileObject() {
|
||||
super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
|
||||
}
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
|
||||
return "public class Test { }";
|
||||
}
|
||||
}
|
||||
}
|
79
test/langtools/tools/javac/resolve/NoObjectToString.java
Normal file
79
test/langtools/tools/javac/resolve/NoObjectToString.java
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 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 8272564
|
||||
* @summary Correct resolution of toString() (and other similar calls) on interfaces
|
||||
* @modules jdk.jdeps/com.sun.tools.classfile
|
||||
* @compile NoObjectToString.java
|
||||
* @run main NoObjectToString
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import com.sun.tools.classfile.*;
|
||||
import com.sun.tools.classfile.ConstantPool.CONSTANT_Methodref_info;
|
||||
|
||||
public class NoObjectToString {
|
||||
public static void main(String... args) throws Exception {
|
||||
NoObjectToString c = new NoObjectToString();
|
||||
c.run(args);
|
||||
}
|
||||
|
||||
void run(String... args) throws Exception {
|
||||
//Verify there are no references to Object.toString() in a Test:
|
||||
InputStream in = NoObjectToString.class.getResourceAsStream("NoObjectToString$Test.class");
|
||||
try {
|
||||
ClassFile cf = ClassFile.read(in);
|
||||
for (ConstantPool.CPInfo cpinfo: cf.constant_pool.entries()) {
|
||||
if (cpinfo.getTag() == ConstantPool.CONSTANT_Methodref) {
|
||||
CONSTANT_Methodref_info ref = (CONSTANT_Methodref_info) cpinfo;
|
||||
String methodDesc = ref.getClassInfo().getName() + "." + ref.getNameAndTypeInfo().getName() + ":" + ref.getNameAndTypeInfo().getType();
|
||||
|
||||
if ("java/lang/Object.toString:()Ljava/lang/String;".equals(methodDesc)) {
|
||||
throw new AssertionError("Found call to j.l.Object.toString");
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ConstantPoolException ignore) {
|
||||
throw new AssertionError(ignore);
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
void test(I i, J j, K k) {
|
||||
i.toString();
|
||||
j.toString();
|
||||
k.toString();
|
||||
}
|
||||
}
|
||||
|
||||
interface I {
|
||||
public String toString();
|
||||
}
|
||||
interface J extends I {}
|
||||
interface K {}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user