8027886: javac allows illegal receiver parameters
8029042: Receiver parameter not supported on local class constructor
Reviewed-by: jfranck, jlahoda
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java Tue Jun 10 15:25:01 2014 -0600
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java Wed Jun 11 12:49:10 2014 -0400
@@ -296,7 +296,8 @@
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) {
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Tue Jun 10 15:25:01 2014 -0600
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Wed Jun 11 12:49:10 2014 -0400
@@ -1041,7 +1041,9 @@
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;
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Tue Jun 10 15:25:01 2014 -0600
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Wed Jun 11 12:49:10 2014 -0400
@@ -720,22 +720,8 @@
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);
@@ -769,7 +755,7 @@
chk.checkTransparentVar(tree.pos(), v, enclScope);
enclScope.enter(v);
}
- if (tree.name.equals(names._this)) {
+ if (TreeInfo.isReceiverParam(tree)) {
// If we are dealing with a receiver parameter, then
// we only allow base type annotations to be type
// annotations. Receivers are not allowed to have
@@ -792,6 +778,26 @@
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();
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Tue Jun 10 15:25:01 2014 -0600
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Wed Jun 11 12:49:10 2014 -0400
@@ -135,6 +135,14 @@
}
}
+ 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) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/FinalReceiverTest.java Wed Jun 11 12:49:10 2014 -0400
@@ -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) {}
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/FinalReceiverTest.out Wed Jun 11 12:49:10 2014 -0400
@@ -0,0 +1,2 @@
+FinalReceiverTest.java:11:43: compiler.err.mod.not.allowed.here: final
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/LocalInnerReceiverTest.java Wed Jun 11 12:49:10 2014 -0400
@@ -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) {}
+ }
+ }
+}
--- a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Receivers.java Tue Jun 10 15:25:01 2014 -0600
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Receivers.java Wed Jun 11 12:49:10 2014 -0400
@@ -54,14 +54,6 @@
<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;