8006345: Report Synthesized Parameters in java.lang.reflect.Parameter API
authormcimadamore
Wed, 13 Feb 2013 17:04:21 +0000
changeset 15720 e61b2f7a5148
parent 15719 6b64cf96346b
child 15721 47ef0371f576
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 Summary: Correctly report synthesized and mandated parameters Reviewed-by: mcimadamore, jjg Contributed-by: eric.mccorkle@oracle.com
langtools/src/share/classes/com/sun/tools/classfile/AccessFlags.java
langtools/src/share/classes/com/sun/tools/javac/code/Flags.java
langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java
langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java
langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java
langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java
--- a/langtools/src/share/classes/com/sun/tools/classfile/AccessFlags.java	Wed Feb 13 10:33:13 2013 +0100
+++ b/langtools/src/share/classes/com/sun/tools/classfile/AccessFlags.java	Wed Feb 13 17:04:21 2013 +0000
@@ -56,7 +56,7 @@
     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_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};
 
@@ -81,12 +81,12 @@
     }
 
     private static final int[] classModifiers = {
-        ACC_PUBLIC, ACC_FINAL, ACC_ABSTRACT, ACC_MODULE
+        ACC_PUBLIC, ACC_FINAL, ACC_ABSTRACT
     };
 
     private static final int[] classFlags = {
         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() {
@@ -100,12 +100,12 @@
 
     private static final int[] innerClassModifiers = {
         ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
-        ACC_ABSTRACT, ACC_MODULE
+        ACC_ABSTRACT
     };
 
     private static final int[] innerClassFlags = {
         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() {
@@ -119,12 +119,12 @@
 
     private static final int[] fieldModifiers = {
         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 = {
         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() {
@@ -137,13 +137,13 @@
 
     private static final int[] methodModifiers = {
         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 = {
         ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
         ACC_SYNCHRONIZED, ACC_BRIDGE, ACC_VARARGS, ACC_NATIVE, ACC_ABSTRACT,
-        ACC_STRICT, ACC_SYNTHETIC, ACC_MODULE
+        ACC_STRICT, ACC_SYNTHETIC
     };
 
     public Set<String> getMethodModifiers() {
@@ -208,8 +208,8 @@
                 return "abstract";
             case ACC_STRICT:
                 return "strictfp";
-            case ACC_MODULE:
-                return "module";
+            case ACC_MANDATED:
+                return "mandated";
             default:
                 return null;
         }
@@ -247,8 +247,8 @@
             return "ACC_ANNOTATION";
         case ACC_ENUM:
             return "ACC_ENUM";
-        case ACC_MODULE:
-            return "ACC_MODULE";
+        case ACC_MANDATED:
+            return "ACC_MANDATED";
         default:
             return null;
         }
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java	Wed Feb 13 10:33:13 2013 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java	Wed Feb 13 17:04:21 2013 +0000
@@ -74,6 +74,7 @@
         if ((mask&DEPRECATED) != 0) flags.add(Flag.DEPRECATED);
         if ((mask&HASINIT) != 0) flags.add(Flag.HASINIT);
         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&NOOUTERTHIS) != 0) flags.add(Flag.NOOUTERTHIS);
         if ((mask&EXISTS) != 0) flags.add(Flag.EXISTS);
@@ -114,6 +115,9 @@
      *  classfile v49.0. */
     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 ModifierFlags = StandardFlags & ~INTERFACE;
 
@@ -342,6 +346,7 @@
         DEPRECATED("deprecated"),
         HASINIT("hasinit"),
         ENUM("enum"),
+        MANDATED("mandated"),
         IPROXY("iproxy"),
         NOOUTERTHIS("noouterthis"),
         EXISTS("exists"),
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java	Wed Feb 13 10:33:13 2013 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java	Wed Feb 13 17:04:21 2013 +0000
@@ -217,6 +217,14 @@
         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
      *  to a method or variable initializer?
      *  Also includes fields of inner classes which are in
@@ -1082,6 +1090,9 @@
         /** The code of the method. */
         public Code code = null;
 
+        /** The extra (synthetic/mandated) parameters of the method. */
+        public List<VarSymbol> extraParams = List.nil();
+
         /** The parameters of the method. */
         public List<VarSymbol> params = null;
 
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java	Wed Feb 13 10:33:13 2013 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java	Wed Feb 13 17:04:21 2013 +0000
@@ -1445,22 +1445,49 @@
         return result;
     }
 
+    private VarSymbol makeOuterThisVarSymbol(Symbol owner, long flags) {
+        if (owner.kind == TYP &&
+            target.usePrivateSyntheticFields())
+            flags |= PRIVATE;
+        Type target = types.erasure(owner.enclClass().type.getEnclosingType());
+        VarSymbol outerThis =
+            new VarSymbol(flags, outerThisName(target, owner), target, owner);
+        outerThisStack = outerThisStack.prepend(outerThis);
+        return outerThis;
+    }
+
+    private JCVariableDecl makeOuterThisVarDecl(int pos, VarSymbol sym) {
+        JCVariableDecl vd = make.at(pos).VarDef(sym, null);
+        vd.vartype = access(vd.vartype);
+        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, Symbol owner) {
-        long flags = FINAL | SYNTHETIC;
-        if (owner.kind == TYP &&
-            target.usePrivateSyntheticFields())
-            flags |= PRIVATE;
-        Type target = types.erasure(owner.enclClass().type.getEnclosingType());
-        VarSymbol outerThis = new VarSymbol(
-            flags, outerThisName(target, owner), target, owner);
-        outerThisStack = outerThisStack.prepend(outerThis);
-        JCVariableDecl vd = make.at(pos).VarDef(outerThis, null);
-        vd.vartype = access(vd.vartype);
-        return vd;
+    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,
@@ -2568,7 +2595,6 @@
                                        "enum" + target.syntheticNameChar() + "name"),
                       syms.stringType, tree.sym);
             nameParam.mods.flags |= SYNTHETIC; nameParam.sym.flags_field |= SYNTHETIC;
-
             JCVariableDecl ordParam = make.
                 Param(names.fromString(target.syntheticNameChar() +
                                        "enum" + target.syntheticNameChar() +
@@ -2579,6 +2605,8 @@
             tree.params = tree.params.prepend(ordParam).prepend(nameParam);
 
             MethodSymbol m = tree.sym;
+            m.extraParams = m.extraParams.prepend(ordParam.sym);
+            m.extraParams = m.extraParams.prepend(nameParam.sym);
             Type olderasure = m.erasure(types);
             m.erasure_field = new MethodType(
                 olderasure.getParameterTypes().prepend(syms.intType).prepend(syms.stringType),
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Wed Feb 13 10:33:13 2013 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Wed Feb 13 17:04:21 2013 +0000
@@ -465,7 +465,8 @@
                       names.valueOf,
                       make.Type(tree.sym.type),
                       List.<JCTypeParameter>nil(),
-                      List.of(make.VarDef(make.Modifiers(Flags.PARAMETER),
+                      List.of(make.VarDef(make.Modifiers(Flags.PARAMETER |
+                                                         Flags.MANDATED),
                                             names.fromString("name"),
                                             make.Type(syms.stringType), null)),
                       List.<JCExpression>nil(), // thrown
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Wed Feb 13 10:33:13 2013 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Wed Feb 13 17:04:21 2013 +0000
@@ -728,14 +728,24 @@
      * Write method parameter names attribute.
      */
     int writeMethodParametersAttr(MethodSymbol m) {
-        if (m.params != null && 0 != m.params.length()) {
-            int attrIndex = writeAttr(names.MethodParameters);
-            databuf.appendByte(m.params.length());
+        MethodType ty = m.externalType(types).asMethodType();
+        final int allparams = ty.argtypes.size();
+        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) {
-                // TODO: expand to cover synthesized, once we figure out
-                // how to represent that.
-                final int flags = (int) s.flags() & (FINAL | SYNTHETIC);
-                // output parameter info
+                final int flags =
+                    ((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
+                    ((int) m.flags() & SYNTHETIC);
                 databuf.appendChar(pool.put(s.name));
                 databuf.appendInt(flags);
             }
--- a/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java	Wed Feb 13 10:33:13 2013 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java	Wed Feb 13 17:04:21 2013 +0000
@@ -400,12 +400,14 @@
         println(header);
         for (MethodParameters_attribute.Entry entry :
                  attr.method_parameter_table) {
+            String namestr =
+                entry.name_index != 0 ?
+                constantWriter.stringValue(entry.name_index) : "<no name>";
             String flagstr =
-                (0 != (entry.flags & ACC_FINAL) ? " final" : "") +
-                (0 != (entry.flags & ACC_SYNTHETIC) ? " synthetic" : "");
-            println(String.format(format,
-                                  constantWriter.stringValue(entry.name_index),
-                                  flagstr));
+                (0 != (entry.flags & ACC_FINAL) ? "final " : "") +
+                (0 != (entry.flags & ACC_MANDATED) ? "mandated " : "") +
+                (0 != (entry.flags & ACC_SYNTHETIC) ? "synthetic" : "");
+            println(String.format(format, namestr, flagstr));
         }
         indent(-1);
         return null;