United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6654037 JCTree.pos may be incorrect for BinaryTrees
JDK-6654037 : JCTree.pos may be incorrect for BinaryTrees

Details
Type:
Bug
Submit Date:
2008-01-23
Status:
Closed
Updated Date:
2011-01-15
Project Name:
JDK
Resolved Date:
2011-01-15
Component:
tools
OS:
linux
Sub-Component:
javac
CPU:
x86
Priority:
P4
Resolution:
Duplicate
Affected Versions:
7
Fixed Versions:
7

Related Reports
Duplicate:
Relates:

Sub Tasks

Description
The JCTree.pos may contain incorrect offset for BinaryTrees in some cases. For example, for expression "o != null && o instanceof String", the JCTree.pos for tree corresponding to the "&&" operator points to the beginning of the "instanceof" operator, while is should point to the beginning of the "&&" operator. Tested on revision "1:e4dae1993f8b" cloned from http://hg.openjdk.java.net/jdk7/jdk7/langtools

Test case:

/*
 * @test @(#)T9999999.java
 * @bug 9999999
 * @summary
 */

import com.sun.source.tree.BinaryTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.VariableTree;
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.tree.JCTree;
import java.net.URI;
import java.util.Arrays;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;

public class T9999999 {
    
    public static void main(String[] args) throws Exception {
        final String bootPath = System.getProperty("sun.boot.class.path"); //NOI18N
        final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
        assert tool != null;

        String code = "package test; public class Test {private void test() {Object o = null; boolean b = o != null && o instanceof String;} private Test() {}}";

        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, Arrays.asList("-bootclasspath", bootPath, "-Xjcov"), null, Arrays.asList(new MyFileObject(code)));
        CompilationUnitTree cut = ct.parse().iterator().next();
        ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0);
        MethodTree method = (MethodTree) clazz.getMembers().get(0);
        VariableTree condSt = (VariableTree) method.getBody().getStatements().get(1);
        BinaryTree cond = (BinaryTree) condSt.getInitializer();
        JCTree condJC = (JCTree) cond;

        if (condJC.pos != 93)
            throw new IllegalStateException("Unexpected position=" + condJC.pos);
    }
    
    static class MyFileObject extends SimpleJavaFileObject {
        private String text;
        public MyFileObject(String text) {
            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
            this.text = text;
        }
        @Override
        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
            return text;
        }
    }
}

                                    

Comments
SUGGESTED FIX

A possible fix:

diff -r 2c89c0bc537e src/share/classes/com/sun/tools/javac/parser/Parser.java
--- a/src/share/classes/com/sun/tools/javac/parser/Parser.java	Mon Jan 21 22:20:41 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/parser/Parser.java	Wed Jan 23 11:24:20 2008 +0100
@@ -721,6 +721,8 @@ public class Parser {
     JCExpression term2Rest(JCExpression t, int minprec) {
         List<JCExpression[]> savedOd = odStackSupply.elems;
         JCExpression[] odStack = newOdStack();
+        List<int[]> savedPos = posStackSupply.elems;
+        int[] posStack = newPosStack();
         List<Token[]> savedOp = opStackSupply.elems;
         Token[] opStack = newOpStack();
         // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
@@ -735,8 +737,9 @@ public class Parser {
             int pos = S.pos();
             S.nextToken();
             odStack[top] = topOp == INSTANCEOF ? type() : term3();
+            posStack[top - 1] = pos;
             while (top > 0 && prec(topOp) >= prec(S.token())) {
-                odStack[top-1] = makeOp(pos, topOp, odStack[top-1],
+                odStack[top-1] = makeOp(posStack[top - 1], topOp, odStack[top-1],
                                         odStack[top]);
                 top--;
                 topOp = opStack[top];
@@ -753,6 +756,7 @@ public class Parser {
         }
 
         odStackSupply.elems = savedOd; // optimization
+        posStackSupply.elems = savedPos; // optimization
         opStackSupply.elems = savedOp; // optimization
         return t;
     }
@@ -806,6 +810,7 @@ public class Parser {
          *  for every binary operation, we use supplys.
          */
         ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
+        ListBuffer<int[]> posStackSupply = new ListBuffer<int[]>();
         ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
 
         private JCExpression[] newOdStack() {
@@ -816,6 +821,14 @@ public class Parser {
             return odStack;
         }
 
+        private int[] newPosStack() {
+            if (posStackSupply.elems == posStackSupply.last)
+                posStackSupply.append(new int[infixPrecedenceLevels + 1]);
+            int[] posStack = posStackSupply.elems.head;
+            posStackSupply.elems = posStackSupply.elems.tail;
+            return posStack;
+        }
+        
         private Token[] newOpStack() {
             if (opStackSupply.elems == opStackSupply.last)
                 opStackSupply.append(new Token[infixPrecedenceLevels + 1]);
                                     
2008-01-23
EVALUATION

Yes
                                     
2008-01-29



Hardware and Software, Engineered to Work Together