United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: 5009601 Bring enum implementation up to date with its spec
5009601 : Bring enum implementation up to date with its spec

Details
Type:
Bug
Submit Date:
2004-03-08
Status:
Resolved
Updated Date:
2004-04-01
Project Name:
JDK
Resolved Date:
2004-04-01
Component:
tools
OS:
generic
Sub-Component:
javac
CPU:
generic
Priority:
P3
Resolution:
Fixed
Affected Versions:
1.4.0
Fixed Versions:
5.0

Related Reports
Relates:
Relates:
Relates:

Sub Tasks

Description
Attached to the CCC proposal corresponding to this bug report is the latest JSR-201 spec draft for enum types (labeled "Preliminary Proposed Final Draft 2").  There are three substantive changes in this draft:

(1)  All enum constructors are implicitly private.  The compiler should implement this behavior.

(2) The use of the abstract and final modifiers on enum types is prohibited.  The compiler should generate a compile-time error if a program uses either of these modifiers on an enum-type.

(3) It is illegal to reflectively instantiate an enum type.  
Constructor.newInstance() will need new checks. (Class.newInstance() should then behave properly as it is implemented in terms of Constructor.newInstance().)

                                    

Comments
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
tiger-beta2

FIXED IN:
tiger-beta2

INTEGRATED IN:
tiger-b46
tiger-beta2


                                     
2004-06-14
WORK AROUND

 
                                     
2004-06-11
PUBLIC COMMENTS

...
                                     
2004-06-10
SUGGESTED FIX

src/share/classes/com/sun/tools/javac/parser>sccs sccsdiff -r1.69 -r1.70 Parser.java 

------- Parser.java -------
2167c2167,2168
<           ClassDef(mods, name, TypeParameter.emptyList,
---
>           ClassDef(new Modifiers(mods.flags|Flags.ENUM, mods.annotations),
>                    name, TypeParameter.emptyList,
2213c2214,2215
<                F.Modifiers(Flags.ENUM), names.empty, TypeParameter.emptyList,
---
>                F.Modifiers(Flags.ENUM | Flags.STATIC),
>                names.empty, TypeParameter.emptyList,

src/share/classes/com/sun/tools/javac/code>sccs sccsdiff -r1.4 -r1.5 BoundKind.java

------- BoundKind.java -------
20c20
<     protected BoundKind(String name) {
---
>     BoundKind(String name) {

src/share/classes/com/sun/tools/javac/comp>sccs sccsdiff -r1.109 -r1.110 Enter.java        

------- Enter.java -------
301c301
<       c.flags_field = chk.checkFlags(tree.pos, tree.mods.flags, c);
---
>       c.flags_field = chk.checkFlags(tree.pos, tree.mods.flags, c, tree);

src/share/classes/com/sun/tools/javac/comp>sccs sccsdiff -r1.25 -r1.26 MemberEnter.java

------- MemberEnter.java -------
542c542
<       m.flags_field = chk.checkFlags(tree.pos, tree.mods.flags, m);
---
>       m.flags_field = chk.checkFlags(tree.pos, tree.mods.flags, m, tree);
585c585
<       v.flags_field = chk.checkFlags(tree.pos, tree.mods.flags, v);
---
>       v.flags_field = chk.checkFlags(tree.pos, tree.mods.flags, v, tree);
985c985,990
<       flags |= (c.flags() & AccessFlags) | GENERATEDCONSTR;
---
>       if ((c.flags() & ENUM) != 0 && 
>           types.supertype(c.type).tsym == syms.enumSym) {
>           // constructors of true enums are private
>           flags = (flags & ~AccessFlags) | PRIVATE | GENERATEDCONSTR;
>       } else
>           flags |= (c.flags() & AccessFlags) | GENERATEDCONSTR;

src/share/classes/com/sun/tools/javac/comp>sccs sccsdiff -r1.153 -r1.154 Attr.java       

------- Attr.java -------
2260,2268c2260,2270
<               // Enums may not be extended.
<               if (allowEnums) {
<                   if (st.tsym == syms.enumSym) {
<                       c.flags_field |= Flags.ENUM;
<                   } else if (st.tsym != null &&
<                                ((st.tsym.flags_field^c.flags_field) & Flags.ENUM) != 0 &&
<                                !target.compilerBootstrap(c)) {
<                       log.error(env.tree.pos, "enum.types.not.extensible");
<                   }
---
>               // java.lang.Enum may not be subclassed by a non-enum
>               if (st.tsym == syms.enumSym &&
>                   ((c.flags_field & Flags.ENUM) == 0) ) 
>                   log.error(env.tree.pos, "enum.no.subclassing");
> 
>               // Enums may not be extended by source-level classes
>               if (st.tsym != null &&
>                   ((st.tsym.flags_field & Flags.ENUM) != 0) &&
>                   ((c.flags_field & Flags.ENUM) == 0) &&
>                   !target.compilerBootstrap(c)) {
>                   log.error(env.tree.pos, "enum.types.not.extensible");

src/share/classes/com/sun/tools/javac/comp>sccs sccsdiff -r1.116 -r1.117 Check.java       

------- Check.java -------
593c593
<     long checkFlags(int pos, long flags, Symbol sym) {
---
>     long checkFlags(int pos, long flags, Symbol sym, Tree tree) {
606,608c606,615
<           if (sym.name == names.init)
<               mask = ConstructorFlags;
<           else if ((sym.owner.flags_field & INTERFACE) != 0)
---
>           if (sym.name == names.init) {
>               if ((sym.owner.flags_field & ENUM) != 0) { 
>                   // enum constructors cannot be declared public or
>                   // protected and must be implicitly or explicitly
>                   // private
>                   implicit = PRIVATE;
>                   mask = PRIVATE;
>               } else
>                   mask = ConstructorFlags;
>           }  else if ((sym.owner.flags_field & INTERFACE) != 0)
627,628c634,635
<               // Nested interfaces are always STATIC (Spec ???)
<               if ((flags & INTERFACE) != 0) implicit = STATIC;
---
>               // Nested interfaces and enums are always STATIC (Spec ???)
>               if ((flags & (INTERFACE | ENUM)) != 0 ) implicit = STATIC;
634,635c641,647
<           // Enums are always STATIC
<           if ((flags & ENUM) != 0) implicit |= STATIC;
---
> 
>           if ((flags & ENUM) != 0) {
>               // enums can't be declared abstract or final
>               mask &= ~(ABSTRACT | FINAL);
>               implicit |= computeImplicitEnumClassFlags(tree);
> 
>           }
677a690,745
> 
>     /** Determine if this enum should be implicitly final or abstract.
>      *
>      *  If the enum has no specialized enum contants, it is final.
>      *
>      *  If the enum does have specialized enum contants, it is
>      *  <i>not</i> final.
>      *
>      *  If the enum has specialized constants and some methods of the
>      *  enum are abstract, it is marked abstract.
>      */
>     private long computeImplicitEnumClassFlags(Tree tree) {
>       long implicitFlags = 0;
> 
>       try {
>           class SpecialTreeVisitor extends Tree.Visitor {
>               boolean specialized;
>               boolean Abstract;
>               SpecialTreeVisitor() {
>                   this.specialized = false;
>                   this.Abstract = false;
>               };
> 
>               public void visitTree(Tree tree) { /* no-op */ }
> 
>               public void visitVarDef(VarDef tree) {
>                   if ((tree.mods.flags & ENUM) != 0) {
>                       if (tree.init instanceof NewClass &&
>                           ((NewClass)tree.init).def != null) {
>                           specialized = true;
>                           // System.out.println("Specialized tree: " + tree);
>                       }
>                   }
>               }
> 
>               public void visitMethodDef(MethodDef tree) {
>                   if ((tree.mods.flags & ABSTRACT) != 0) 
>                       Abstract = true;
>               }
> 
>           }
> 
>           SpecialTreeVisitor sts = new SpecialTreeVisitor();
>           ClassDef cdef = (ClassDef) tree;
>           for(Tree defs: cdef.defs)
>               defs.accept(sts);
> 
>           implicitFlags = (!sts.specialized ?
>                            FINAL:
>                            (sts.Abstract ? ABSTRACT : 0L));
> 
>       } catch (ClassCastException cce) {}
> 
>       return implicitFlags;
>     }
> 

src/share/classes/java/lang/reflect>sccs sccsdiff -r1.44 -r1.45 Constructor.java

------- Constructor.java -------
389c389,390
<      *              parameter type by a method invocation conversion.
---
>      *              parameter type by a method invocation conversion; if
>      *              this constructor pertains to an enum type.
409a411,412
>       if ((clazz.getModifiers() & Modifier.ENUM) != 0) 
>           throw new IllegalArgumentException("Cannot reflectively create enum objects");


###@###.### 2004-03-29
                                     
2004-03-29
EVALUATION

Will aim for beta2.

###@###.### 2004-03-08
                                     
2004-03-08



Hardware and Software, Engineered to Work Together