8027886: javac allows illegal receiver parameters

8029042: Receiver parameter not supported on local class constructor

Reviewed-by: jfranck, jlahoda
This commit is contained in:
Paul Govereau 2014-06-11 12:49:10 -04:00
parent 3ea78c679c
commit 577b60e711
8 changed files with 89 additions and 27 deletions

View File

@ -296,7 +296,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) {

View File

@ -1041,7 +1041,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;

View File

@ -720,22 +720,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);
@ -769,7 +755,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
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 @@ 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();

View File

@ -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) {

View File

@ -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) {}
}
}
}

View File

@ -0,0 +1,2 @@
FinalReceiverTest.java:11:43: compiler.err.mod.not.allowed.here: final
1 error

View File

@ -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) {}
}
}
}

View File

@ -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;