Bug 40736

Summary: JDT compiler fails to compile legitimate Java code.
Product: [Eclipse Project] JDT Reporter: Deyan Bektchiev <dejan>
Component: CoreAssignee: Philipe Mulet <philippe_mulet>
Status: VERIFIED FIXED QA Contact:
Severity: major    
Priority: P3 CC: teryaev
Version: 3.0   
Target Milestone: 2.1.2   
Hardware: PC   
OS: Windows NT   
Whiteboard:
Attachments:
Description Flags
regression test
none
regression test update none

Description Deyan Bektchiev CLA 2003-07-24 18:40:44 EDT
I guess the compiler can generate a warning for this but an error is a bit too
much for the class below:

package util;

import java.util.Random;

public class EclipseBug
{
    public void showBug() throws MyException
    {
        System.out.println("test");
    }

    protected void throwsMethod() throws MyException
    {
        if(new Random().nextInt() == 500)
        {
            throw new MyException();
        }
    }

    class MyException extends Exception
    {

    }
}

class sub extends EclipseBug
{
    public void showBug() throws MyException
    {
        if(false)
        {
            try
            {
                try
                {
                    throwsMethod();
                }
                finally
                {
                    System.out.println("finally");
                }
            }
            catch(MyException ex)
            { // THIS IS LINE 44 THE COMPILE COMPLAINS
                ex.printStackTrace();
            }
        }

        super.showBug();
    }

}


Result of compilation:

1. ERROR in D:\Dev\2003.2\corejrisk\src\util\EclipseBug.java (at line 44)
    {
                ex.printStackTrace();
            }
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Unreachable catch block
----------
1 problem (1 error)


Compilation goes fine if this same code is in the base class or of the Exception
is not a subclass of Exception.
Comment 1 Philipe Mulet CLA 2003-07-25 05:12:46 EDT
Indeed, we should not complain.
Comment 2 Nick Teryaev CLA 2003-07-29 03:31:18 EDT
test case reduced a little bit:

public class Sample
{
	public void method()
	{
		if (false) {
			try {
				try {
					throw new InterruptedException();
				} finally {
					System.out.println();
				}
			}
			catch(InterruptedException e) {
			}
		}
	}
}
Comment 3 Nick Teryaev CLA 2003-07-29 03:40:25 EDT
Created attachment 5575 [details]
regression test
Comment 4 Nick Teryaev CLA 2003-07-29 03:40:40 EDT
regression test added
Comment 5 Nick Teryaev CLA 2003-07-29 03:52:17 EDT
Created attachment 5576 [details]
regression test update

added a test for if (true) {} else { ...code... } situation
Comment 6 Nick Teryaev CLA 2003-07-29 03:53:18 EDT
proposed patch:

Index: IfStatement.java
===================================================================
RCS 
file: /home/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compi
ler/ast/IfStatement.java,v
retrieving revision 1.35
diff -u -r1.35 IfStatement.java
--- IfStatement.java	26 Jun 2003 15:59:51 -0000	1.35
+++ IfStatement.java	29 Jul 2003 07:51:19 -0000
@@ -83,7 +83,7 @@
 			// Save info for code gen
 			thenInitStateIndex =
 				currentScope.methodScope
().recordInitializationStates(thenFlowInfo);
-			if (!thenStatement.complainIfUnreachable(thenFlowInfo, 
currentScope, false)) {
+			if (!isConditionOptimizedFalse && !
thenStatement.complainIfUnreachable(thenFlowInfo, currentScope, false)) {
 				thenFlowInfo =
 					thenStatement.analyseCode(currentScope, 
flowContext, thenFlowInfo);
 			}
@@ -100,7 +100,7 @@
 			// Save info for code gen
 			elseInitStateIndex =
 				currentScope.methodScope
().recordInitializationStates(elseFlowInfo);
-			if (!elseStatement.complainIfUnreachable(elseFlowInfo, 
currentScope, false)) {
+			if (!isConditionOptimizedTrue && !
elseStatement.complainIfUnreachable(elseFlowInfo, currentScope, false)) {
 				elseFlowInfo =
 					elseStatement.analyseCode(currentScope, 
flowContext, elseFlowInfo);
 			}
Comment 7 Philipe Mulet CLA 2003-08-06 05:02:58 EDT
This fix would not work as it would entirely skip the flow analysis inside 
offending fake reachable portions of the ASTs.
The real fix is quite more complex and lives elsewhere. Unreachable code should 
still be processed
during the analysis, slightly differently.

e.g.
if (false) {
	return;
	return; // should still complain about being unreachable
}

The real fix is actually in checks for unreachable flow infos, which should be 
replaced  from "...info.isReachable()" into "...info == FlowInfo.DEAD_END".

Down the road we should get rid of DEAD_ENDs since these are loosing track of 
the initialization information from thereon.
Comment 8 Philipe Mulet CLA 2003-08-28 12:19:04 EDT
Fixed, regression tests added.
Comment 9 Philipe Mulet CLA 2003-09-23 06:43:12 EDT
Backported to 2.1 stream for further integration.
Regression test added.
Comment 10 Philipe Mulet CLA 2003-09-23 19:17:24 EDT
Released for 2.1.2 (backported better version, see bug 42692).
Comment 11 Philipe Mulet CLA 2003-10-18 08:08:21 EDT
Regression tests are InitializationTest#test161/test162.
These were not backported to 2.1.2 stream. Added now.
Comment 12 Philipe Mulet CLA 2003-10-18 08:41:28 EDT
2.1.2 stream was missing portion of the fix on TryStatement.
Backport complete now. 
Comment 13 Frederic Fusier CLA 2003-10-23 05:20:23 EDT
Verified with build 2.1.2 RC2
Comment 14 Jerome Lanneluc CLA 2003-10-23 05:35:03 EDT
Verified as well.