8006345: Report Synthesized Parameters in java.lang.reflect.Parameter API

8006896: ClassReader doesn't see MethodParameters attr for method of anon inner class
8007098: Output Synthesized Parameters to MethodParameters Attributes

Correctly report synthesized and mandated parameters

Reviewed-by: mcimadamore, jjg
This commit is contained in:
Eric Mccorkle 2013-02-13 17:04:21 +00:00 committed by Maurizio Cimadamore
parent 14c0c8eed8
commit 8ccde1a96e
7 changed files with 93 additions and 36 deletions

View file

@ -56,7 +56,7 @@ public class AccessFlags {
public static final int ACC_SYNTHETIC = 0x1000; // class, inner, field, method public static final int ACC_SYNTHETIC = 0x1000; // class, inner, field, method
public static final int ACC_ANNOTATION = 0x2000; // class, inner public static final int ACC_ANNOTATION = 0x2000; // class, inner
public static final int ACC_ENUM = 0x4000; // class, inner, field public static final int ACC_ENUM = 0x4000; // class, inner, field
public static final int ACC_MODULE = 0x8000; // class, inner, field, method public static final int ACC_MANDATED = 0x8000; // class, inner, field, method
public static enum Kind { Class, InnerClass, Field, Method}; public static enum Kind { Class, InnerClass, Field, Method};
@ -81,12 +81,12 @@ public class AccessFlags {
} }
private static final int[] classModifiers = { private static final int[] classModifiers = {
ACC_PUBLIC, ACC_FINAL, ACC_ABSTRACT, ACC_MODULE ACC_PUBLIC, ACC_FINAL, ACC_ABSTRACT
}; };
private static final int[] classFlags = { private static final int[] classFlags = {
ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_INTERFACE, ACC_ABSTRACT, ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_INTERFACE, ACC_ABSTRACT,
ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, ACC_MODULE ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM
}; };
public Set<String> getClassModifiers() { public Set<String> getClassModifiers() {
@ -100,12 +100,12 @@ public class AccessFlags {
private static final int[] innerClassModifiers = { private static final int[] innerClassModifiers = {
ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
ACC_ABSTRACT, ACC_MODULE ACC_ABSTRACT
}; };
private static final int[] innerClassFlags = { private static final int[] innerClassFlags = {
ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_SUPER, ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_SUPER,
ACC_INTERFACE, ACC_ABSTRACT, ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, ACC_MODULE ACC_INTERFACE, ACC_ABSTRACT, ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM
}; };
public Set<String> getInnerClassModifiers() { public Set<String> getInnerClassModifiers() {
@ -119,12 +119,12 @@ public class AccessFlags {
private static final int[] fieldModifiers = { private static final int[] fieldModifiers = {
ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
ACC_VOLATILE, ACC_TRANSIENT, ACC_MODULE ACC_VOLATILE, ACC_TRANSIENT
}; };
private static final int[] fieldFlags = { private static final int[] fieldFlags = {
ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
ACC_VOLATILE, ACC_TRANSIENT, ACC_SYNTHETIC, ACC_ENUM, ACC_MODULE ACC_VOLATILE, ACC_TRANSIENT, ACC_SYNTHETIC, ACC_ENUM
}; };
public Set<String> getFieldModifiers() { public Set<String> getFieldModifiers() {
@ -137,13 +137,13 @@ public class AccessFlags {
private static final int[] methodModifiers = { private static final int[] methodModifiers = {
ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT, ACC_STRICT, ACC_MODULE ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT, ACC_STRICT
}; };
private static final int[] methodFlags = { private static final int[] methodFlags = {
ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
ACC_SYNCHRONIZED, ACC_BRIDGE, ACC_VARARGS, ACC_NATIVE, ACC_ABSTRACT, ACC_SYNCHRONIZED, ACC_BRIDGE, ACC_VARARGS, ACC_NATIVE, ACC_ABSTRACT,
ACC_STRICT, ACC_SYNTHETIC, ACC_MODULE ACC_STRICT, ACC_SYNTHETIC
}; };
public Set<String> getMethodModifiers() { public Set<String> getMethodModifiers() {
@ -208,8 +208,8 @@ public class AccessFlags {
return "abstract"; return "abstract";
case ACC_STRICT: case ACC_STRICT:
return "strictfp"; return "strictfp";
case ACC_MODULE: case ACC_MANDATED:
return "module"; return "mandated";
default: default:
return null; return null;
} }
@ -247,8 +247,8 @@ public class AccessFlags {
return "ACC_ANNOTATION"; return "ACC_ANNOTATION";
case ACC_ENUM: case ACC_ENUM:
return "ACC_ENUM"; return "ACC_ENUM";
case ACC_MODULE: case ACC_MANDATED:
return "ACC_MODULE"; return "ACC_MANDATED";
default: default:
return null; return null;
} }

View file

@ -74,6 +74,7 @@ public class Flags {
if ((mask&DEPRECATED) != 0) flags.add(Flag.DEPRECATED); if ((mask&DEPRECATED) != 0) flags.add(Flag.DEPRECATED);
if ((mask&HASINIT) != 0) flags.add(Flag.HASINIT); if ((mask&HASINIT) != 0) flags.add(Flag.HASINIT);
if ((mask&ENUM) != 0) flags.add(Flag.ENUM); if ((mask&ENUM) != 0) flags.add(Flag.ENUM);
if ((mask&MANDATED) != 0) flags.add(Flag.MANDATED);
if ((mask&IPROXY) != 0) flags.add(Flag.IPROXY); if ((mask&IPROXY) != 0) flags.add(Flag.IPROXY);
if ((mask&NOOUTERTHIS) != 0) flags.add(Flag.NOOUTERTHIS); if ((mask&NOOUTERTHIS) != 0) flags.add(Flag.NOOUTERTHIS);
if ((mask&EXISTS) != 0) flags.add(Flag.EXISTS); if ((mask&EXISTS) != 0) flags.add(Flag.EXISTS);
@ -114,6 +115,9 @@ public class Flags {
* classfile v49.0. */ * classfile v49.0. */
public static final int ENUM = 1<<14; public static final int ENUM = 1<<14;
/** Added in SE8, represents constructs implicitly declared in source. */
public static final int MANDATED = 1<<15;
public static final int StandardFlags = 0x0fff; public static final int StandardFlags = 0x0fff;
public static final int ModifierFlags = StandardFlags & ~INTERFACE; public static final int ModifierFlags = StandardFlags & ~INTERFACE;
@ -342,6 +346,7 @@ public class Flags {
DEPRECATED("deprecated"), DEPRECATED("deprecated"),
HASINIT("hasinit"), HASINIT("hasinit"),
ENUM("enum"), ENUM("enum"),
MANDATED("mandated"),
IPROXY("iproxy"), IPROXY("iproxy"),
NOOUTERTHIS("noouterthis"), NOOUTERTHIS("noouterthis"),
EXISTS("exists"), EXISTS("exists"),

View file

@ -217,6 +217,14 @@ public abstract class Symbol implements Element {
return (flags() & INTERFACE) != 0; return (flags() & INTERFACE) != 0;
} }
public boolean isPrivate() {
return (flags_field & Flags.AccessFlags) == PRIVATE;
}
public boolean isEnum() {
return (flags() & ENUM) != 0;
}
/** Is this symbol declared (directly or indirectly) local /** Is this symbol declared (directly or indirectly) local
* to a method or variable initializer? * to a method or variable initializer?
* Also includes fields of inner classes which are in * Also includes fields of inner classes which are in
@ -1082,6 +1090,9 @@ public abstract class Symbol implements Element {
/** The code of the method. */ /** The code of the method. */
public Code code = null; public Code code = null;
/** The extra (synthetic/mandated) parameters of the method. */
public List<VarSymbol> extraParams = List.nil();
/** The parameters of the method. */ /** The parameters of the method. */
public List<VarSymbol> params = null; public List<VarSymbol> params = null;

View file

@ -1445,24 +1445,51 @@ public class Lower extends TreeTranslator {
return result; return result;
} }
/** Definition for this$n field. private VarSymbol makeOuterThisVarSymbol(Symbol owner, long flags) {
* @param pos The source code position of the definition.
* @param owner The class in which the definition goes.
*/
JCVariableDecl outerThisDef(int pos, Symbol owner) {
long flags = FINAL | SYNTHETIC;
if (owner.kind == TYP && if (owner.kind == TYP &&
target.usePrivateSyntheticFields()) target.usePrivateSyntheticFields())
flags |= PRIVATE; flags |= PRIVATE;
Type target = types.erasure(owner.enclClass().type.getEnclosingType()); Type target = types.erasure(owner.enclClass().type.getEnclosingType());
VarSymbol outerThis = new VarSymbol( VarSymbol outerThis =
flags, outerThisName(target, owner), target, owner); new VarSymbol(flags, outerThisName(target, owner), target, owner);
outerThisStack = outerThisStack.prepend(outerThis); outerThisStack = outerThisStack.prepend(outerThis);
JCVariableDecl vd = make.at(pos).VarDef(outerThis, null); return outerThis;
}
private JCVariableDecl makeOuterThisVarDecl(int pos, VarSymbol sym) {
JCVariableDecl vd = make.at(pos).VarDef(sym, null);
vd.vartype = access(vd.vartype); vd.vartype = access(vd.vartype);
return vd; return vd;
} }
/** Definition for this$n field.
* @param pos The source code position of the definition.
* @param owner The method in which the definition goes.
*/
JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
ClassSymbol c = owner.enclClass();
boolean isMandated =
// Anonymous constructors
(owner.isConstructor() && owner.isAnonymous()) ||
// Constructors of non-private inner member classes
(owner.isConstructor() && c.isInner() &&
!c.isPrivate() && !c.isStatic());
long flags =
FINAL | (isMandated ? MANDATED : SYNTHETIC);
VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
owner.extraParams = owner.extraParams.prepend(outerThis);
return makeOuterThisVarDecl(pos, outerThis);
}
/** Definition for this$n field.
* @param pos The source code position of the definition.
* @param owner The class in which the definition goes.
*/
JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC);
return makeOuterThisVarDecl(pos, outerThis);
}
/** Return a list of trees that load the free variables in given list, /** Return a list of trees that load the free variables in given list,
* in reverse order. * in reverse order.
* @param pos The source code position to be used for the trees. * @param pos The source code position to be used for the trees.
@ -2568,7 +2595,6 @@ public class Lower extends TreeTranslator {
"enum" + target.syntheticNameChar() + "name"), "enum" + target.syntheticNameChar() + "name"),
syms.stringType, tree.sym); syms.stringType, tree.sym);
nameParam.mods.flags |= SYNTHETIC; nameParam.sym.flags_field |= SYNTHETIC; nameParam.mods.flags |= SYNTHETIC; nameParam.sym.flags_field |= SYNTHETIC;
JCVariableDecl ordParam = make. JCVariableDecl ordParam = make.
Param(names.fromString(target.syntheticNameChar() + Param(names.fromString(target.syntheticNameChar() +
"enum" + target.syntheticNameChar() + "enum" + target.syntheticNameChar() +
@ -2579,6 +2605,8 @@ public class Lower extends TreeTranslator {
tree.params = tree.params.prepend(ordParam).prepend(nameParam); tree.params = tree.params.prepend(ordParam).prepend(nameParam);
MethodSymbol m = tree.sym; MethodSymbol m = tree.sym;
m.extraParams = m.extraParams.prepend(ordParam.sym);
m.extraParams = m.extraParams.prepend(nameParam.sym);
Type olderasure = m.erasure(types); Type olderasure = m.erasure(types);
m.erasure_field = new MethodType( m.erasure_field = new MethodType(
olderasure.getParameterTypes().prepend(syms.intType).prepend(syms.stringType), olderasure.getParameterTypes().prepend(syms.intType).prepend(syms.stringType),

View file

@ -465,7 +465,8 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
names.valueOf, names.valueOf,
make.Type(tree.sym.type), make.Type(tree.sym.type),
List.<JCTypeParameter>nil(), List.<JCTypeParameter>nil(),
List.of(make.VarDef(make.Modifiers(Flags.PARAMETER), List.of(make.VarDef(make.Modifiers(Flags.PARAMETER |
Flags.MANDATED),
names.fromString("name"), names.fromString("name"),
make.Type(syms.stringType), null)), make.Type(syms.stringType), null)),
List.<JCExpression>nil(), // thrown List.<JCExpression>nil(), // thrown

View file

@ -728,14 +728,24 @@ public class ClassWriter extends ClassFile {
* Write method parameter names attribute. * Write method parameter names attribute.
*/ */
int writeMethodParametersAttr(MethodSymbol m) { int writeMethodParametersAttr(MethodSymbol m) {
if (m.params != null && 0 != m.params.length()) { MethodType ty = m.externalType(types).asMethodType();
int attrIndex = writeAttr(names.MethodParameters); final int allparams = ty.argtypes.size();
databuf.appendByte(m.params.length()); if (m.params != null && allparams != 0) {
final int attrIndex = writeAttr(names.MethodParameters);
databuf.appendByte(allparams);
// Write extra parameters first
for (VarSymbol s : m.extraParams) {
final int flags =
((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
((int) m.flags() & SYNTHETIC);
databuf.appendChar(pool.put(s.name));
databuf.appendInt(flags);
}
// Now write the real parameters
for (VarSymbol s : m.params) { for (VarSymbol s : m.params) {
// TODO: expand to cover synthesized, once we figure out final int flags =
// how to represent that. ((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
final int flags = (int) s.flags() & (FINAL | SYNTHETIC); ((int) m.flags() & SYNTHETIC);
// output parameter info
databuf.appendChar(pool.put(s.name)); databuf.appendChar(pool.put(s.name));
databuf.appendInt(flags); databuf.appendInt(flags);
} }

View file

@ -400,12 +400,14 @@ public class AttributeWriter extends BasicWriter
println(header); println(header);
for (MethodParameters_attribute.Entry entry : for (MethodParameters_attribute.Entry entry :
attr.method_parameter_table) { attr.method_parameter_table) {
String namestr =
entry.name_index != 0 ?
constantWriter.stringValue(entry.name_index) : "<no name>";
String flagstr = String flagstr =
(0 != (entry.flags & ACC_FINAL) ? " final" : "") + (0 != (entry.flags & ACC_FINAL) ? "final " : "") +
(0 != (entry.flags & ACC_SYNTHETIC) ? " synthetic" : ""); (0 != (entry.flags & ACC_MANDATED) ? "mandated " : "") +
println(String.format(format, (0 != (entry.flags & ACC_SYNTHETIC) ? "synthetic" : "");
constantWriter.stringValue(entry.name_index), println(String.format(format, namestr, flagstr));
flagstr));
} }
indent(-1); indent(-1);
return null; return null;