--- 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();
}