United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-7057297 : Project Coin: diamond erroneously accepts in array initializer expressions

Details
Type:
Bug
Submit Date:
2011-06-21
Status:
Resolved
Updated Date:
2011-12-07
Project Name:
JDK
Resolved Date:
2011-09-02
Component:
tools
OS:
generic
Sub-Component:
javac
CPU:
unknown
Priority:
P2
Resolution:
Fixed
Affected Versions:
7
Fixed Versions:
7u2 (b06)

Related Reports
Backport:
Relates:

Sub Tasks

Description
The following program erroneously compiles:

class Foo<X> {}

class BlocksTest {
    void test() {
        Foo<String>[] fooArr = new Foo<>[]{ };
    }
}

                                    

Comments
SUGGESTED FIX

A webrev of this fix is available at the following URL:
http://hg.openjdk.java.net/jdk7u/jdk7u-dev/langtools/rev/8c9f07f9aa28
                                     
2011-08-26
EVALUATION

This is a bug - diamond should only be allowed in class creation expressions. Quoting from JLS SE 7 draft, the grammar of instance creation expression is the following:

ClassInstanceCreationExpression:
     new TypeArgumentsopt TypeDeclSpecifier TypeArgumentsOrDiamondopt
                                     ( ArgumentListopt ) ClassBodyopt

     Primary . new TypeArgumentsopt Identifier TypeArgumentsOrDiamondopt
                                     ( ArgumentListopt ) ClassBodyopt

TypeArgumentsOrDiamond:
     TypeArguments
     <>

ArgumentList:
     Expression
     ArgumentList , Expression


In other words, diamond is only allowed in instance creation expression (that is, in cases where the 'new' keyword is followed by a plain or qualified class name).
                                     
2011-06-21
SUGGESTED FIX

diff --git a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
--- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
+++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
@@ -1397,7 +1397,12 @@
         mode = oldmode;
         if (S.token() == LBRACKET) {
             JCExpression e = arrayCreatorRest(newpos, t);
-            if (typeArgs != null) {
+            if (diamondFound) {
+                setErrorEndPos(S.prevEndPos());
+                reportSyntaxError(newpos, "cannot.create.array.with.diamond");
+                return toP(F.at(newpos).Erroneous(List.<JCExpression>of(e)));
+            }
+            else if (typeArgs != null) {
                 int pos = newpos;
                 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
                     // note: this should always happen but we should
diff --git a/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/share/classes/com/sun/tools/javac/resources/compiler.properties
--- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties
+++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties
@@ -462,6 +462,9 @@
 compiler.err.cannot.create.array.with.type.arguments=\
     cannot create array with type arguments
 
+compiler.err.cannot.create.array.with.diamond=\
+    cannot use ''<>'' in array initializer
+
 #
 # limits.  We don't give the limits in the diagnostic because we expect
 # them to change, yet we want to use the same diagnostic.  These are all
                                     
2011-06-21



Hardware and Software, Engineered to Work Together