6881115: javac permits nested anno w/o mandatory attrs => IncompleteAnnotationException
authormcimadamore
Thu, 05 Aug 2010 09:44:54 +0100
changeset 6342 228b73431edb
parent 6162 9d0f96b4befa
child 6343 655c0db5643b
6881115: javac permits nested anno w/o mandatory attrs => IncompleteAnnotationException Summary: default annotation value is not attributed Reviewed-by: jjg, darcy
langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java
langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
langtools/test/tools/javac/annotations/6881115/T6881115.java
langtools/test/tools/javac/annotations/6881115/T6881115.out
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Aug 02 16:29:54 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Aug 05 09:44:54 2010 +0100
@@ -675,24 +675,32 @@
 
             // Check that type parameters are well-formed.
             chk.validate(tree.typarams, localEnv);
-            if ((owner.flags() & ANNOTATION) != 0 &&
-                tree.typarams.nonEmpty())
-                log.error(tree.typarams.head.pos(),
-                          "intf.annotation.members.cant.have.type.params");
 
             // Check that result type is well-formed.
             chk.validate(tree.restype, localEnv);
-            if ((owner.flags() & ANNOTATION) != 0)
+
+            // annotation method checks
+            if ((owner.flags() & ANNOTATION) != 0) {
+                // annotation method cannot have throws clause
+                if (tree.thrown.nonEmpty()) {
+                    log.error(tree.thrown.head.pos(),
+                            "throws.not.allowed.in.intf.annotation");
+                }
+                // annotation method cannot declare type-parameters
+                if (tree.typarams.nonEmpty()) {
+                    log.error(tree.typarams.head.pos(),
+                            "intf.annotation.members.cant.have.type.params");
+                }
+                // validate annotation method's return type (could be an annotation type)
                 chk.validateAnnotationType(tree.restype);
-
-            if ((owner.flags() & ANNOTATION) != 0)
+                // ensure that annotation method does not clash with members of Object/Annotation
                 chk.validateAnnotationMethod(tree.pos(), m);
 
-            // Check that all exceptions mentioned in the throws clause extend
-            // java.lang.Throwable.
-            if ((owner.flags() & ANNOTATION) != 0 && tree.thrown.nonEmpty())
-                log.error(tree.thrown.head.pos(),
-                          "throws.not.allowed.in.intf.annotation");
+                // if default value is an annotation, check it is a well-formed
+                // annotation value (e.g. no duplicate values, no missing values, etc.)
+                chk.validateAnnotationDefaultValue(tree.defaultValue);
+            }
+
             for (List<JCExpression> l = tree.thrown; l.nonEmpty(); l = l.tail)
                 chk.checkType(l.head.pos(), l.head.type, syms.throwableType);
 
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Aug 02 16:29:54 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Thu Aug 05 09:44:54 2010 +0100
@@ -1929,6 +1929,23 @@
  * Check annotations
  **************************************************************************/
 
+    /**
+     * Validate annotations in default values
+     */
+    void validateAnnotationDefaultValue(JCTree defaultValue) {
+        class DefaultValueValidator extends TreeScanner {
+            @Override
+            public void visitAnnotation(JCAnnotation tree) {
+                super.visitAnnotation(tree);
+                validateAnnotation(tree);
+            }
+        }
+        // defaultValue may be null if an error occurred, so don't bother validating it
+        if (defaultValue != null) {
+            defaultValue.accept(new DefaultValueValidator());
+        }
+    }
+
     /** Annotation types are restricted to primitives, String, an
      *  enum, an annotation, Class, Class<?>, Class<? extends
      *  Anything>, arrays of the preceding.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/6881115/T6881115.java	Thu Aug 05 09:44:54 2010 +0100
@@ -0,0 +1,18 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug     6881115
+ * @summary javac permits nested anno w/o mandatory attrs => IncompleteAnnotationException
+ * @author  mcimadamore
+ * @compile/fail/ref=T6881115.out -XDrawDiagnostics T6881115.java
+ */
+
+@interface A {
+    B b() default @B(b2 = 1, b2 = 2);
+    B[] b_arr() default {@B(), @B(b2 = 1, b2 = 2)};
+}
+@interface B {
+    String b1();
+    int b2();
+}
+@A
+class T6881115 {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/6881115/T6881115.out	Thu Aug 05 09:44:54 2010 +0100
@@ -0,0 +1,6 @@
+T6881115.java:10:30: compiler.err.duplicate.annotation.member.value: b2, B
+T6881115.java:10:19: compiler.err.annotation.missing.default.value: B, b1
+T6881115.java:11:26: compiler.err.annotation.missing.default.value: B, b1
+T6881115.java:11:43: compiler.err.duplicate.annotation.member.value: b2, B
+T6881115.java:11:32: compiler.err.annotation.missing.default.value: B, b1
+5 errors