Bug 300133

Summary: [1.5][compiler] Local classes inside enum constants generate default constructor without implicit constructor call
Product: [Eclipse Project] JDT Reporter: Chris Jester-Young <cky>
Component: CoreAssignee: Olivier Thomann <Olivier_Thomann>
Status: VERIFIED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: amj87.iitr, Olivier_Thomann, srikanth_sankaran
Version: 3.6Flags: srikanth_sankaran: review+
Target Milestone: 3.6 M5   
Hardware: PC   
OS: Linux   
Whiteboard:
Attachments:
Description Flags
An example program that demonstrates the bug
none
Proposed fix + regression test none

Description Chris Jester-Young CLA 2010-01-19 23:03:34 EST
Build Identifier: M20090917-0800

When you have an enum constant with a class body, and declare a local class within a method in the enum constant class body, Eclipse generates the default constructor for that local class without the required super() call. The verifier then rightly rejects that class.

See upcoming attached example.

Reproducible: Always

Steps to Reproduce:
1. Run the attached program in Eclipse, and watch it fail verification.
2. Compile the same program with Sun javac, and watch it run successfully.
Comment 1 Chris Jester-Young CLA 2010-01-19 23:04:53 EST
Created attachment 156594 [details]
An example program that demonstrates the bug
Comment 2 Olivier Thomann CLA 2010-01-21 10:28:02 EST
Reproduced:
Exception in thread "main" java.lang.VerifyError: (class: X$1$1Finder, method: <init> signature: (LX$1;Ljava/util/regex/Pattern;)V) Constructor must call super() or this()
        at X$1.createMatcher(X.java:22)
        at X.main(X.java:29)

Working on it.
Comment 3 Olivier Thomann CLA 2010-01-21 12:25:16 EST
Created attachment 156823 [details]
Proposed fix + regression test

This increased the nestedType counter to make sure that an implicit constructor call is inserted for the default constructor of the local class.
Comment 4 Olivier Thomann CLA 2010-01-21 12:25:37 EST
Srikanth, please review.
Comment 5 Olivier Thomann CLA 2010-01-21 22:35:15 EST
Released for 3.6M5.
Comment 6 Ayushman Jain CLA 2010-01-25 06:57:38 EST
Verified for 3.6M5 using build I20100122-0800
Comment 7 Srikanth Sankaran CLA 2010-01-25 06:59:50 EST
Verified.
Comment 8 Srikanth Sankaran CLA 2010-01-28 05:06:34 EST
Sorry it took me a long while to get to this and once
I got there a good while to understand the fix even
though the fix is only 4 lines long.

The fix looks OK, other than the nit that we needn't
have the statement 

this.variablesCounter[this.nestedType] = 0;
in Parser.consumeEnumConstantWithClassBody()

Are we sure the extra call to consumeNestedType won't cause any
issues ? Given

EnumConstant ::= EnumConstantHeader ForceNoDiet ClassBody RestoreDiet
ClassBody ::= '{' ClassBodyDeclarationsopt '}
ClassBodyDeclarationsopt ::= NestedType ClassBodyDeclarations
NestedType ::= $empty 
/.$putCase consumeNestedType(); $break./

So in any event there would have been a call to consumeNestedType.
It wouldn't have been in a convenient enough place to do a

    this.variablesCounter[this.nestedType]++;

though. I can't think of a problem with this, just that the counter
is holding an incorrect value.

I wonder if a more straightforward solution would have been possible
by checking whether we are dealing with a local anonymous type at
the call site of TypeDeclaration.createDefaultConstructor(boolean, boolean)
I didn't test this though -- Thanks.
Comment 9 Olivier Thomann CLA 2010-01-28 14:40:55 EST
You are right. The only thing I wanted to achieve was to make sure the variableCounter was incremented.
Feel free to revisit it.