changeset 2649:cb7e7928902f

8029012: parameter_index for type annotation not updated after outer.this added Summary: Fix javac's handling of type annotations when synthetic parameters are added Reviewed-by: jjg, mcimadamore
author emc
date Mon, 24 Nov 2014 12:49:30 -0500
parents 9e80ab1dad9e
children 272300c8b557
files src/share/classes/com/sun/tools/javac/comp/Lower.java test/tools/javac/annotations/typeAnnotations/classfile/ClassfileInspector.java test/tools/javac/annotations/typeAnnotations/classfile/SyntheticParameters.java test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java
diffstat 4 files changed, 1100 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/Lower.java	Thu Nov 20 14:05:39 2014 -0800
+++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java	Mon Nov 24 12:49:30 2014 -0500
@@ -2716,9 +2716,10 @@
                       syms.intType, tree.sym);
             ordParam.mods.flags |= SYNTHETIC; ordParam.sym.flags_field |= SYNTHETIC;
 
+            MethodSymbol m = tree.sym;
             tree.params = tree.params.prepend(ordParam).prepend(nameParam);
-
-            MethodSymbol m = tree.sym;
+            incrementParamTypeAnnoIndexes(m, 2);
+
             m.extraParams = m.extraParams.prepend(ordParam.sym);
             m.extraParams = m.extraParams.prepend(nameParam.sym);
             Type olderasure = m.erasure(types);
@@ -2741,6 +2742,17 @@
         }
     }
     //where
+    private void incrementParamTypeAnnoIndexes(MethodSymbol m,
+                                               int amount) {
+        for (final Attribute.TypeCompound anno : m.getRawTypeAttributes()) {
+            // Increment the parameter_index of any existing formal
+            // parameter annotations.
+            if (anno.position.type == TargetType.METHOD_FORMAL_PARAMETER) {
+                anno.position.parameter_index += amount;
+            }
+        }
+    }
+
     private void visitMethodDefInternal(JCMethodDecl tree) {
         if (tree.name == names.init &&
             (currentClass.isInner() || currentClass.isLocal())) {
@@ -2771,8 +2783,10 @@
             // Add this$n (if needed) in front of and free variables behind
             // constructor parameter list.
             tree.params = tree.params.appendList(fvdefs);
-            if (currentClass.hasOuterInstance())
+            if (currentClass.hasOuterInstance()) {
                 tree.params = tree.params.prepend(otdef);
+                incrementParamTypeAnnoIndexes(m, 1);
+            }
 
             // If this is an initial constructor, i.e., it does not start with
             // this(...), insert initializers for this$n and proxies
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileInspector.java	Mon Nov 24 12:49:30 2014 -0500
@@ -0,0 +1,950 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.annotation.*;
+import java.io.*;
+import java.net.URL;
+import java.util.List;
+
+import com.sun.tools.classfile.*;
+
+/**
+ * A class providing utilities for writing tests that inspect class
+ * files directly, looking for specific type annotations.
+ *
+ * Note: this framework does not currently handle repeating
+ * annotations.
+ */
+public class ClassfileInspector {
+
+    /**
+     * A group of expected annotations to be found in a given class.
+     * If the class name is null, then the template will be applied to
+     * every class.
+     */
+    public static class Expected {
+        /**
+         * The name of the class.  If {@code null} this template will
+         * apply to every class; otherwise, it will only be applied to
+         * the named class.
+         */
+        public final String classname;
+
+        /**
+         * The expected class annotations.  These will be checked
+         * against the class' attributes.
+         */
+        public final ExpectedTypeAnnotation[] classAnnos;
+
+        /**
+         * The expected method annotations.  These will be checked
+         * against all methods in the class.
+         */
+        public final ExpectedMethodTypeAnnotation[] methodAnnos;
+
+        /**
+         * The expected field annotations.  These will be checked
+         * against all fields in the class.
+         */
+        public final ExpectedFieldTypeAnnotation[] fieldAnnos;
+
+        /**
+         * Create an {@code Expected} from its components.
+         *
+         * @param classname The name of the class to match, or {@code
+         *                  null} for all classes.
+         * @param classAnnos The expected class annotations.
+         * @param methodAnnos The expected method annotations.
+         * @param fieldAnnos The expected field annotations.
+         */
+        public Expected(String classname,
+                        ExpectedTypeAnnotation[] classAnnos,
+                        ExpectedMethodTypeAnnotation[] methodAnnos,
+                        ExpectedFieldTypeAnnotation[] fieldAnnos) {
+            this.classname = classname;
+            this.classAnnos = classAnnos;
+            this.methodAnnos = methodAnnos;
+            this.fieldAnnos = fieldAnnos;
+        }
+
+        public String toString() {
+            final StringBuilder sb = new StringBuilder();
+            final String newline = System.lineSeparator();
+            sb.append("Expected on class ").append(classname);
+            if (null != classAnnos) {
+                sb.append(newline).append("Class annotations:").append(newline);
+                for(ExpectedTypeAnnotation anno : classAnnos) {
+                    sb.append(anno).append(newline);
+                }
+            }
+            if (null != methodAnnos) {
+                sb.append(newline).append("Method annotations:").append(newline);
+                for(ExpectedTypeAnnotation anno : methodAnnos) {
+                    sb.append(anno).append(newline);
+                }
+            }
+            if (null != fieldAnnos) {
+                sb.append(newline).append("Field annotations:").append(newline);
+                for(ExpectedTypeAnnotation anno : fieldAnnos) {
+                    sb.append(anno).append(newline);
+                }
+            }
+            return sb.toString();
+        }
+
+        /**
+         * See if this template applies to a class.
+         *
+         * @param classname The classname to check.
+         * @return Whether or not this template should apply.
+         */
+        public boolean matchClassName(String classname) {
+            return this.classname == null || this.classname.equals(classname);
+        }
+
+        /**
+         * After applying the template to all classes, check to see if
+         * any of the expected annotations weren't matched.
+         *
+         * @return The number of missed matches.
+         */
+        public int check() {
+            int count = 0;
+            if (classAnnos != null) {
+                for(ExpectedTypeAnnotation expected : classAnnos) {
+                    if (!expected.check()) {
+                        count++;
+                    }
+                }
+            }
+            if (methodAnnos != null) {
+                for(ExpectedMethodTypeAnnotation expected : methodAnnos) {
+                    if (!expected.check()) {
+                        count++;
+                    }
+                }
+            }
+            if (fieldAnnos != null) {
+                for(ExpectedFieldTypeAnnotation expected : fieldAnnos) {
+                    if (!expected.check()) {
+                        count++;
+                    }
+                }
+            }
+            return count;
+        }
+    }
+
+    /**
+     * An expected type annotation.  This is both a superclass for
+     * method and field type annotations, as well as a class for type
+     * annotations on a class.
+     */
+    public static class ExpectedTypeAnnotation {
+        private int count = 0;
+        protected final String expectedName;
+        protected final int expectedCount;
+        protected final TypeAnnotation.TargetType targetType;
+        protected final int bound_index;
+        protected final int parameter_index;
+        protected final int type_index;
+        protected final int exception_index;
+        protected final TypeAnnotation.Position.TypePathEntry[] typePath;
+        protected final boolean visibility;
+
+        /**
+         * Create an {@code ExpectedTypeAnnotation} from its
+         * components.  It is usually a better idea to use a {@code
+         * Builder} to do this.
+         *
+         * @param expectedName The expected annotation name.
+         * @param visibility Whether this annotation should be runtime-visible.
+         * @param expectedCount The number of annotations that should
+         *                      be seen.  If 0, this asserts that the
+         *                      described annotation is not present.
+         * @param targetType The expected target type.
+         * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}.
+         * @param parameter_index The expected parameter index, or
+         *                        {@code Integer.MIN_VALUE}.
+         * @param type_index The expected type index, or {@code Integer.MIN_VALUE}.
+         * @param exception_index The expected exception index, or
+         *                        {@code Integer.MIN_VALUE}.
+         * @param typePath The expected type path.
+         */
+        public ExpectedTypeAnnotation(String expectedName,
+                                      boolean visibility,
+                                      int expectedCount,
+                                      TypeAnnotation.TargetType targetType,
+                                      int bound_index,
+                                      int parameter_index,
+                                      int type_index,
+                                      int exception_index,
+                                      TypeAnnotation.Position.TypePathEntry... typePath) {
+            this.expectedName = expectedName;
+            this.visibility = visibility;
+            this.expectedCount = expectedCount;
+            this.targetType = targetType;
+            this.bound_index = bound_index;
+            this.parameter_index = parameter_index;
+            this.type_index = type_index;
+            this.exception_index = exception_index;
+            this.typePath = typePath;
+        }
+
+        public String toString() {
+            final StringBuilder sb = new StringBuilder();
+            sb.append("Expected ");
+            sb.append(expectedCount);
+            sb.append(" annotation ");
+            sb.append(expectedName);
+            sb.append(visibility ? ", runtime visibile " : ", runtime invisibile ");
+            sb.append(targetType);
+            sb.append(", bound_index = ");
+            sb.append(bound_index);
+            sb.append(", parameter_index = ");
+            sb.append(parameter_index);
+            sb.append(", type_index = ");
+            sb.append(type_index);
+            sb.append(", exception_index = ");
+            sb.append(exception_index);
+            sb.append(", type_path = [");
+            for(int i = 0; i < typePath.length; i++) {
+                if (i != 0) {
+                    sb.append(", ");
+                }
+                sb.append(typePath[i]);
+            }
+            sb.append("]");
+            return sb.toString();
+        }
+
+        /**
+         * See if this template matches the given visibility.
+         *
+         * @param Whether or not the annotation is visible at runtime.
+         * @return Whether or not this template matches the visibility.
+         */
+        public boolean matchVisibility(boolean visibility) {
+            return this.visibility == visibility;
+        }
+
+        /**
+         * Attempty to match this template against an annotation.  If
+         * it does match, then the match count for the template will
+         * be incremented.  Otherwise, nothing will be done.
+         *
+         * @param anno The annotation to attempt to match.
+         */
+        public void matchAnnotation(TypeAnnotation anno) {
+            boolean matches = true;
+
+            try {
+                matches = anno.constant_pool.getUTF8Info(anno.annotation.type_index).value.equals("L" + expectedName + ";");
+            } catch(Exception e) {
+                matches = false;
+            }
+
+            matches = matches && anno.position.type == targetType;
+            matches = matches && anno.position.bound_index == bound_index;
+            matches = matches && anno.position.parameter_index == parameter_index;
+            matches = matches && anno.position.type_index == type_index;
+            matches = matches && anno.position.exception_index == exception_index;
+            matches = matches && anno.position.location.size() == typePath.length;
+
+            if (matches) {
+                int i = 0;
+                for(TypeAnnotation.Position.TypePathEntry entry :
+                         anno.position.location) {
+                    matches = matches && typePath[i++].equals(entry);
+                }
+            }
+
+            if (matches) {
+                count++;
+            }
+        }
+
+        /**
+         * After all matching, check to see if the expected number of
+         * matches equals the actual number.  If not, then print a
+         * failure message and return {@code false}.
+         *
+         * @return Whether or not the expected number of matched
+         *         equals the actual number.
+         */
+        public boolean check() {
+            if (count != expectedCount) {
+                System.err.println(this + ", but saw " + count);
+                return false;
+            } else {
+                return true;
+            }
+        }
+
+        /**
+         * A builder class for creating {@code
+         * ExpectedTypeAnnotation}s in a more convenient fashion.  The
+         * constructor for {@code ExpectedTypeAnnotation} takes a
+         * large number of parameters (by necessity).  This class
+         * allows users to construct a {@code ExpectedTypeAnnotation}s
+         * using only the ones they need.
+         */
+        public static class Builder {
+            protected final String expectedName;
+            protected final int expectedCount;
+            protected final TypeAnnotation.TargetType targetType;
+            protected final boolean visibility;
+            protected int bound_index = Integer.MIN_VALUE;
+            protected int parameter_index = Integer.MIN_VALUE;
+            protected int type_index = Integer.MIN_VALUE;
+            protected int exception_index = Integer.MIN_VALUE;
+            protected TypeAnnotation.Position.TypePathEntry[] typePath =
+                new TypeAnnotation.Position.TypePathEntry[0];
+
+            /**
+             * Create a {@code Builder} from the mandatory parameters.
+             *
+             * @param expectedName The expected annotation name.
+             * @param targetType The expected target type.
+             * @param visibility Whether this annotation should be runtime-visible.
+             * @param expectedCount The number of annotations that should be seen.
+             */
+            public Builder(String expectedName,
+                           TypeAnnotation.TargetType targetType,
+                           boolean visibility,
+                           int expectedCount) {
+                this.expectedName = expectedName;
+                this.visibility = visibility;
+                this.expectedCount = expectedCount;
+                this.targetType = targetType;
+            }
+
+            /**
+             * Create an {@code ExpectedTypeAnnotation} from all
+             * parameters that have been provided.  The default values
+             * will be used for those that have not.
+             *
+             * @return The cretaed {@code ExpectedTypeAnnotation}.
+             */
+            public ExpectedTypeAnnotation build() {
+                return new ExpectedTypeAnnotation(expectedName, visibility,
+                                                  expectedCount, targetType,
+                                                  bound_index, parameter_index,
+                                                  type_index, exception_index,
+                                                  typePath);
+            }
+
+            /**
+             * Provide a bound index parameter.
+             *
+             * @param bound_index The bound_index value.
+             */
+            public Builder setBoundIndex(int bound_index) {
+                this.bound_index = bound_index;
+                return this;
+            }
+
+            /**
+             * Provide a parameter index parameter.
+             *
+             * @param bound_index The parameter_index value.
+             */
+            public Builder setParameterIndex(int parameter_index) {
+                this.parameter_index = parameter_index;
+                return this;
+            }
+
+            /**
+             * Provide a type index parameter.
+             *
+             * @param type_index The type_index value.
+             */
+            public Builder setTypeIndex(int type_index) {
+                this.type_index = type_index;
+                return this;
+            }
+
+            /**
+             * Provide an exception index parameter.
+             *
+             * @param exception_index The exception_index value.
+             */
+            public Builder setExceptionIndex(int exception_index) {
+                this.exception_index = exception_index;
+                return this;
+            }
+
+            /**
+             * Provide a type path parameter.
+             *
+             * @param typePath The type path value.
+             */
+            public Builder setTypePath(TypeAnnotation.Position.TypePathEntry[] typePath) {
+                this.typePath = typePath;
+                return this;
+            }
+        }
+    }
+
+    /**
+     * A type annotation found on a method.
+     */
+    public static class ExpectedMethodTypeAnnotation extends ExpectedTypeAnnotation {
+        private final String methodname;
+
+        /**
+         * Create an {@code ExpectedMethodTypeAnnotation} from its
+         * components.  It is usually a better idea to use a {@code
+         * Builder} to do this.
+         *
+         * @param methodname The expected method name.
+         * @param expectedName The expected annotation name.
+         * @param visibility Whether this annotation should be runtime-visible.
+         * @param expectedCount The number of annotations that should be seen.
+         * @param targetType The expected target type.
+         * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}.
+         * @param parameter_index The expected parameter index, or
+         *                        {@code Integer.MIN_VALUE}.
+         * @param type_index The expected type index, or {@code Integer.MIN_VALUE}.
+         * @param exception_index The expected exception index, or
+         *                        {@code Integer.MIN_VALUE}.
+         * @param typePath The expected type path.
+         */
+        public ExpectedMethodTypeAnnotation(String methodname,
+                                            String expectedName,
+                                            boolean visibility,
+                                            int expectedCount,
+                                            TypeAnnotation.TargetType targetType,
+                                            int bound_index,
+                                            int parameter_index,
+                                            int type_index,
+                                            int exception_index,
+                                            TypeAnnotation.Position.TypePathEntry... typePath) {
+            super(expectedName, visibility, expectedCount, targetType, bound_index,
+                  parameter_index, type_index, exception_index, typePath);
+            this.methodname = methodname;
+        }
+
+        public String toString() {
+            final StringBuilder sb = new StringBuilder();
+            sb.append("Expected ");
+            sb.append(expectedCount);
+            sb.append(" annotation ");
+            sb.append(expectedName);
+            sb.append(visibility ? ", runtime visibile " : ", runtime invisibile ");
+            sb.append(targetType);
+            sb.append(", bound_index = ");
+            sb.append(bound_index);
+            sb.append(", parameter_index = ");
+            sb.append(parameter_index);
+            sb.append(", type_index = ");
+            sb.append(type_index);
+            sb.append(", exception_index = ");
+            sb.append(exception_index);
+            sb.append(", type_path = [");
+            for(int i = 0; i < typePath.length; i++) {
+                if (i != 0) {
+                    sb.append(", ");
+                }
+                sb.append(typePath[i]);
+            }
+            sb.append("]");
+            sb.append(" on method ");
+            sb.append(methodname);
+            return sb.toString();
+        }
+
+        /**
+         * See if this template applies to a method.
+         *
+         * @param methodname The method name to check.
+         * @return Whether or not this template should apply.
+         */
+        public boolean matchMethodName(String methodname) {
+            return this.methodname.equals(methodname);
+        }
+
+        /**
+         * A builder class for creating {@code
+         * ExpectedMethodTypeAnnotation}s in a more convenient fashion.  The
+         * constructor for {@code ExpectedMethodTypeAnnotation} takes a
+         * large number of parameters (by necessity).  This class
+         * allows users to construct a {@code ExpectedMethodTypeAnnotation}s
+         * using only the ones they need.
+         */
+        public static class Builder extends ExpectedTypeAnnotation.Builder {
+            protected final String methodname;
+
+            /**
+             * Create a {@code Builder} from the mandatory parameters.
+             *
+             * @param methodname The expected method name.
+             * @param expectedName The expected annotation name.
+             * @param targetType The expected target type.
+             * @param visibility Whether this annotation should be runtime-visible.
+             * @param expectedCount The number of annotations that should be seen.
+             */
+            public Builder(String methodname,
+                           String expectedName,
+                           TypeAnnotation.TargetType targetType,
+                           boolean visibility,
+                           int expectedCount) {
+                super(expectedName, targetType, visibility, expectedCount);
+                this.methodname = methodname;
+            }
+
+            /**
+             * Create an {@code ExpectedMethodTypeAnnotation} from all
+             * parameters that have been provided.  The default values
+             * will be used for those that have not.
+             *
+             * @return The cretaed {@code ExpectedMethodTypeAnnotation}.
+             */
+            public ExpectedMethodTypeAnnotation build() {
+                return new ExpectedMethodTypeAnnotation(methodname, expectedName,
+                                                        visibility, expectedCount,
+                                                        targetType, bound_index,
+                                                        parameter_index, type_index,
+                                                        exception_index, typePath);
+            }
+        }
+    }
+
+    /**
+     * A type annotation found on a field.
+     */
+    public static class ExpectedFieldTypeAnnotation extends ExpectedTypeAnnotation {
+        private final String fieldname;
+
+        /**
+         * Create an {@code ExpectedFieldTypeAnnotation} from its
+         * components.  It is usually a better idea to use a {@code
+         * Builder} to do this.
+         *
+         * @param fieldname The expected field name.
+         * @param expectedName The expected annotation name.
+         * @param visibility Whether this annotation should be runtime-visible.
+         * @param expectedCount The number of annotations that should be seen.
+         * @param targetType The expected target type.
+         * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}.
+         * @param parameter_index The expected parameter index, or
+         *                        {@code Integer.MIN_VALUE}.
+         * @param type_index The expected type index, or {@code Integer.MIN_VALUE}.
+         * @param exception_index The expected exception index, or
+         *                        {@code Integer.MIN_VALUE}.
+         * @param typePath The expected type path.
+         */
+        public ExpectedFieldTypeAnnotation(String fieldname,
+                                           String expectedName,
+                                           boolean visibility,
+                                           int expectedCount,
+                                           TypeAnnotation.TargetType targetType,
+                                           int bound_index,
+                                           int parameter_index,
+                                           int type_index,
+                                           int exception_index,
+                                           TypeAnnotation.Position.TypePathEntry... typePath) {
+            super(expectedName, visibility, expectedCount, targetType, bound_index,
+                  parameter_index, type_index, exception_index, typePath);
+            this.fieldname = fieldname;
+        }
+
+        public String toString() {
+            final StringBuilder sb = new StringBuilder();
+            sb.append("Expected ").append(expectedCount)
+            .append(" annotation ").append(expectedName)
+            .append(visibility ? ", runtime visibile " : ", runtime invisibile ")
+            .append(targetType)
+            .append(", bound_index = ").append(bound_index)
+            .append(", parameter_index = ").append(parameter_index)
+            .append(", type_index = ").append(type_index)
+            .append(", exception_index = ").append(exception_index)
+            .append(", type_path = [");
+
+            for(int i = 0; i < typePath.length; i++) {
+                if (i != 0) {
+                    sb.append(", ");
+                }
+                sb.append(typePath[i]);
+            }
+            sb.append("]")
+            .append(" on field ").append(fieldname);
+            return sb.toString();
+        }
+
+        /**
+         * See if this template applies to a field.
+         *
+         * @param fieldname The field name to check.
+         * @return Whether or not this template should apply.
+         */
+        public boolean matchFieldName(String fieldname) {
+            return this.fieldname.equals(fieldname);
+        }
+
+        /**
+         * A builder class for creating {@code
+         * ExpectedFieldTypeAnnotation}s in a more convenient fashion.  The
+         * constructor for {@code ExpectedFieldTypeAnnotation} takes a
+         * large number of parameters (by necessity).  This class
+         * allows users to construct a {@code ExpectedFieldTypeAnnotation}s
+         * using only the ones they need.
+         */
+        public static class Builder extends ExpectedTypeAnnotation.Builder {
+            protected final String fieldname;
+
+            /**
+             * Create a {@code Builder} from the mandatory parameters.
+             *
+             * @param fieldname The expected field name.
+             * @param expectedName The expected annotation name.
+             * @param targetType The expected target type.
+             * @param visibility Whether this annotation should be runtime-visible.
+             * @param expectedCount The number of annotations that should be seen.
+             */
+            public Builder(String fieldname,
+                           String expectedName,
+                           TypeAnnotation.TargetType targetType,
+                           boolean visibility,
+                           int expectedCount) {
+                super(expectedName, targetType, visibility, expectedCount);
+                this.fieldname = fieldname;
+            }
+
+            /**
+             * Create an {@code ExpectedFieldTypeAnnotation} from all
+             * parameters that have been provided.  The default values
+             * will be used for those that have not.
+             *
+             * @return The cretaed {@code ExpectedFieldTypeAnnotation}.
+             */
+            public ExpectedFieldTypeAnnotation build() {
+                return new ExpectedFieldTypeAnnotation(fieldname, expectedName,
+                                                       visibility, expectedCount,
+                                                       targetType, bound_index,
+                                                       parameter_index, type_index,
+                                                       exception_index, typePath);
+            }
+        }
+    }
+
+    private void matchClassTypeAnnotation(ClassFile classfile,
+                                          ExpectedTypeAnnotation expected)
+        throws ConstantPoolException {
+        for(Attribute attr : classfile.attributes) {
+            attr.accept(typeAnnoMatcher, expected);
+        }
+    }
+
+    private void matchMethodTypeAnnotation(ClassFile classfile,
+                                           ExpectedMethodTypeAnnotation expected)
+        throws ConstantPoolException {
+        for(Method meth : classfile.methods) {
+            if (expected.matchMethodName(meth.getName(classfile.constant_pool))) {
+                for(Attribute attr : meth.attributes) {
+                    attr.accept(typeAnnoMatcher, expected);
+                }
+            }
+        }
+    }
+
+    private void matchFieldTypeAnnotation(ClassFile classfile,
+                                          ExpectedFieldTypeAnnotation expected)
+        throws ConstantPoolException {
+        for(Field field : classfile.fields) {
+            if (expected.matchFieldName(field.getName(classfile.constant_pool))) {
+                for(Attribute attr : field.attributes) {
+                    attr.accept(typeAnnoMatcher, expected);
+                }
+            }
+        }
+    }
+
+    private void matchClassTypeAnnotations(ClassFile classfile,
+                                           ExpectedTypeAnnotation[] expected)
+        throws ConstantPoolException {
+        for(ExpectedTypeAnnotation one : expected) {
+            matchClassTypeAnnotation(classfile, one);
+        }
+    }
+
+    private void matchMethodTypeAnnotations(ClassFile classfile,
+                                            ExpectedMethodTypeAnnotation[] expected)
+        throws ConstantPoolException {
+        for(ExpectedMethodTypeAnnotation one : expected) {
+            matchMethodTypeAnnotation(classfile, one);
+        }
+    }
+
+    private void matchFieldTypeAnnotations(ClassFile classfile,
+                                           ExpectedFieldTypeAnnotation[] expected)
+        throws ConstantPoolException {
+        for(ExpectedFieldTypeAnnotation one : expected) {
+            matchFieldTypeAnnotation(classfile, one);
+        }
+    }
+
+    /**
+     * Run a template on a single {@code ClassFile}.
+     *
+     * @param classfile The {@code ClassFile} on which to run tests.
+     * @param expected The expected annotation template.
+     */
+    public void run(ClassFile classfile,
+                    Expected... expected)
+            throws ConstantPoolException {
+        run(new ClassFile[] { classfile }, expected);
+    }
+
+    /**
+     * Run a template on multiple {@code ClassFile}s.
+     *
+     * @param classfile The {@code ClassFile}s on which to run tests.
+     * @param expected The expected annotation template.
+     */
+    public void run(ClassFile[] classfiles,
+                    Expected... expected)
+            throws ConstantPoolException {
+        for(ClassFile classfile : classfiles) {
+            for(Expected one : expected) {
+                if (one.matchClassName(classfile.getName())) {
+                    if (one.classAnnos != null)
+                        matchClassTypeAnnotations(classfile, one.classAnnos);
+                    if (one.methodAnnos != null)
+                        matchMethodTypeAnnotations(classfile, one.methodAnnos);
+                    if (one.fieldAnnos != null)
+                        matchFieldTypeAnnotations(classfile, one.fieldAnnos);
+                }
+            }
+        }
+        int count = 0;
+        for (Expected one : expected) {
+            count += one.check();
+        }
+
+        if (count != 0) {
+            throw new RuntimeException(count + " errors occurred in test");
+        }
+    }
+
+    /**
+     * Get a {@code ClassFile} from its file name.
+     *
+     * @param name The class' file name.
+     * @return The {@code ClassFile}
+     */
+    public static ClassFile getClassFile(String name)
+        throws IOException, ConstantPoolException {
+        final URL url = ClassfileInspector.class.getResource(name);
+        final InputStream in = url.openStream();
+        try {
+            return ClassFile.read(in);
+        } finally {
+            in.close();
+        }
+    }
+
+    private static final Attribute.Visitor<Void, ExpectedTypeAnnotation> typeAnnoMatcher =
+        new Attribute.Visitor<Void, ExpectedTypeAnnotation>() {
+
+        @Override
+        public Void visitBootstrapMethods(BootstrapMethods_attribute attr,
+                                          ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitDefault(DefaultAttribute attr,
+                                 ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitAnnotationDefault(AnnotationDefault_attribute attr,
+                                           ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr,
+                                             ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitCode(Code_attribute attr,
+                              ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitCompilationID(CompilationID_attribute attr,
+                                       ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitConstantValue(ConstantValue_attribute attr,
+                                       ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitDeprecated(Deprecated_attribute attr,
+                                    ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitEnclosingMethod(EnclosingMethod_attribute attr,
+                                         ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitExceptions(Exceptions_attribute attr,
+                                    ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitInnerClasses(InnerClasses_attribute attr,
+                                      ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitLineNumberTable(LineNumberTable_attribute attr,
+                                         ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitLocalVariableTable(LocalVariableTable_attribute attr,
+                                            ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr,
+                                                ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitMethodParameters(MethodParameters_attribute attr,
+                                          ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+            public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr,
+                                                       ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr,
+                                                     ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr,
+                                                            ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr,
+                                                              ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitSignature(Signature_attribute attr,
+                                   ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr,
+                                              ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitSourceFile(SourceFile_attribute attr,
+                                    ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitSourceID(SourceID_attribute attr,
+                                  ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitStackMap(StackMap_attribute attr,
+                                  ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitStackMapTable(StackMapTable_attribute attr,
+                                       ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitSynthetic(Synthetic_attribute attr,
+                                   ExpectedTypeAnnotation expected) {
+            return null;
+        }
+
+        @Override
+        public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr,
+                                                       ExpectedTypeAnnotation expected) {
+            if (expected.matchVisibility(true)) {
+                for(TypeAnnotation anno : attr.annotations) {
+                    expected.matchAnnotation(anno);
+                }
+            }
+
+            return null;
+        }
+
+        @Override
+        public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr,
+                                                         ExpectedTypeAnnotation expected) {
+            if (expected.matchVisibility(false)) {
+                for(TypeAnnotation anno : attr.annotations) {
+                    expected.matchAnnotation(anno);
+                }
+            }
+
+            return null;
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/annotations/typeAnnotations/classfile/SyntheticParameters.java	Mon Nov 24 12:49:30 2014 -0500
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test SyntheticParameters
+ * @summary Test generation of annotations on inner class parameters.
+ * @build ClassfileInspector
+ * @run main SyntheticParameters
+ */
+
+import java.io.*;
+import java.lang.annotation.*;
+
+import com.sun.tools.classfile.*;
+
+public class SyntheticParameters extends ClassfileInspector {
+
+    private static final String Inner_class = "SyntheticParameters$Inner.class";
+    private static final String Foo_class = "SyntheticParameters$Foo.class";
+    private static final Expected Inner_expected =
+        new Expected("SyntheticParameters$Inner",
+                     null,
+                     new ExpectedMethodTypeAnnotation[] {
+                         (ExpectedMethodTypeAnnotation)
+                         // Assert there is no annotation on the
+                         // this$0 parameter.
+                         new ExpectedMethodTypeAnnotation.Builder(
+                             "<init>",
+                             "A",
+                             TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
+                             false,
+                             0).setParameterIndex(0).build(),
+                         (ExpectedMethodTypeAnnotation)
+                         // Assert there is an annotation on the
+                         // first parameter.
+                         new ExpectedMethodTypeAnnotation.Builder(
+                             "<init>",
+                             "A",
+                             TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
+                             false,
+                             1).setParameterIndex(1).build(),
+                         (ExpectedMethodTypeAnnotation)
+                         new ExpectedMethodTypeAnnotation.Builder(
+                             "foo",
+                             "A",
+                             TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
+                             false,
+                             1).setParameterIndex(0).build(),
+                         (ExpectedMethodTypeAnnotation)
+                         new ExpectedMethodTypeAnnotation.Builder(
+                             "foo",
+                             "A",
+                             TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
+                             false,
+                             0).setParameterIndex(1).build()
+                     },
+                     null);
+    private static final Expected Foo_expected =
+        new Expected("SyntheticParameters$Foo",
+                     null,
+                     new ExpectedMethodTypeAnnotation[] {
+                         (ExpectedMethodTypeAnnotation)
+                         // Assert there is no annotation on the
+                         // $enum$name parameter.
+                         new ExpectedMethodTypeAnnotation.Builder(
+                             "<init>",
+                             "A",
+                             TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
+                             false,
+                             0).setParameterIndex(0).build(),
+                         (ExpectedMethodTypeAnnotation)
+                         // Assert there is no annotation on the
+                         // $enum$ordinal parameter.
+                         new ExpectedMethodTypeAnnotation.Builder(
+                             "<init>",
+                             "A",
+                             TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
+                             false,
+                             0).setParameterIndex(1).build(),
+                         (ExpectedMethodTypeAnnotation)
+                         // Assert there is an annotation on the
+                         // first parameter.
+                         new ExpectedMethodTypeAnnotation.Builder(
+                             "<init>",
+                             "A",
+                             TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
+                             false,
+                             1).setParameterIndex(2).build()
+                     },
+                     null);
+
+    public static void main(String... args) throws Exception {
+        new SyntheticParameters().run(
+            new ClassFile[] { getClassFile(Inner_class), getClassFile(Foo_class) },
+            new Expected[] { Inner_expected, Foo_expected });
+    }
+
+    public class Inner {
+        public Inner(@A int a) {}
+        public void foo(@A int a, int b) {}
+    }
+
+    public static enum Foo {
+        ONE(null);
+        Foo(@A Object a) {}
+    }
+}
+
+@Target({ElementType.TYPE_USE})
+@interface A {}
--- a/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java	Thu Nov 20 14:05:39 2014 -0800
+++ b/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java	Mon Nov 24 12:49:30 2014 -0500
@@ -46,7 +46,7 @@
     @TADescriptions({
         @TADescription(annotation = "TA", type = METHOD_RETURN, genericLocation = {1, 0}),
         @TADescription(annotation = "TB", type = METHOD_RETURN, genericLocation = {1, 0}),
-        @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
+        @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
     })
     @TestClass("Test$Inner")
     public String innerClass() {
@@ -61,7 +61,7 @@
         @TADescription(annotation = "TB", type = METHOD_RETURN, genericLocation = {1, 0}),
         @TADescription(annotation = "TC", type = METHOD_RECEIVER),
         @TADescription(annotation = "TD", type = METHOD_RETURN, genericLocation = {1, 0}),
-        @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
+        @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
     })
     @TestClass("Test$Inner")
     public String innerClass2() {
@@ -77,7 +77,7 @@
         @TADescription(annotation = "TC", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0}),
         @TADescription(annotation = "TD", type = METHOD_RECEIVER, genericLocation = {1, 0}),
         @TADescription(annotation = "TE", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0}),
-        @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
+        @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
     })
     @TestClass("Outer$Middle$Inner")
     public String innerClass3() {