mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 11:04:34 +02:00
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
8 changed files with 89 additions and 27 deletions
|
@ -296,7 +296,8 @@ public class Flags {
|
||||||
ModifierFlags = ((long)StandardFlags & ~INTERFACE) | DEFAULT,
|
ModifierFlags = ((long)StandardFlags & ~INTERFACE) | DEFAULT,
|
||||||
InterfaceMethodMask = ABSTRACT | STATIC | PUBLIC | STRICTFP | DEFAULT,
|
InterfaceMethodMask = ABSTRACT | STATIC | PUBLIC | STRICTFP | DEFAULT,
|
||||||
AnnotationTypeElementMask = ABSTRACT | PUBLIC,
|
AnnotationTypeElementMask = ABSTRACT | PUBLIC,
|
||||||
LocalVarFlags = FINAL | PARAMETER;
|
LocalVarFlags = FINAL | PARAMETER,
|
||||||
|
ReceiverParamFlags = PARAMETER;
|
||||||
|
|
||||||
|
|
||||||
public static Set<Modifier> asModifierSet(long flags) {
|
public static Set<Modifier> asModifierSet(long flags) {
|
||||||
|
|
|
@ -1041,7 +1041,9 @@ public class Check {
|
||||||
|
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
case VAR:
|
case VAR:
|
||||||
if (sym.owner.kind != TYP)
|
if (TreeInfo.isReceiverParam(tree))
|
||||||
|
mask = ReceiverParamFlags;
|
||||||
|
else if (sym.owner.kind != TYP)
|
||||||
mask = LocalVarFlags;
|
mask = LocalVarFlags;
|
||||||
else if ((sym.owner.flags_field & INTERFACE) != 0)
|
else if ((sym.owner.flags_field & INTERFACE) != 0)
|
||||||
mask = implicit = InterfaceVarFlags;
|
mask = implicit = InterfaceVarFlags;
|
||||||
|
|
|
@ -720,22 +720,8 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||||
attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype);
|
attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype);
|
||||||
} else {
|
} else {
|
||||||
attr.attribType(tree.vartype, localEnv);
|
attr.attribType(tree.vartype, localEnv);
|
||||||
if (tree.nameexpr != null) {
|
if (TreeInfo.isReceiverParam(tree))
|
||||||
attr.attribExpr(tree.nameexpr, localEnv);
|
checkReceiver(tree, 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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
deferredLintHandler.setPos(prevLintPos);
|
deferredLintHandler.setPos(prevLintPos);
|
||||||
|
@ -769,7 +755,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||||
chk.checkTransparentVar(tree.pos(), v, enclScope);
|
chk.checkTransparentVar(tree.pos(), v, enclScope);
|
||||||
enclScope.enter(v);
|
enclScope.enter(v);
|
||||||
}
|
}
|
||||||
if (tree.name.equals(names._this)) {
|
if (TreeInfo.isReceiverParam(tree)) {
|
||||||
// If we are dealing with a receiver parameter, then
|
// If we are dealing with a receiver parameter, then
|
||||||
// we only allow base type annotations to be type
|
// we only allow base type annotations to be type
|
||||||
// annotations. Receivers are not allowed to have
|
// 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);
|
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) {
|
public boolean needsLazyConstValue(JCTree tree) {
|
||||||
InitTreeVisitor initTreeVisitor = new InitTreeVisitor();
|
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?
|
/** Is there a constructor declaration in the given list of trees?
|
||||||
*/
|
*/
|
||||||
public static boolean hasConstructors(List<JCTree> 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 { }
|
<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 {
|
class WithBody {
|
||||||
Object f;
|
Object f;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue