diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 617d8ca7077..1465ea652b1 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -1982,7 +1982,7 @@ public class Attr extends JCTree.Visitor { twrResult.check(resource, resource.type); //check that resource type cannot throw InterruptedException - checkAutoCloseable(resource.pos(), localEnv, resource.type); + checkAutoCloseable(localEnv, resource, true); VarSymbol var = ((JCVariableDecl) resource).sym; @@ -2031,7 +2031,9 @@ public class Attr extends JCTree.Visitor { } } - void checkAutoCloseable(DiagnosticPosition pos, Env env, Type resource) { + void checkAutoCloseable(Env env, JCTree tree, boolean useSite) { + DiagnosticPosition pos = tree.pos(); + Type resource = tree.type; if (!resource.isErroneous() && types.asSuper(resource, syms.autoCloseableType.tsym) != null && !types.isSameType(resource, syms.autoCloseableType)) { // Don't emit warning for AutoCloseable itself @@ -2049,9 +2051,15 @@ public class Attr extends JCTree.Visitor { log.popDiagnosticHandler(discardHandler); } if (close.kind == MTH && - close.overrides(syms.autoCloseableClose, resource.tsym, types, true) && + (useSite || close.owner != syms.autoCloseableType.tsym) && + ((MethodSymbol)close).binaryOverrides(syms.autoCloseableClose, resource.tsym, types) && chk.isHandled(syms.interruptedExceptionType, types.memberType(resource, close).getThrownTypes())) { - log.warning(pos, LintWarnings.TryResourceThrowsInterruptedExc(resource)); + if (!useSite && close.owner == resource.tsym) { + log.warning(TreeInfo.diagnosticPositionFor(close, tree), + LintWarnings.TryResourceCanThrowInterruptedExc(resource)); + } else { + log.warning(pos, LintWarnings.TryResourceThrowsInterruptedExc(resource)); + } } } } @@ -5649,7 +5657,7 @@ public class Attr extends JCTree.Visitor { chk.checkImplementations(tree); //check that a resource implementing AutoCloseable cannot throw InterruptedException - checkAutoCloseable(tree.pos(), env, c.type); + checkAutoCloseable(env, tree, false); for (List l = tree.defs; l.nonEmpty(); l = l.tail) { // Attribute declaration diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index d6358f6075d..4e034ff1bc8 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -2368,6 +2368,11 @@ compiler.warn.try.resource.not.referenced=\ compiler.warn.try.resource.throws.interrupted.exc=\ auto-closeable resource {0} has a member method close() that could throw InterruptedException +# 0: type +# lint: try +compiler.warn.try.resource.can.throw.interrupted.exc=\ + close() method can throw InterruptedException in auto-closeable class {0} + # lint: unchecked compiler.warn.unchecked.assign=\ unchecked assignment: {0} to {1} diff --git a/test/langtools/tools/javac/TryWithResources/InterruptedExceptionTest.java b/test/langtools/tools/javac/TryWithResources/InterruptedExceptionTest.java index 25dae2cc668..05317b00492 100644 --- a/test/langtools/tools/javac/TryWithResources/InterruptedExceptionTest.java +++ b/test/langtools/tools/javac/TryWithResources/InterruptedExceptionTest.java @@ -228,7 +228,8 @@ public class InterruptedExceptionTest { public void report(Diagnostic diagnostic) { if (diagnostic.getKind() == Diagnostic.Kind.WARNING && - diagnostic.getCode().contains("try.resource.throws.interrupted.exc")) { + (diagnostic.getCode().contains("try.resource.throws.interrupted.exc") || + diagnostic.getCode().contains("try.resource.can.throw.interrupted.exc"))) { tryWarnFound++; } } diff --git a/test/langtools/tools/javac/TryWithResources/InterruptedExceptionTest2.java b/test/langtools/tools/javac/TryWithResources/InterruptedExceptionTest2.java new file mode 100644 index 00000000000..396823789fd --- /dev/null +++ b/test/langtools/tools/javac/TryWithResources/InterruptedExceptionTest2.java @@ -0,0 +1,256 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8155591 + * @summary Verify cases where no AutoCloseable InterruptedException warning should be generated + * @compile/ref=InterruptedExceptionTest2.out -XDrawDiagnostics -Xlint:try InterruptedExceptionTest2.java + */ + +import java.util.function.Supplier; + +// Here's an interface and a class that we can inherit declaring offending close() methods + +interface HasClose { + void close() throws Exception; +} + +class WithConcreteClose { + public void close() throws Exception { } +} + +abstract class WithAbstractClose { + public abstract void close() throws Exception; +} + +// Interface declaration tests + +interface InterruptedExceptionTest_I1 extends AutoCloseable { +} + +interface InterruptedExceptionTest_I2 extends AutoCloseable { + @Override void close(); +} + +interface InterruptedExceptionTest_I3 extends AutoCloseable { + @Override void close() throws InterruptedException; // warning here +} + +interface InterruptedExceptionTest_I4 extends AutoCloseable { + @Override void close() throws Exception; // warning here +} + +interface InterruptedExceptionTest_I5 extends AutoCloseable { + @Override default void close() { } +} + +interface InterruptedExceptionTest_I6 extends AutoCloseable { + @Override default void close() throws InterruptedException { } // warning here +} + +interface InterruptedExceptionTest_I7 extends AutoCloseable { + @Override default void close() throws Exception { } // warning here +} + +interface InterruptedExceptionTest_I8 extends HasClose, AutoCloseable { +} + +interface InterruptedExceptionTest_I9 extends HasClose, AutoCloseable { + @Override void close(); +} + +// Abstract class declaration tests + +abstract class InterruptedExceptionTest_C1 implements AutoCloseable { +} + +abstract class InterruptedExceptionTest_C2 implements AutoCloseable { + @Override public abstract void close(); +} + +abstract class InterruptedExceptionTest_C3 implements AutoCloseable { + @Override public abstract void close() throws InterruptedException; // warning here +} + +abstract class InterruptedExceptionTest_C4 implements AutoCloseable { + @Override public abstract void close() throws Exception; // warning here +} + +abstract class InterruptedExceptionTest_C5 implements AutoCloseable { + @Override public void close() { } +} + +abstract class InterruptedExceptionTest_C6 implements AutoCloseable { + @Override public void close() throws InterruptedException { } // warning here +} + +abstract class InterruptedExceptionTest_C7 implements AutoCloseable { + @Override public void close() throws Exception { } // warning here +} + +abstract class InterruptedExceptionTest_C8 implements HasClose, AutoCloseable { +} + +abstract class InterruptedExceptionTest_C9 implements HasClose, AutoCloseable { + @Override public void close() { } +} + +abstract class InterruptedExceptionTest_C10 extends WithConcreteClose implements AutoCloseable { // warning here +} + +abstract class InterruptedExceptionTest_C11 extends WithAbstractClose implements AutoCloseable { +} + +// Interface use site tests + +class UseSite_I1 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_I1 t = s.get()) { // warning here + t.hashCode(); + } + } +} + +class UseSite_I2 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_I2 t = s.get()) { + t.hashCode(); + } + } +} + +class UseSite_I3 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_I3 t = s.get()) { // warning here + t.hashCode(); + } + } +} + +class UseSite_I4 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_I4 t = s.get()) { // warning here + t.hashCode(); + } + } +} + +class UseSite_I5 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_I5 t = s.get()) { + t.hashCode(); + } + } +} + +class UseSite_I6 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_I6 t = s.get()) { // warning here + t.hashCode(); + } + } +} + +class UseSite_I7 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_I7 t = s.get()) { // warning here + t.hashCode(); + } + } +} + +class UseSite_I8 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_I8 t = s.get()) { // warning here + t.hashCode(); + } + } +} + +class UseSite_I9 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_I9 t = s.get()) { + t.hashCode(); + } + } +} + +// Abstract class use site tests + +class UseSite_C1 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_C1 t = s.get()) { // warning here + t.hashCode(); + } + } +} + +class UseSite_C2 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_C2 t = s.get()) { + t.hashCode(); + } + } +} + +class UseSite_C3 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_C3 t = s.get()) { // warning here + t.hashCode(); + } + } +} + +class UseSite_C4 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_C4 t = s.get()) { // warning here + t.hashCode(); + } + } +} + +class UseSite_C5 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_C5 t = s.get()) { + t.hashCode(); + } + } +} + +class UseSite_C6 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_C6 t = s.get()) { // warning here + t.hashCode(); + } + } +} + +class UseSite_C7 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_C7 t = s.get()) { // warning here + t.hashCode(); + } + } +} + +class UseSite_C8 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_C8 t = s.get()) { // warning here + t.hashCode(); + } + } +} + +class UseSite_C9 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_C9 t = s.get()) { + t.hashCode(); + } + } +} + +class UseSite_C10 { + void m(Supplier s) throws Exception { + try (InterruptedExceptionTest_C10 t = s.get()) { // warning here + t.hashCode(); + } + } +} diff --git a/test/langtools/tools/javac/TryWithResources/InterruptedExceptionTest2.out b/test/langtools/tools/javac/TryWithResources/InterruptedExceptionTest2.out new file mode 100644 index 00000000000..9aae66cea5e --- /dev/null +++ b/test/langtools/tools/javac/TryWithResources/InterruptedExceptionTest2.out @@ -0,0 +1,23 @@ +InterruptedExceptionTest2.java:34:20: compiler.warn.try.resource.can.throw.interrupted.exc: InterruptedExceptionTest_I3 +InterruptedExceptionTest2.java:38:20: compiler.warn.try.resource.can.throw.interrupted.exc: InterruptedExceptionTest_I4 +InterruptedExceptionTest2.java:46:28: compiler.warn.try.resource.can.throw.interrupted.exc: InterruptedExceptionTest_I6 +InterruptedExceptionTest2.java:50:28: compiler.warn.try.resource.can.throw.interrupted.exc: InterruptedExceptionTest_I7 +InterruptedExceptionTest2.java:70:36: compiler.warn.try.resource.can.throw.interrupted.exc: InterruptedExceptionTest_C3 +InterruptedExceptionTest2.java:74:36: compiler.warn.try.resource.can.throw.interrupted.exc: InterruptedExceptionTest_C4 +InterruptedExceptionTest2.java:82:27: compiler.warn.try.resource.can.throw.interrupted.exc: InterruptedExceptionTest_C6 +InterruptedExceptionTest2.java:86:27: compiler.warn.try.resource.can.throw.interrupted.exc: InterruptedExceptionTest_C7 +InterruptedExceptionTest2.java:96:10: compiler.warn.try.resource.throws.interrupted.exc: InterruptedExceptionTest_C10 +InterruptedExceptionTest2.java:106:42: compiler.warn.try.resource.throws.interrupted.exc: InterruptedExceptionTest_I1 +InterruptedExceptionTest2.java:122:42: compiler.warn.try.resource.throws.interrupted.exc: InterruptedExceptionTest_I3 +InterruptedExceptionTest2.java:130:42: compiler.warn.try.resource.throws.interrupted.exc: InterruptedExceptionTest_I4 +InterruptedExceptionTest2.java:146:42: compiler.warn.try.resource.throws.interrupted.exc: InterruptedExceptionTest_I6 +InterruptedExceptionTest2.java:154:42: compiler.warn.try.resource.throws.interrupted.exc: InterruptedExceptionTest_I7 +InterruptedExceptionTest2.java:162:42: compiler.warn.try.resource.throws.interrupted.exc: InterruptedExceptionTest_I8 +InterruptedExceptionTest2.java:180:42: compiler.warn.try.resource.throws.interrupted.exc: InterruptedExceptionTest_C1 +InterruptedExceptionTest2.java:196:42: compiler.warn.try.resource.throws.interrupted.exc: InterruptedExceptionTest_C3 +InterruptedExceptionTest2.java:204:42: compiler.warn.try.resource.throws.interrupted.exc: InterruptedExceptionTest_C4 +InterruptedExceptionTest2.java:220:42: compiler.warn.try.resource.throws.interrupted.exc: InterruptedExceptionTest_C6 +InterruptedExceptionTest2.java:228:42: compiler.warn.try.resource.throws.interrupted.exc: InterruptedExceptionTest_C7 +InterruptedExceptionTest2.java:236:42: compiler.warn.try.resource.throws.interrupted.exc: InterruptedExceptionTest_C8 +InterruptedExceptionTest2.java:252:43: compiler.warn.try.resource.throws.interrupted.exc: InterruptedExceptionTest_C10 +22 warnings diff --git a/test/langtools/tools/javac/diags/examples/TryResourceThrowsInterruptedExc.java b/test/langtools/tools/javac/diags/examples/TryResourceThrowsInterruptedExc.java index c22992c991e..6d24a6c2a83 100644 --- a/test/langtools/tools/javac/diags/examples/TryResourceThrowsInterruptedExc.java +++ b/test/langtools/tools/javac/diags/examples/TryResourceThrowsInterruptedExc.java @@ -22,8 +22,15 @@ */ // key: compiler.warn.try.resource.throws.interrupted.exc +// key: compiler.warn.try.resource.can.throw.interrupted.exc // options: -Xlint:try class TryResourceThrowsInterruptedException implements AutoCloseable { public void close() throws InterruptedException {} + { + try (var t = new TryResourceThrowsInterruptedException()) { + t.hashCode(); + } catch (InterruptedException e) { + } + } }