8027886: javac allows illegal receiver parameters
8029042: Receiver parameter not supported on local class constructor Reviewed-by: jfranck, jlahoda
This commit is contained in:
parent
3ea78c679c
commit
577b60e711
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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) {}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
FinalReceiverTest.java:11:43: compiler.err.mod.not.allowed.here: final
|
||||
1 error
|
@ -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) {}
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user