Community
Participate
Working Groups
The source of the Scope.java class doesn't compile because of a NPE. java.lang.NullPointerException at org.eclipse.jdt.internal.compiler.codegen.BranchLabel.branch(BranchLabel.java:127) at org.eclipse.jdt.internal.compiler.codegen.CodeStream.goto_(CodeStream.java:3129) at org.eclipse.jdt.internal.compiler.ast.BranchStatement.generateCode(BranchStatement.java:60) at org.eclipse.jdt.internal.compiler.ast.IfStatement.generateCode(IfStatement.java:183) at org.eclipse.jdt.internal.compiler.ast.ForStatement.generateCode(ForStatement.java:290) at org.eclipse.jdt.internal.compiler.ast.Block.generateCode(Block.java:51) at org.eclipse.jdt.internal.compiler.ast.ForStatement.generateCode(ForStatement.java:290) at org.eclipse.jdt.internal.compiler.ast.LabeledStatement.generateCode(LabeledStatement.java:104) at org.eclipse.jdt.internal.compiler.ast.Block.generateCode(Block.java:51) at org.eclipse.jdt.internal.compiler.ast.IfStatement.generateCode(IfStatement.java:183) at org.eclipse.jdt.internal.compiler.ast.Block.generateCode(Block.java:51) at org.eclipse.jdt.internal.compiler.ast.ForStatement.generateCode(ForStatement.java:290) at org.eclipse.jdt.internal.compiler.ast.LabeledStatement.generateCode(LabeledStatement.java:104) at org.eclipse.jdt.internal.compiler.ast.Block.generateCode(Block.java:51) at org.eclipse.jdt.internal.compiler.ast.IfStatement.generateCode(IfStatement.java:183) at org.eclipse.jdt.internal.compiler.ast.Block.generateCode(Block.java:51) at org.eclipse.jdt.internal.compiler.ast.IfStatement.generateCode(IfStatement.java:183) at org.eclipse.jdt.internal.compiler.ast.Block.generateCode(Block.java:51) at org.eclipse.jdt.internal.compiler.ast.ForStatement.generateCode(ForStatement.java:290) at org.eclipse.jdt.internal.compiler.ast.LabeledStatement.generateCode(LabeledStatement.java:104) at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.generateCode(AbstractMethodDeclaration.java:244) at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.generateCode(AbstractMethodDeclaration.java:182) at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.generateCode(TypeDeclaration.java:543) at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.generateCode(TypeDeclaration.java:612) at org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.generateCode(CompilationUnitDeclaration.java:361) at org.eclipse.jdt.internal.compiler.Compiler.resolve(Compiler.java:919) at org.eclipse.jdt.internal.compiler.Compiler.resolve(Compiler.java:958) at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process(CompilationUnitProblemFinder.java:202) at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process(CompilationUnitProblemFinder.java:268) at org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation.makeConsistent(ReconcileWorkingCopyOperation.java:190) at org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation.executeOperation(ReconcileWorkingCopyOperation.java:89) at org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:728) at org.eclipse.jdt.internal.core.JavaModelOperation.runOperation(JavaModelOperation.java:788) at org.eclipse.jdt.internal.core.CompilationUnit.reconcile(CompilationUnit.java:1244) at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile(JavaReconcilingStrategy.java:126) at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.access$0(JavaReconcilingStrategy.java:108) at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy$1.run(JavaReconcilingStrategy.java:89) at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile(JavaReconcilingStrategy.java:87) at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.initialReconcile(JavaReconcilingStrategy.java:178) at org.eclipse.jdt.internal.ui.text.CompositeReconcilingStrategy.initialReconcile(CompositeReconcilingStrategy.java:114) at org.eclipse.jdt.internal.ui.text.JavaCompositeReconcilingStrategy.initialReconcile(JavaCompositeReconcilingStrategy.java:136) at org.eclipse.jface.text.reconciler.MonoReconciler.initialProcess(MonoReconciler.java:105) at org.eclipse.jdt.internal.ui.text.JavaReconciler.initialProcess(JavaReconciler.java:406) at org.eclipse.jface.text.reconciler.AbstractReconciler$BackgroundThread.run(AbstractReconciler.java:173) This might be related to the latest changes in the code generation changes around dead code. I am investigating to isolate a test case.
A must fix for M6.
Reduced test case: public abstract class X { private static Object[] bar() { return null; } protected final Object foo() { Object[] tab = null; if (tab != null) { Object[] v = bar(); int length = tab.length; loop : for (int i = 0, max = v.length; i < max; i++) { Object o = v[i]; if (o == null) { continue loop; } if (0 == length) { loop2 : for (int j = 0; j < length; j++) { Object o2 = null; for (int k = 0; k < length; k++) { if (o2 == tab[k]) { continue loop2; } } continue loop; } return o; } } } return null; } } This blows up with HEAD contents. It is related to the recent changes for dead code detection and code generation. The code stream of the labels for the labeled statement are still null at code generation time causing the NPE.
Created attachment 190598 [details] Proposed fix With this patch, the code compiles again and still reports a dead code warning.
Stephan, Ayushman, please review the patch and propagate the same kind of changes to all possible locations. I haven't checked in details other possible usages of UNREACHABLE instead of UNREACHABLE_OR_DEAD. I also haven't run all tests yet.
Created attachment 190636 [details] proposed fix extended Here's the same fix extended to some other places which affect code gen later on. Testing this now.
Created attachment 190644 [details] fix + tests Same fix with added tests. Note that the change in LocalDeclaration is to make sure we treat a local declaration in a null analysed dead code as reachable. As a consequence, local variable unused warnings also show up inside dead code now, which is good. Olivier/Stephan, if you don't have any objections with this fix, I'll release it.
(In reply to comment #5) > Created attachment 190636 [details] > proposed fix extended > > Here's the same fix extended to some other places which affect code gen later > on. Testing this now. I had prepared a similar patch last night. But I must have been tired: I forgot to actually click submit.. So, while working independently we agree on the locations in FlowContext and sub-classes. The common pattern is: - XFlowContext has a field initsOnY - this field is initialized to FlowInfo.DEAD_END (!) - only during recordZFrom(..) is this field updated to something useful - this method only works if not dead code (need to use UNREACHABLE_OR_DEAD) IMO in all those methods changing the outer if should suffice for the immediate issue. (The inner if in LoopingFlowContext only affects the content of the flowInfo, it is unrelated to the NPE at hand). With just these changes I ran tests.compiler and tests.model and they pass. Also the occurrences in LocalDeclaration and MethodScope looked suspicious to me. I agree with changing these, too. I missed the location in TryStatement, but that's a good catch, too. On the semantic side I suspect FlowContext.recordSettingFinal(..) should also be changed for correct analysis, but I don't see danger of an NPE here.
Now we had a mid-air collision of comments. .... (In reply to comment #6) > Created attachment 190644 [details] > fix + tests > > Same fix with added tests. > Note that the change in LocalDeclaration is to make sure we treat a local > declaration in a null analysed dead code as reachable. As a consequence, local > variable unused warnings also show up inside dead code now, which is good. > Olivier/Stephan, if you don't have any objections with this fix, I'll release > it. Maybe you can briefly comment on two points where our findings differ: - why change the inner if in LoopingFlowContext? - how about FlowContext.recordSettingFinal? thanks, Stephan
(In reply to comment #8) > Maybe you can briefly comment on two points where our findings differ: > - why change the inner if in LoopingFlowContext? I couldn't really convince myself on changing it or leaving it as is. I was basically trying the following tweaked case (focus on the portion between the "///////.."): public class X { private static Object[] bar() { Object o = null; if (o != null) { int a11 = 0; a11++; Object aa = null; if (aa == null) { aa.toString(); } } return null; } protected final Object foo() { Object[] tab = null; if (tab != null) { Object[] v = bar(); int length = tab.length; loop : for (int i = 0, max = v.length; i < max; i++) { Object o = v[i]; ///////////////////////////////////////////////// if (o == null) { continue loop; // CONTINUE 1 } o = null; if (o == null ) { continue loop; // CONTINUE 2 } //////////////////////////////////////////////////// if (0 == length) { loop2 : for (int j = 0; j < length; j++) { Object o2 = null; for (int k = 0; k < length; k++) { if (o2 == tab[k]) { continue loop2; } } continue loop; } return o; } } } return null; } } I saw that if we just have the UNREACHABLE bit comparison, we don't merge the initsOnContinue that we obtained from the CONTINUE 1, and just copy the flowInfo of the loop into the inits. I'm not sure if it'll have any consequence on code gen really. Frankly speaking, I wasn't able to make up my mind. We can use just the UNREACHABLE bit as well. > - how about FlowContext.recordSettingFinal? I did consider this but didnt find a possibility of an NPE. Again, we can change this as well to be consistent. Let me know what you think.
(In reply to comment #9) > Let me know what you think. It's probably safest to use UNREACHABLE_OR_DEAD in all mentioned locations even if no direct impact on codegen can be shown now (as to minimize the danger of null-analysis causing grief). At the same time I suggest to open fups for the issues where we still want to investigate the exact impact on analysis in general. This would affect at least both locations mentioned in comment 8 . That why we can take our time to find test cases for those and still cleanly fix the NPE now.
Created attachment 190668 [details] same fix with suggested changes I'll release this fix then. It passes all tests.
Released in HEAD for 3.7M6
Created attachment 190669 [details] released patch Same patch. Just fixed some comments.
(In reply to comment #10) > At the same time I suggest to open fups for the issues where we still want > to investigate the exact impact on analysis in general. Done. See bug 339253
Verified for 3.7M6.
Verified with build I20110428-0848 for 3.7RC0