langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java
changeset 6029 89f2c9b62d31
parent 5847 1908176fd6e3
child 6148 3a8158299c51
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java	Wed Jun 23 16:51:30 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java	Thu Jun 24 10:34:53 2010 -0700
@@ -674,6 +674,40 @@
         return rs.resolveInternalField(pos, attrEnv, qual, name);
     }
 
+    /** Anon inner classes are used as access constructor tags.
+     * accessConstructorTag will use an existing anon class if one is available,
+     * and synthethise a class (with makeEmptyClass) if one is not available.
+     * However, there is a small possibility that an existing class will not
+     * be generated as expected if it is inside a conditional with a constant
+     * expression. If that is found to be the case, create an empty class here.
+     */
+    private void checkAccessConstructorTags() {
+        for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
+            ClassSymbol c = l.head;
+            if (isTranslatedClassAvailable(c))
+                continue;
+            // Create class definition tree.
+            JCClassDecl cdef = make.ClassDef(
+                make.Modifiers(STATIC | SYNTHETIC), names.empty,
+                List.<JCTypeParameter>nil(),
+                null, List.<JCExpression>nil(), List.<JCTree>nil());
+            cdef.sym = c;
+            cdef.type = c.type;
+            // add it to the list of classes to be generated
+            translated.append(cdef);
+        }
+    }
+    // where
+    private boolean isTranslatedClassAvailable(ClassSymbol c) {
+        for (JCTree tree: translated) {
+            if (tree.getTag() == JCTree.CLASSDEF
+                    && ((JCClassDecl) tree).sym == c) {
+                return true;
+            }
+        }
+        return false;
+    }
+
 /**************************************************************************
  * Access methods
  *************************************************************************/
@@ -718,6 +752,10 @@
      */
     private Map<Symbol,MethodSymbol> accessConstrs;
 
+    /** A list of all class symbols used for access constructor tags.
+     */
+    private List<ClassSymbol> accessConstrTags;
+
     /** A queue for all accessed symbols.
      */
     private ListBuffer<Symbol> accessed;
@@ -1138,6 +1176,8 @@
         ClassSymbol ctag = chk.compiled.get(flatname);
         if (ctag == null)
             ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass);
+        // keep a record of all tags, to verify that all are generated as required
+        accessConstrTags = accessConstrTags.prepend(ctag);
         return ctag;
     }
 
@@ -3394,6 +3434,7 @@
             accessNums = new HashMap<Symbol,Integer>();
             accessSyms = new HashMap<Symbol,MethodSymbol[]>();
             accessConstrs = new HashMap<Symbol,MethodSymbol>();
+            accessConstrTags = List.nil();
             accessed = new ListBuffer<Symbol>();
             translate(cdef, (JCExpression)null);
             for (List<Symbol> l = accessed.toList(); l.nonEmpty(); l = l.tail)
@@ -3401,6 +3442,7 @@
             for (EnumMapping map : enumSwitchMap.values())
                 map.translate();
             checkConflicts(this.translated.toList());
+            checkAccessConstructorTags();
             translated = this.translated;
         } finally {
             // note that recursive invocations of this method fail hard
@@ -3420,6 +3462,7 @@
             accessNums = null;
             accessSyms = null;
             accessConstrs = null;
+            accessConstrTags = null;
             accessed = null;
             enumSwitchMap.clear();
         }