United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-7071246 Enclosing string literal in parenthesis in switch-case crashes javac
JDK-7071246 : Enclosing string literal in parenthesis in switch-case crashes javac

Details
Type:
Bug
Submit Date:
2011-07-26
Status:
Closed
Updated Date:
2012-08-11
Project Name:
JDK
Resolved Date:
2012-02-24
Component:
tools
OS:
windows_vista,linux_redhat_4.0,solaris_10,windows_xp,windows_7
Sub-Component:
javac
CPU:
x86,sparc
Priority:
P4
Resolution:
Fixed
Affected Versions:
7
Fixed Versions:

Related Reports
Backport:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Relates:
Relates:
Relates:

Sub Tasks

Description
FULL PRODUCT VERSION :
java version "1.7.0"
Java(TM) SE Runtime Environment (build 1.7.0-b147)
Java HotSpot(TM) Client VM (build 21.0-b17, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

EXTRA RELEVANT SYSTEM CONFIGURATION :
PROCESSOR_ARCHITECTURE=AMD64
PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 23 Stepping 6, GenuineInte
PROCESSOR_LEVEL=6
PROCESSOR_REVISION=1706
  ProgramData=C:\ProgramData
  ProgramFiles=C:\Program Files
  ProgramFiles(x86)=C:\Program Files (x86)
  ProgramW6432=C:\Program Files
SESSIONNAME=Console
SystemDrive=C:
SystemRoot=C:\Windows

A DESCRIPTION OF THE PROBLEM :
Running javac on a program which contains a string literal enclosed in parenthesis like in the example listed below causes javac to throw  NullPointerException and terminate.

...
switch (s) {
 case ("xyz"): // enclosing the string literal in parenthesis causes javac to crash
    ...
}
...

Note:
- Removing the parenthesis from this program helps resolve the issue.
- Replacing the String with int in the example will not reproduce this issue and hence using parenthesis with int literal in 'case' is handled well.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create a file named Test.java with the following content:

=== Begin file Test.java ===
public class Test {
    public static void main(String args[]) {
        switch(args[0]) {
            case("hello"):
                System.out.println("hello!!");
                break;
            default:
                System.out.println("hi!");
        }
    }
}
=== End of file Test.java ===

Save the file and execute the following from the command prompt:

javac Test.java

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Test.class is expected to be created as a result of successful compilation.
ACTUAL -
javac crashes with the following error message:

C:\Temp>"C:\Program Files (x86)\Java\jdk1.7.0\bin\javac.exe" Test.java
An exception has occurred in the compiler (1.7.0). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport)  after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report.  Thank you.
java.lang.NullPointerException
        at com.sun.tools.javac.comp.Lower.visitStringSwitch(Lower.java:3456)
        at com.sun.tools.javac.comp.Lower.visitSwitch(Lower.java:3357)
        at com.sun.tools.javac.tree.JCTree$JCSwitch.accept(JCTree.java:959)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2160)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:70)
        at com.sun.tools.javac.tree.TreeTranslator.visitBlock(TreeTranslator.java:160)
        at com.sun.tools.javac.comp.Lower.visitBlock(Lower.java:3311)
        at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:781)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2160)
        at com.sun.tools.javac.tree.TreeTranslator.visitMethodDef(TreeTranslator.java:144)
        at com.sun.tools.javac.comp.Lower.visitMethodDefInternal(Lower.java:2619)
        at com.sun.tools.javac.comp.Lower.visitMethodDef(Lower.java:2538)
        at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:669)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2160)
        at com.sun.tools.javac.comp.Lower.visitClassDef(Lower.java:2283)
        at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:591)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2160)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2180)
        at com.sun.tools.javac.comp.Lower.translateTopLevelClass(Lower.java:3650)
        at com.sun.tools.javac.main.JavaCompiler.desugar(JavaCompiler.java:1393)
        at com.sun.tools.javac.main.JavaCompiler.desugar(JavaCompiler.java:1271)
        at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:870)
        at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:829)
        at com.sun.tools.javac.main.Main.compile(Main.java:417)
        at com.sun.tools.javac.main.Main.compile(Main.java:331)
        at com.sun.tools.javac.main.Main.compile(Main.java:322)
        at com.sun.tools.javac.Main.compile(Main.java:76)
        at com.sun.tools.javac.Main.main(Main.java:61)

C:\Temp>

ERROR MESSAGES/STACK TRACES THAT OCCUR :
C:\Temp>"C:\Program Files (x86)\Java\jdk1.7.0\bin\javac.exe" Test.java
An exception has occurred in the compiler (1.7.0). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport)  after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report.  Thank you.
java.lang.NullPointerException
        at com.sun.tools.javac.comp.Lower.visitStringSwitch(Lower.java:3456)
        at com.sun.tools.javac.comp.Lower.visitSwitch(Lower.java:3357)
        at com.sun.tools.javac.tree.JCTree$JCSwitch.accept(JCTree.java:959)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2160)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:70)
        at com.sun.tools.javac.tree.TreeTranslator.visitBlock(TreeTranslator.java:160)
        at com.sun.tools.javac.comp.Lower.visitBlock(Lower.java:3311)
        at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:781)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2160)
        at com.sun.tools.javac.tree.TreeTranslator.visitMethodDef(TreeTranslator.java:144)
        at com.sun.tools.javac.comp.Lower.visitMethodDefInternal(Lower.java:2619)
        at com.sun.tools.javac.comp.Lower.visitMethodDef(Lower.java:2538)
        at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:669)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2160)
        at com.sun.tools.javac.comp.Lower.visitClassDef(Lower.java:2283)
        at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:591)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2160)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2180)
        at com.sun.tools.javac.comp.Lower.translateTopLevelClass(Lower.java:3650)
        at com.sun.tools.javac.main.JavaCompiler.desugar(JavaCompiler.java:1393)
        at com.sun.tools.javac.main.JavaCompiler.desugar(JavaCompiler.java:1271)
        at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:870)
        at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:829)
        at com.sun.tools.javac.main.Main.compile(Main.java:417)
        at com.sun.tools.javac.main.Main.compile(Main.java:331)
        at com.sun.tools.javac.main.Main.compile(Main.java:322)
        at com.sun.tools.javac.Main.compile(Main.java:76)
        at com.sun.tools.javac.Main.main(Main.java:61)

C:\Temp>

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
//
// File name: Test.java
//
public class Test {
    public static void main(String args[]) {
        switch(args[0]) {
            case("hello"):
                System.out.println("hello!!");
                break;
            default:
                System.out.println("hi!");
        }
    }
}
=== End of file Test.java ===
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Remove the parenthesis from around the sting literal:


=== Begin file Test.java ===
public class Test {
    public static void main(String args[]) {
        switch(args[0]) {
            case "hello":  // workaround is to remove the parenthesis
                System.out.println("hello!!");
                break;
            default:
                System.out.println("hi!");
        }
    }
}
=== End of file Test.java ===

                                    

Comments
EVALUATION

Parens should be skipped during code generation.
                                     
2011-07-27
SUGGESTED FIX

# HG changeset patch
# User darcy
# Date 1312481737 25200
# Node ID 64b9b7ae33667807e34e17a8e017e9d4adb43c33
# Parent 0d6d41563040e1fa91180cf0a54165bdb2b78827
7071246: Enclosing string literal in parenthesis in switch-case crashes javac
Reviewed-by: mcimadamore

--- a/src/share/classes/com/sun/tools/javac/comp/Lower.java	Wed Jul 27 11:53:17 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java	Thu Aug 04 11:15:37 2011 -0700
@@ -3450,6 +3450,7 @@ public class Lower extends TreeTranslato
                 JCExpression expression = oneCase.getExpression();
 
                 if (expression != null) { // expression for a "default" case is null
+                    expression = TreeInfo.skipParens(expression);
                     String labelExpr = (String) expression.type.constValue();
                     Integer mapping = caseLabelToPosition.put(labelExpr, casePosition);
                     Assert.checkNull(mapping);
@@ -3555,8 +3556,8 @@ public class Lower extends TreeTranslato
                 if (isDefault)
                     caseExpr = null;
                 else {
-                    caseExpr = make.Literal(caseLabelToPosition.get((String)oneCase.
-                                                                    getExpression().
+                    caseExpr = make.Literal(caseLabelToPosition.get((String)TreeInfo.skipParens(oneCase.
+                                                                                                getExpression()).
                                                                     type.constValue()));
                 }
 
--- a/test/tools/javac/StringsInSwitch/StringSwitches.java	Wed Jul 27 11:53:17 2011 -0700
+++ b/test/tools/javac/StringsInSwitch/StringSwitches.java	Thu Aug 04 11:15:37 2011 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2011 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 6827009
+ * @bug 6827009 7071246
  * @summary Positive tests for strings in switch.
  * @author  Joseph D. Darcy
  */
@@ -36,6 +36,7 @@ public class StringSwitches {
         failures += testPileup();
         failures += testSwitchingTwoWays();
         failures += testNamedBreak();
+        failures += testExtraParens();
 
         if (failures > 0) {
             throw new RuntimeException();
@@ -260,4 +261,19 @@ public class StringSwitches {
         result |= (1<<5);
         return result;
     }
+
+    private static int testExtraParens() {
+        int failures = 1;
+        String s = "first";
+
+        switch(s) {
+        case (("first")):
+            failures = 0;
+            break;
+        case ("second"):
+            throw new RuntimeException("Should not be reached.");
+        }
+
+        return failures;
+    }
 }
                                     
2011-08-04
PUBLIC COMMENTS

See
http://hg.openjdk.java.net/jdk8/tl/langtools/rev/64b9b7ae3366
                                     
2011-08-04



Hardware and Software, Engineered to Work Together