diff options
author | pgovereau <none@none> | 2014-06-18 12:30:29 -0400 |
---|---|---|
committer | pgovereau <none@none> | 2014-06-18 12:30:29 -0400 |
commit | 7cbd2bf15b73def0638af556ce1c6b77393e244d (patch) | |
tree | c09caef2b81547db50c0864d2a2b1b3dcec1341f | |
parent | 29563410adba74b7d6d64335a6454dc479f5a575 (diff) |
8027886: javac allows illegal receiver parameters
8029042: Receiver parameter not supported on local class constructor
Reviewed-by: jfranck, jlahoda
8 files changed, 88 insertions, 26 deletions
diff --git a/src/share/classes/com/sun/tools/javac/code/Flags.java b/src/share/classes/com/sun/tools/javac/code/Flags.java index 241b3019..bbe45f80 100644 --- a/src/share/classes/com/sun/tools/javac/code/Flags.java +++ b/src/share/classes/com/sun/tools/javac/code/Flags.java @@ -295,7 +295,8 @@ public class Flags { ModifierFlags = ((long)StandardFlags & ~INTERFACE) | DEFAULT, InterfaceMethodMask = ABSTRACT | STATIC | PUBLIC | STRICTFP | DEFAULT, AnnotationTypeElementMask = ABSTRACT | PUBLIC, - LocalVarFlags = FINAL | PARAMETER; + LocalVarFlags = FINAL | PARAMETER, + ReceiverParamFlags = PARAMETER; public static Set<Modifier> asModifierSet(long flags) { diff --git a/src/share/classes/com/sun/tools/javac/comp/Check.java b/src/share/classes/com/sun/tools/javac/comp/Check.java index 56033cfe..7511ad54 100644 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java @@ -1038,7 +1038,9 @@ public class Check { switch (sym.kind) { case VAR: - if (sym.owner.kind != TYP) + if (TreeInfo.isReceiverParam(tree)) + mask = ReceiverParamFlags; + else if (sym.owner.kind != TYP) mask = LocalVarFlags; else if ((sym.owner.flags_field & INTERFACE) != 0) mask = implicit = InterfaceVarFlags; diff --git a/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java b/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java index 95f10e43..7fa7fcc4 100644 --- a/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java +++ b/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java @@ -652,22 +652,8 @@ public class MemberEnter extends JCTree.Visitor implements Completer { attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype); } else { attr.attribType(tree.vartype, localEnv); - if (tree.nameexpr != null) { - attr.attribExpr(tree.nameexpr, localEnv); - MethodSymbol m = localEnv.enclMethod.sym; - if (m.isConstructor()) { - Type outertype = m.owner.owner.type; - if (outertype.hasTag(TypeTag.CLASS)) { - checkType(tree.vartype, outertype, "incorrect.constructor.receiver.type"); - checkType(tree.nameexpr, outertype, "incorrect.constructor.receiver.name"); - } else { - log.error(tree, "receiver.parameter.not.applicable.constructor.toplevel.class"); - } - } else { - checkType(tree.vartype, m.owner.type, "incorrect.receiver.type"); - checkType(tree.nameexpr, m.owner.type, "incorrect.receiver.name"); - } - } + if (TreeInfo.isReceiverParam(tree)) + checkReceiver(tree, localEnv); } } finally { deferredLintHandler.setPos(prevLintPos); @@ -714,6 +700,26 @@ public class MemberEnter extends JCTree.Visitor implements Completer { log.error(tree, diag, type, tree.type); } } + void checkReceiver(JCVariableDecl tree, Env<AttrContext> localEnv) { + attr.attribExpr(tree.nameexpr, localEnv); + MethodSymbol m = localEnv.enclMethod.sym; + if (m.isConstructor()) { + Type outertype = m.owner.owner.type; + if (outertype.hasTag(TypeTag.METHOD)) { + // we have a local inner class + outertype = m.owner.owner.owner.type; + } + if (outertype.hasTag(TypeTag.CLASS)) { + checkType(tree.vartype, outertype, "incorrect.constructor.receiver.type"); + checkType(tree.nameexpr, outertype, "incorrect.constructor.receiver.name"); + } else { + log.error(tree, "receiver.parameter.not.applicable.constructor.toplevel.class"); + } + } else { + checkType(tree.vartype, m.owner.type, "incorrect.receiver.type"); + checkType(tree.nameexpr, m.owner.type, "incorrect.receiver.name"); + } + } public boolean needsLazyConstValue(JCTree tree) { InitTreeVisitor initTreeVisitor = new InitTreeVisitor(); diff --git a/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java index f871bf66..f8d7d583 100644 --- a/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java +++ b/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java @@ -135,6 +135,14 @@ public class TreeInfo { } } + public static boolean isReceiverParam(JCTree tree) { + if (tree.hasTag(VARDEF)) { + return ((JCVariableDecl)tree).nameexpr != null; + } else { + return false; + } + } + /** Is there a constructor declaration in the given list of trees? */ public static boolean hasConstructors(List<JCTree> trees) { diff --git a/test/tools/javac/annotations/FinalReceiverTest.java b/test/tools/javac/annotations/FinalReceiverTest.java new file mode 100644 index 00000000..96ef9d98 --- /dev/null +++ b/test/tools/javac/annotations/FinalReceiverTest.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8027886 + * @summary Receiver parameters must not be final + * @compile/fail/ref=FinalReceiverTest.out -XDrawDiagnostics FinalReceiverTest.java + */ + +class FinalReceiverTest { + void m() { + class Inner { + Inner(final FinalReceiverTest FinalReceiverTest.this) {} + } + } +} diff --git a/test/tools/javac/annotations/FinalReceiverTest.out b/test/tools/javac/annotations/FinalReceiverTest.out new file mode 100644 index 00000000..0aaa9642 --- /dev/null +++ b/test/tools/javac/annotations/FinalReceiverTest.out @@ -0,0 +1,2 @@ +FinalReceiverTest.java:11:43: compiler.err.mod.not.allowed.here: final +1 error diff --git a/test/tools/javac/annotations/LocalInnerReceiverTest.java b/test/tools/javac/annotations/LocalInnerReceiverTest.java new file mode 100644 index 00000000..c32ec409 --- /dev/null +++ b/test/tools/javac/annotations/LocalInnerReceiverTest.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, 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 8029042 + * @summary Receiver parameter not supported on local class constructor + * @compile LocalInnerReceiverTest.java + */ + +class LocalInnerReceiverTest { + void m() { + class Inner { + Inner(LocalInnerReceiverTest LocalInnerReceiverTest.this) {} + } + } +} diff --git a/test/tools/javac/annotations/typeAnnotations/newlocations/Receivers.java b/test/tools/javac/annotations/typeAnnotations/newlocations/Receivers.java index 95103ff1..c9d719c5 100644 --- a/test/tools/javac/annotations/typeAnnotations/newlocations/Receivers.java +++ b/test/tools/javac/annotations/typeAnnotations/newlocations/Receivers.java @@ -54,14 +54,6 @@ class WithValue { <T extends Runnable> void accept(@B("m") WithValue this, T r) throws Exception { } } -class WithFinal { - void plain(final @B("m") WithFinal this) { } - <T> void generic(final @B("m") WithFinal this) { } - void withException(final @B("m") WithFinal this) throws Exception { } - String nonVoid(final @B("m") WithFinal this) { return null; } - <T extends Runnable> void accept(final @B("m") WithFinal this, T r) throws Exception { } -} - class WithBody { Object f; |