Bug 151772 - Declare Soft Half Applying and Improperly on Anonymous Class
Summary: Declare Soft Half Applying and Improperly on Anonymous Class
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: 1.5.2   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 1.5.3   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-07-25 17:29 EDT by Ron Bodkin CLA
Modified: 2006-11-09 08:38 EST (History)
0 users

See Also:


Attachments
testcase and fix (5.14 KB, application/zip)
2006-09-22 08:40 EDT, Helen Beeken CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Ron Bodkin CLA 2006-07-25 17:29:48 EDT
AspectJ 1.5.2 compiles this code without error, whereas the declare soft shouldn't have any effect, in particular it shouldn't allow the run() method on the anonymous class to throw an undeclared checked exception. Interestingly the runtime catch and coversion to a SoftException is NOT performed in this case, just removing the need to declare the exception.

import java.sql.SQLException;

public class SoftenInner {
    public static void main(String args[]) {
        new SoftenInner().foo();
    }

    public void foo() {
        new Runnable() {
            public void run() {
                throw new SQLException("test");
            }
        }.run();
    }
}

public aspect Softener {
    declare soft: Throwable: execution(* SoftenInner.foo());
}
Comment 1 Helen Beeken CLA 2006-09-19 10:49:35 EDT
The reason the test program is compiling without any errors is because by the time org.aspectj.ajdt.internal.compiler.problem.AjProblemReporter.unhandledException(..) is called the referenceContext is the method foo() rather than run(). Consequently, we match the pointcut "execution(* SoftenInner.foo())" with "public void foo()". This always matches and so we return from unhandledException(..) thinking that the declare soft is softening this exception.

The referenceContext changes in the call 

scope.problemReporter()

where scope is the MethodScope for run() (FlowContext line 275). This starts with the run() method and then moves outwards recording the last known method until it reaches null. In this case the last known method is foo() and so this is returned. 
Comment 2 Helen Beeken CLA 2006-09-20 11:52:11 EDT
Some observations:

1. if we add "public void run() throws SQLException" then we get the "exception not compatible with throws clause in Runnable.run()" compilation error (as expected)
2. if have "declare soft: Throwable :execution(* Runnable.run())" then get an unchecked exception (because the outer method is foo and we see if the pointcut matches executions of foo which it doesn't)
3. if add the "throws SQLException" then with run in pointcut we get both error messages
4. Without any declare soft...the only error message is the one about the unhandled exception.


As expected, the following compiles with javac:

----------------------------------------------------

public class C implements I {
	public void foo() throws RuntimeException {
	}
}

interface I {
	public void foo();
}
----------------------------------------------------

Essentially though, this is what the declare soft is doing. According to the 
documentation of declare soft:

"An aspect may specify that a particular kind of exception, if thrown at a 
join point, should bypass Java's usual static exception checking system and 
instead be thrown as a org.aspectj.lang.SoftException, which is subtype of 
RuntimeException and thus does not need to be declared."

Therefore, it seems from this definition that one wouldn't expect to get the unhandled exception when declare soft is applied to a method which throws an exception not compatible with the method it overrides. 

However, the question is whether 

    declare soft: Throwable: execution(* SoftenInner.foo());

or

    declare soft: Throwable :execution(* Runnable.run());

(or both) should soften the "throw new SQLException()".
Comment 3 Andrew Clement CLA 2006-09-21 09:39:52 EDT
I think

declare soft: Throwable :execution(* Runnable.run());

should soften it and not 

declare soft: Throwable: execution(* SoftenInner.foo());

And I know we have had problems in the past with  problemReporter() executing in an incorrect scope.
Comment 4 Helen Beeken CLA 2006-09-22 06:29:22 EDT
I believe this is an extension to bug 125981. Porting the fix proposed in that bug to the other FlowContext.checkExceptionHandlers method ensures the behaviour expected in comment #3.
Comment 5 Helen Beeken CLA 2006-09-22 08:40:41 EDT
Created attachment 50693 [details]
testcase and fix

The attached zip contains the following:

* pr151772-tests.txt: apply to the tests project

* FlowContext.java: to replace org.aspectj.org.eclipse.jdt.internal.compiler.flow.FlowContext.

Together these contain the testcases and fix both for this bug and bug 125981.
Comment 6 Helen Beeken CLA 2006-09-25 03:39:39 EDT
Fix has been applied and is in latest AJ dev build (Build.824 - 09/22/2006 17:59:43)
Comment 7 Andrew Clement CLA 2006-09-25 03:53:40 EDT
fix available.
Comment 8 Matthew Webster CLA 2006-09-25 09:38:02 EDT
Updated org.aspectj/bundles.
Comment 9 Helen Beeken CLA 2006-11-09 08:38:11 EST
iplog