8027886: javac allows illegal receiver parameters
authorpgovereau
Wed, 11 Jun 2014 12:49:10 -0400
changeset 24903 41e1812d6b4c
parent 24902 de6c922c8712
child 24904 668968682128
8027886: javac allows illegal receiver parameters 8029042: Receiver parameter not supported on local class constructor Reviewed-by: jfranck, jlahoda
langtools/src/share/classes/com/sun/tools/javac/code/Flags.java
langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java
langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java
langtools/test/tools/javac/annotations/FinalReceiverTest.java
langtools/test/tools/javac/annotations/FinalReceiverTest.out
langtools/test/tools/javac/annotations/LocalInnerReceiverTest.java
langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Receivers.java
--- 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;