Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4396402

Spec bugs on compile-time constants

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 1.4.0
    • 1.3.0
    • specification
    • merlin
    • generic
    • generic



      Name: boT120536 Date: 12/08/2000


      java version "1.3.0_01"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0_01)
      Java HotSpot(TM) Client VM (build 1.3.0_01, mixed mode)


      The specification for 15.28, Constant Expressions, has a number of bugs.

      1. You have omitted the fact that ParenthesizedExpressions are valid constant
      expressions. This is obviously allowable, though, since you then list
      (short)(1*2*3*4*5) as an example constant.

      2. The last two bullets are misleading. They should be amended to read:
      "Simple names that refer to final primitives or Strings whose initializers are
      constant expressions.
      "Qualified names of the form TypeName . Identifier that refer to final
      primitives or Strings whose initializers are constant expressions."

      As they stand now, I could argue that the following should be legal Java (in
      fact, I had submitted this as a bug to the compiler department, and was told I
      was in error, and to refer the matter to specification):

      class Bad {
        static final Object o = "This is a constant initializer";
        void foo(int i) {
          switch (i) {
            case (String)o != "This string is constant" ? 1 : 2: // case 1
          }
        }
      }

      As you can see, I used only a cast to String, a simple named reference to a
      final variable whose initializer was a constant, the != operator, a string
      literal, two integer literals, and the ?: operator, all valid by bullets in the
      list of 15.28. Without the addition of an explicit statement that all
      subexpressions, such as the field accesses, must also be primitives or type
      String, this class file meets all the written specs for compilation, even though
      it violates the spirit of the section.

      3. You need to specify how to handle integer division by constant 0. 1/0 is
      composed solely of elements that form constants, but cannot be a constant itself
      since it is undefined. However, should it be a compile-time error to have a
      constant 0 as the divisor to integer /, %, /=, and %=? Or should compilers do
      as javac 1.3 does, and compile it as a non-constant and generate the guaranteed
      ArithmeticException?

      Personally, I would prefer that any attempt to do integer division by a constant
      0 should be flagged as a compile-time error. If it is allowed to compile, then
      you are violating the premise that all expressions can complete normally, since
      you would be guaranteed an abrupt completion on that expression.

      class Divide {
        void foo(int i) {
          int j = i / 0;
          System.out.print(j); // this statement is unreachable
        }
      }

      4. You should probably clarify the behavior of the short-circuiting logic
      operators, when the condition is constant. Must the unevaluated portion of the
      expression be constant for the overall expression to be constant? If bytecode
      is generated for the unused side of the operator, it will never be called.

      class ShortCircuit {
        void foo(int i) {
          boolean t = true, f = false;
          switch (i) {
            case (true || t) ? 0 : 1: // case 0
            case (false && f) ? 0 : 1: // case 1
            case true ? 2 : i: // case 2
            case false ? i : 3: // case 3
          }
        }
      }

      5. Presumably, constant expressions can alter what exceptions an expression may
      throw. I am assuming that this code should be illegal, as all the catch blocks
      are provably unreachable. However, I could not find any definitive mention in
      the specs one way or another as to the correctness of my assumptions. Javac 1.3
      compiles this, but has other known bugs with not noticing unreachable catch
      blocks.

      class Question {
        void foo() {
          try {
            String s = "a" + "b"; // cannot throw OutOfMemoryError, as the class
                                  // file only sees this as "ab"
          } catch(OutOfMemoryError e) {
          }
          try {
            int[] i = new int[1]; // cannot throw NegativeArraySizeException, as
                                  // the size is positive
            char c = 'c';
            int[] j = new int[c]; // ditto
          } catch(NegativeArraySizeException e) {
          }
          try {
            int i = 1;
            int j = i / 1; // cannot throw ArithmeticException
          } catch (ArithmeticException e) {
          }
        }
      }

      Likewise, code such as new int[-1] should be a compile-time error, rather than
      waiting until runtime to throw the NegativeArraySizeException.
      (Review ID: 113476)
      ======================================================================

            gbrachasunw Gilad Bracha (Inactive)
            bonealsunw Bret O'neal (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: